STM32有用串口接收中断+空闲中断.也有用DMA+空闲中断的,今天我先用串口接收中断+空闲中断原理就是每接收到一个字节产生一次接收中断,将接收的数据放进缓存区,当一包数据接收完会产生空闲中断,这是我们判断接收完成续上篇,这次不用点点点了,因为跟上篇配置一样,简单写个结构体#define RX_BUF_MAX_LEN 512 // 最大接收缓存字节数typedef struct{ uint8_t rx_buff[RX_BUF_MAX_LEN];//缓存区 uint8_t len; //接收长度 uint8_t flag; //用于判断是否接收完 1为接收完}USRAT_RX;再写个初始化(清空)结构体void Clear_Usart(USRAT_RX *usart_rx)//初始化(清空)串口结构体{ memset((uint8_t *)usart_rx, 0, sizeof(USRAT_RX));//全写0}把之前的回调函数注释了,感觉HAL库的回调函数并不好用,直接在中断里写吧void USART2_IRQHandler(void){ /* USER CODE BEGIN USART2_IRQn 0 */ if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE) != RESET)//产生接收中断 { HAL_UART_IRQHandler(&huart2); // 该函数会清空中断标志,取消中断使能,并间接调用回调函数,清除接收标志 // 收到数据,将其放入缓冲区 usart1_rx.rx_buff[usart1_rx.len++] = recv_buf; if(usart1_rx.len>RX_BUF_MAX_LEN){//防止刷爆串口缓存 usart1_rx.flag = 1; // 标记接收完成 } } if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET)//产生空闲中断(说明接收完) { __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清楚空闲中断标志(否则会一直不断进入中断) usart1_rx.flag = 1; // 标记接收完成 if(usart1_rx.len==0){//防止误入 usart1_rx.flag = 0; } } HAL_UART_Receive_IT(&huart2,&recv_buf,1); // 重新使能接收中断 /* USER CODE END USART2_IRQn 0 */}
注释已经很清楚了,我就不解释了,我们还要初始化串口结构体,打开接收中断和空闲中断Clear_Usart(&usart1_rx);//初始化串口结构体HAL_UART_Receive_IT(&huart2,&recv_buf,1);//使能串口接收中断__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 使能空闲中断在while(1)里添加判断函数if(usart1_rx.flag){//判断接收完成 printf("%s\r\n",usart1_rx.rx_buff);//打印出数据 if(strstr((const char *)usart1_rx.rx_buff, "LED_ON") != NULL){//如果匹配到数据LED_ON HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET); printf("Turn on the LED"); } else if(strstr((const char *)usart1_rx.rx_buff, "LED_OFF") != NULL){//如果匹配到数据LED_OFF HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); printf("Turn off the LED"); } else {//不匹配打印error printf("error\r\n"); } Clear_Usart(&usart1_rx);//清空串口结构体}
看效果
|