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

再次质疑 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版