串口实现不定长中断(空闲中断)
目录
串口实现不定长中断(空闲中断)
1、串口头文件
2、串口初始化配置
3、msp公用的一个函数这里有三个串口,都会调用msp先进行一个判断
4、对接收数组进行清空
5、中断服务函数--数据收发
1.空闲中断的触发机制:
6、重定向到串口1中
1、串口头文件
#include "sys.h"
#define UART1_RX_BUF_SIZE 128 //接收
#define UART1_TX_BUF_SIZE 64 //发送 发送可以小一些看使用的场景
//宏定义错误代码
#define UART_EOK 0
#define UART_ERROR 1
#define UART_ETIMEOUT 2 //数据超时
#define UART_EINVAL 3 //非法字符
void uart1_init(uint32_t baudrate);
void uart1_receiv_test(void);
uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE];
uint16_t uart1_rx_len = 0;
2、串口初始化配置
UART_HandleTypeDef uart1_handle = {0};
void uart1_init(uint32_t baudrate)
{
uart1_handle.Instance = USART1; //选择通用异步收发器
uart1_handle.Init.Baudrate = baudrate; //设置波特率
uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; //字长参数列表用的8位
uart1_handle.Init.StopBits = UART_STOPBITS_1; //停止位的数量
uart1_handle.Init.Parity = UART_PARITY_NONE; //奇偶奇偶校验,不过不准确所以不用
uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;//流控制
uart1_handle.Init.Mode = UART_MODE_TX_RX; //设置即使要收又要发
HAL_UART_Init(&uart1_handle);
}
3、msp公用的一个函数这里有三个串口,都会调用msp先进行一个判断
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
//由于是公共函数需要判断是哪个串口
if(huart->Instance == USART1)
{
//通用异步收发器使能
//串口时钟使能
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
//配置GPIO口
GPIO_InitTypeDef gpio_initstruct;
//配置TX
gpio_initstruct.Pin = GPIO_PIN_9; //选择PA9
gpio_initstruct.Mode = GPIO_MODE_AF_PP; //复用推完输出
gpio_initstruct.Pull = GPIO_PULLUP; //上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;//高速模式
HAL_GPIO_Init(&GPIOA,gpio_initstruct);
//配置RX
gpio_initstruct.Pin = GPIO_PIN_10; //选择PA9
gpio_initstruct.Mode = GPIO_MODE_AF_INPUT;//由数据手册stm32V10的GPIO配置要求而的
HAL_GPIO_Init(&GPIOA,gpio_initdstruct);
//NVIC配置
HAL_GPIO_EnableIRQ(USART1_IRQn); //使能中断
HAL_NVIC_SetPriority(USART1_IRQn,2,2); //设置中断优先级
//如何确定RNXE被置为1 __HAL_UART_ENABLE_IT()
__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);
__HAL_UART_ENABLE_IT(huart,UART_IT_IDLE); //空闲中断
}
}
4、对接收数组进行清空
void uart1_rx_clear(void)
{
memset(&uart1_rx_buf,0,sizeof(uart1_rx_buf));
uart1_rx_len = 0;
}
5、中断服务函数--数据收发
1.空闲中断的触发机制:
空闲中断是在监测到数据接收后(即串口的RXNE位被置位)开始检测,当总线上在一个字节对应的周期内未再有新的数据接收时,触发空闲中断IDLE位被硬件置1.
void USART1_IRQHandler(void)
{
uint8_t receive_data = 0;
//判断什么时候数据的收发 如何判断是否收到数据 看RXNE RDR接收数据寄存器内不为空 就会触发一个
中断就可以进行一个操作
//判断是否为RXNE触发的中断
//需要判断数组是否接收完,防止缓冲区被刷爆
if(__HAL_UART_GET_FLAG(&uart1_handle,UART_RX_RXNE) != RESET)
{
//需要判断数组是否接收完,防止缓冲区被刷爆
if(uart1_rx_len >= sizeof(uart1_rx_buf))
uart1_rx_len = 0;
//进行接收
//接收的位置,接受的数据,接收的长度,超时时间
HAL_UART_Receive(&uart1_handle,&receive_data,1,1000);
uart1_rx_buf[uart1_rx_len++] = receive_data;//接收到的数据保存到数组中
//需要判断数组是否接收完
//发出数据
}
if(__HAL_UART_GET_FLAG(&huart1_handle,UART_RX_IDLE) !=RESET)
{
printf("recv: %s\r\n",uart1_rx_buf);//直接打印
uart1_rx_clear(); //清空数组中的数据一边下一次接收,造成影响
__HAL_UART_CLEAR_IDLEFLAG(&uart1_handle);//对UART_FLAG_IDLE进行软件清零
}
}
6、重定向到串口1中
int fputc(int ch, FILE *f)
{
while((USART1-SR & 0x40) == 0)
USART1->DR = (uint8_t)ch;
return ch;
}