再次质疑 HAL_UART_Receive_IT函数
最近准备搞STM32L471 而以前103/107都是基于标准库写的。现在没办法了,用HAL库,而CUBEMX软件则是打开了新世界的大门。看网上的教程 果然遇到了评论中的问题。http://www.waveshare.net/study/article-644-1.html
只能执行一次,就不行了。在论坛我也找到了曾经的讨论https://www.stmcu.org.cn/module/forum/thread-604716-1-1.html
现在小弟在此表达一下这个问题。
第一步建立工程(107已经被我上个帖子搞坏了,用103吧)
第二部左边使能3处
第三部时钟
第四部使能中断 默认的115200 N 8 1不改
最后设置一下 就生成代码。
现在板子3根线连接:PC用一个驱动CH340的 串口转UART PCGND---板子GNDPC TC--板子 RXPC RX--板子 TX 打开串口助手准备实验。
先来简单的:直接输出
uint8_t ch=0xAb;//1
uint8_t aRxBuffer[]="hello GKoSon\r\n";//2
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);//3
HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);//4
while (1)
{。。。
上面增加的1234就可以完成直接输出调试信息了。【举例不好 也就算了吧】
现在开始接受,准备用中断接收。
CASE1
uint8_t ch=0xAb;//1
uint8_t aRxBuffer="0123456789";//2
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
//HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);//3
//HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);//4
HAL_UART_Transmit_IT(&huart1, (uint8_t *)aRxBuffer, sizeof(aRxBuffer));//5
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);//6
while (1)
{}
在上面的1234以后增加2局用于中断收发的使能。
在main.c最后重写回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);
}
此时效果:跑起来--板子给串口发送成功---串口给板子发送很多A但是板子只能返回一次!
CASE2
为什么只有第一次是成功的? 现在在while一直调用函数HAL_UART_Receive_IT
也就是修改为
while (1)
{
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);
HAL_Delay(100);
}
现在是成功了 问题是这肯定不行的 轮训还弄啥嘞。
CASE3
还是放弃上面的,依然用while(1){}这样,不轮询。
参考别人的 ,在每次接收的回调函数里面
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);
}
实际效果跟CASE1是一样的,第一次成功以后就不行了。
注意到这个其实中断每次是只接收1个u8的,所以改成10位1就可以了。
也就是:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 1,0xFFFF);
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
}
此时蜜汁还用。
那么除了这样用1,还有没有好办法呢?
本帖最后由 ringsp 于 2018-9-8 07:12 编辑
cczhw 发表于 2018-8-21 08:53
那是你没做好。
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表数据结构吗?用过动态内存分配吗?对编译器和arm架构理解吗?有没有用散转文件去定义程序段和数据段的位置?用cube生成一个上百M的工程上来就可以写print hello world就是高手了? ringsp 发表于 2018-9-8 07:10
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表 ...
建议赶紧去医院检查一下脑子。 没见过STM32这么蛋疼的串口,非标准16C550,纯自定义的。大多数情况下的应用都是,需要每一字节去解析协议。初始化的时候开启接收中断,只要来数据,要么满硬件FIFO触发中断,要么就是来了数据但不满FIFO触发超时中断,两种中断都可以去处理数据。而ST的HAL自以为是要么死等timeout,而把中断方式做成不断的开关中断,把很好的回调概念玩残了。而且没有硬件FIFO,容易丢字节。真不知道用STM32垃圾芯片的都是些什么应用,为了那些连环形队列数据结构都不会的人快速上手做产品? HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, Number);意思是接收到Number个字节后,触发HAL_UART_RxCpltCallback,没收满是不会触发的。而且HAL_UART_Receive_IT是一次性的,触发完后需要时要再调用一下。条件允许的话,用DMA+空闲中断实现不定长接收。 我之前直接修改的底层驱动,把他完成后的关闭逻辑部分删除了。。 我之前也遇到过,后来我发现只要你发送端一个个字符发送就不会出现问题,中断可以一直触发, myccl 发表于 2018-4-20 15:14
我之前也遇到过,后来我发现只要你发送端一个个字符发送就不会出现问题,中断可以一直触发, ...
也就是你的方法跟我一样用 1 与龙共舞 发表于 2018-4-20 15:23
也就是你的方法跟我一样用 1
不是,是在串口助手里一个个字符发。。。 myccl 发表于 2018-4-20 16:15
不是,是在串口助手里一个个字符发。。。
不用这么麻烦的。。。 与龙共舞 发表于 2018-4-20 16:22
不用这么麻烦的。。。
可是之前我试过像你一样将10改1,还是不行啊 HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);//6
这个函数是每次串口1接收到了设置的10个字节,进入串口接收中断回调函数HAL_UART_RxCpltCallback,
譬如发送15个字节,前10个字节收到后,进入函数HAL_UART_RxCpltCallback,后5个字节没满10个字节,不会进入的 第015章 STM32外设之Dhttps://www.stmcu.org.cn/module/forum/forum.php?mod=image&aid=412809&size=300x300&key=1cbb717b824b93bd&nocache=yes&type=fixnone