完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1、需求
1、收到数据,放入缓存 2、取出数据进行协议解析 2、问题 HAL库的接收函数,指定接收固定数长的数据。 //中断方式接收 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //非中断方式接收 HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); 按照常规思维,我们会有以下几个问题。 1、是不是一直要在主循环里面去调用这个函数,以免漏掉数据。 2、如果我的数据不是定长的,我该如何来接收这些数据呢? 3、解决 3.1、以前的解决方法 放在以前呢,我们是重写了HAL库的中断接收函数,直接在里面对DR寄存器进行操作,然后放在自己的缓冲区,相当于回到了以前非HAL库的那种操作方式。这种解决方式并没有什么不好,甚至会提升代码运行效率。但是这种方式,HAL库的优势并没有发挥出来,程序的一致性也没有得到体现。甚至在每一次cubeMX重新生成代码后,还需要手动去修改中断函数。 下面是以前我们团队大牛重写的中断接收函数。 /** * @brief void Uart_Fifo_IRQHandler(UART_HandleTypeDef *huart) * @auther MSA * @param UART_HandleTypeDef *huart * @note 使用Uart_Fifo时的中断处理函数 * @note 注意参考hal库HAL_UART_IRQHandler函数中关于错误标志的处理 */ uint8_t uc_ore_cnt = 0; //test void Uart_Fifo_IRQHandler(UART_FIFO_Typedef *st_uart_fifo_tx_p, UART_FIFO_Typedef *st_uart_fifo_rx_p) { //错误处理, //errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); //以上错误标志中ORE和FE在EIE使能的时候会产生中断,不清楚会一直进入中断 //错误中断标志使能位是EIE,不知道hal库的初始化是否会使能该中断,应该不会 //RXNE中断或者EIE中断使能后,ORE中断自动使能 if( (__HAL_UART_GET_IT(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_ORE) != RESET)&& ((__HAL_UART_GET_IT_SOURCE(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_RXNE) != RESET)||(__HAL_UART_GET_IT_SOURCE(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_ERR) != RESET)) ) { uc_ore_cnt++; __HAL_UART_CLEAR_IT(st_uart_fifo_tx_p->st_uart_handle_p, UART_CLEAR_OREF); } //发送中断的处理 if((__HAL_UART_GET_IT(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_TXE) != RESET) && (__HAL_UART_GET_IT_SOURCE(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_TXE) != RESET)) { if(st_uart_fifo_tx_p->uw_fifo_cnt) { --(st_uart_fifo_tx_p->uw_fifo_cnt); st_uart_fifo_tx_p->st_uart_handle_p->Instance->TDR = *(st_uart_fifo_tx_p->uc_fifo_addr_p + st_uart_fifo_tx_p->uw_fifo_read_index); if(++(st_uart_fifo_tx_p->uw_fifo_read_index) >= st_uart_fifo_tx_p->uw_fifo_size) { st_uart_fifo_tx_p->uw_fifo_read_index = 0; } } if(st_uart_fifo_tx_p->uw_fifo_cnt == 0) { /* Disable the UART Transmit Data Register Empty Interrupt */ __HAL_UART_DISABLE_IT(st_uart_fifo_tx_p->st_uart_handle_p, UART_IT_TXE); } } //接收中断处理 uint8_t ucData; if((__HAL_UART_GET_IT(st_uart_fifo_rx_p->st_uart_handle_p, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(st_uart_fifo_rx_p->st_uart_handle_p, UART_IT_RXNE) != RESET)) { ucData = (uint8_t)(st_uart_fifo_rx_p->st_uart_handle_p->Instance->RDR&0x01FF); if(((st_uart_fifo_rx_p->st_uart_handle_p->Instance->ISR) & 0x0000) == 0)//无错误 { /*buf满了则清除缓冲区*/ if(++(st_uart_fifo_rx_p->uw_fifo_cnt) > st_uart_fifo_rx_p->uw_fifo_size) { // st_uart_fifo_rx_p->uw_fifo_cnt = st_uart_fifo_rx_p->uw_fifo_size; //test st_uart_fifo_rx_p->uw_fifo_cnt = 0; //test st_uart_fifo_rx_p->uw_fifo_write_index = st_uart_fifo_rx_p->uw_fifo_read_index; st_uart_fifo_rx_p->uc_fifo_overflow = 1; } else { //增加一个接受回调函数 *(st_uart_fifo_rx_p->uc_fifo_addr_p + st_uart_fifo_rx_p->uw_fifo_write_index) = ucData; if(++(st_uart_fifo_rx_p->uw_fifo_write_index) >= st_uart_fifo_rx_p->uw_fifo_size) { st_uart_fifo_rx_p->uw_fifo_write_index = 0; } } }//接收到数据 MSA_UART_RxCpltCallback(ucData, st_uart_fifo_rx_p); } } 3.2、新的解决方法 一次项目机会,重新审视了以前的操作方式,觉得应该是有比较好的解决方案的。于是出现了下面这种方法。好处有以下几点。 1、不需要修改HAL库的基础函数 2、系统可移植性提高 3、不需要去研究寄存器,去判断串口接收错误 这种方式,是利用hal库的接收完成回调函数,当串口数据接收完成后会进入回调函数,我们只需要完善回调函数,就可以了。回调函数是个弱函数,类似于C++里面的虚函数。主要方法如下 1、利用HAL库中断接收方法接收一个数据。当这个数据接收完成后,会进入回调函数。 HAL_UART_Receive_IT(&huart1, &aRxBuffer, 1); 1 2、在回调函数里面,处理完数据后,重新调用上面这条语句。这样,只要有数据进来,中断就不停的接收数据,并放入自己定义的缓冲区。 //测试版本,没有判断是哪个串口收到的数据 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(++(st_uart1_rx_fifo.uw_fifo_cnt) > st_uart1_rx_fifo.uw_fifo_size) { st_uart1_rx_fifo.uw_fifo_cnt = st_uart1_rx_fifo.uw_fifo_size; //test st_uart1_rx_fifo.uw_fifo_cnt = 0; //test st_uart1_rx_fifo.uw_fifo_write_index = st_uart1_rx_fifo.uw_fifo_read_index; st_uart1_rx_fifo.uc_fifo_overflow = 1; } else { //增加一个接受回调函数 *(st_uart1_rx_fifo.uc_fifo_addr_p + st_uart1_rx_fifo.uw_fifo_write_index) = aRxBuffer; if(++(st_uart1_rx_fifo.uw_fifo_write_index) >= st_uart1_rx_fifo.uw_fifo_size) { st_uart1_rx_fifo.uw_fifo_write_index = 0; } } HAL_UART_Receive_IT(&huart1, &aRxBuffer, 1); } 4、总结 接收一个字节,然后利用接收完成回调函数,在回调函数里面处理完对应的数据后,继续接收一个字节。如此往复。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1649 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1566 浏览 1 评论
994 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
694 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1613 浏览 2 评论
1872浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
660浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
528浏览 3评论
544浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
517浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-28 08:56 , Processed in 0.563856 second(s), Total 73, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号