你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

再次质疑 HAL_UART_Receive_IT函数  

[复制链接]
GKoSon 提问时间:2018-4-19 17:38 /
阅读主题, 点击返回1楼
收藏 1 评论37 发布时间:2018-4-19 17:38
37个回答
zhao.zhao 回答时间:2018-8-12 13:58:21
一般不会溢出,串口中断优先等级设置得高一点,串口相对于CPU的运行速度慢多了,一般接收一个字节的时间够串口中断程序运行完成。
SimonZhou 回答时间:2018-8-21 08:53:47
ringsp 发表于 2018-8-12 11:59
改成1之后,如果在接收回调函数里面做数据解析并给线程发送消息,那么很可能紧接着的第二个字节overflow ...

那是你没做好。
ringsp 回答时间:2018-9-8 07:10:01
本帖最后由 ringsp 于 2018-9-8 07:12 编辑
cczhw 发表于 2018-8-21 08:53
那是你没做好。

一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表数据结构吗?用过动态内存分配吗?对编译器和arm架构理解吗?有没有用散转文件去定义程序段和数据段的位置?用cube生成一个上百M的工程上来就可以写print hello world就是高手了?
Snail_Feng 回答时间:2018-9-8 09:02:43
ringsp 发表于 2018-9-8 07:10
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表 ...

DMA了解一下
hellolinux-2302 回答时间:2018-9-8 09:16:32
看来那HAL火就不打一处冒出来,简单的事情弄得这么复杂......................直接勾选LL库!!
void MX_USART1_UART_Init(void) 函数中最后增加
  1. LL_USART_EnableIT_RXNE(USART1);
复制代码
发送用printf函数
  1. #include "stdio.h"
  2.   #ifdef __GNUC__
  3.     /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
  4.        set to 'Yes') calls __io_putchar() */
  5.     #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  6.   #else
  7.     #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  8.   #endif /* __GNUC__ */

  9. /*******************************************************************************
  10. * Function Name  : PUTCHAR_PROTOTYPE
  11. * Description    : Retargets the C library printf function to the USART.
  12. * Input          : None
  13. * Output         : None
  14. * Return         : None
  15. *******************************************************************************/
  16.         PUTCHAR_PROTOTYPE
  17.         {
  18.     /* Wait for TXE flag to be raised */
  19.     while (!LL_USART_IsActiveFlag_TXE(USART1));
  20.     LL_USART_TransmitData8(USART1, ch);
  21.     while (!LL_USART_IsActiveFlag_TC(USART1));
  22.     return ch;
  23.         }
复制代码
接收用中断方式,只要修改
void USART1_CharReception_Callback(void)
这个函数就可以了






ringsp 回答时间:2018-9-13 19:38:36

DMA就能解决这个问题吗?你待发送的数据要待在那个位置不能改变,而且只有等全部发完了才能再次操作?完全要应用程序去中断设置标识。实际的应用程序往往是要发送一个数据结构或者一个数组,那么调用发送后,后面的事完全不用再管,否则退出函数了那些局部变量怎么办?
ringsp 回答时间:2018-9-13 21:11:25

DMA只能解决CPU的负担问题,不能解决应用数据发送退出函数后的数据保持问题。
mrxueyuan 回答时间:2018-9-14 16:34:11
这个。。。有点神奇哦
lwg8458 回答时间:2018-12-7 16:41:40
zhao.zhao 发表于 2018-4-20 16:44
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);//6
这个函数是每次串口1接收到了设置的10个字节 ...

这个说到点
zhjb1 回答时间:2018-12-28 10:42:45
旧话重提,我遇到的问题有点不太一样。
采用您们所描述函数和代码可以将定义换成数组发送出去,但不能使用printf函数,只要打开此函数,MCU就宕机了。如果模拟缓冲输出,但结果无法成为需要的数值。
比如像从串口输出ADC的采样数据,结果为16进制数据,小数在前,大数灾后。如果采用自编的转换代码结果还不如直接看16进制数——因为他是正确的。
谢谢
unkao1 回答时间:2019-3-28 15:05:52
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{。。。。。
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);//6

郁闷,这个aRxBuffer 必须定义为全局变量才接收正常,局部变量不行,什么原因
lockyer 回答时间:2019-4-30 16:25:22
unkao1 发表于 2019-3-28 15:05
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{。。。。。
    HAL_UART_Receive_IT(&huart1, ...

那是因为接收字符的处理函数是在另外一个文件中,stm32f0xx_hal_uart.c
接收函数只是把变量的地址给了huart结构,再从别的地方赋值接收的数据
所以你局部变量退出这个函数地址就作废了,接收串口的数据也不可能赋值给你了。
lockyer 回答时间:2019-4-30 16:26:34
zhjb1 发表于 2018-12-28 10:42
旧话重提,我遇到的问题有点不太一样。
采用您们所描述函数和代码可以将定义换成数组发送出去,但不能使用p ...

printf的函数 putc不要用中断,要用直接发送的 HAL_UART_Transmit 。否则中断无法发送。
lockyer 回答时间:2019-4-30 16:40:32
ringsp 发表于 2018-8-12 10:20
没见过STM32这么蛋疼的串口,非标准16C550,纯自定义的。大多数情况下的应用都是,需要每一字节去解析协议 ...

很吐血。
1、主程序用 HAL_UART_Transmit , printf发送。如果发送期间有接收中断,那么中断中的再次HAL_UART_Receive_IT会返回HAL_BUSY。然后就再也无法接收了。因为中断没再次开启。全双工的串口被HAL库的大神设计成半双工了,而且是隐性的,偶尔出错,你都不知道问题所在了。

2、HAL库透过了几层函数调用,处理太多无用的判断,效率几乎慢了10倍甚至几十倍。8M主频处理下几个字节的命令都有可能OVERUN,导致数据丢失。48M好一些。

3、一旦数据处理不过来,就会触发HAL_UART_ErrorCallback。你就没机会再次开启中断接收了。必须在这个里面也加入错误处理和重新开启中断接收。

4、  最简单的,接收一个字符,然后发回去,如果字符多了,例如10个字符,都经常会触发HAL_UART_ErrorCallback,接收溢出。数据丢失。48M的32位机居然处理不过来9600的10个字节接收和回发。

总的来说,设计这个HAL串口库的人根本就不是一个干过实际应用的,都是书呆子,好庞大,好复杂,好低效,很多问题,很不好用。以前听说HAL库很多小问题,现在看真的不能用于真正的项目了。要用也只能大量的测试和很熟悉才行。 怪不得很多高手都只是用CUBEMX的配置,然后其他都自己写了。
一个串口收发,就一个寄存器读写,几个标志位清除。4行代码搞定的事情,居然用了过百行代码,几个函数调用开销。
其实那么多代码开销,还不如做个小的FIFO的循环缓冲区,10-50字节就好了。保证串口数据不丢失。然后做个空闲中断给我们用就可以了。有数据空闲,有数据,有指定数量数据三种触发中断通知处理数据。缓冲区自定义。
lockyer 回答时间:2019-4-30 16:42:26
ringsp 发表于 2018-9-8 07:10
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表 ...

小试牛刀用串口做个简单的几个字节的命令收发,发现问题很多,很多,很多,兔血一地。。。。。。
比起当年的51,pic,stm8,stm32f1的库,哭死,cubemx就是设置简单,可视化

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版