最近准备搞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---板子GND PC TC--板子 RX PC 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[10]="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,还有没有好办法呢? |
一大帮干单片机的,看到st的驱动库惊为高科技。用过环形队列做串口收发吗?真正理解钩子函数吗?用过链表数据结构吗?用过动态内存分配吗?对编译器和arm架构理解吗?有没有用散转文件去定义程序段和数据段的位置?用cube生成一个上百M的工程上来就可以写print hello world就是高手了?
老哥一针见血,怪不得怎么不触发中断,原来得
*pData
满才会触发。建议赶紧去医院检查一下脑子。
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
也就是你的方法跟我一样 用 1
不是,是在串口助手里一个个字符发。。。
不用这么麻烦的。。。
可是之前我试过像你一样将10改1,还是不行啊
这个函数是每次串口1接收到了设置的10个字节,进入串口接收中断回调函数HAL_UART_RxCpltCallback,
譬如发送15个字节,前10个字节收到后,进入函数HAL_UART_RxCpltCallback,后5个字节没满10个字节,不会进入的
评分
查看全部评分
反正当上次接收还没有结束的时候调了也没用,但是当上次接收结束了,调一下又进入接收状态了呀,本来HAL库就是这么设计的。
非要在中断回调中再开启中断接收,似乎没有必要。而且万一这个时候由于其他原因串口接收被占了,你调用中断接收失败,整个链条就断了。还是放在while(1)中保险。
评分
查看全部评分
那为什么把10改成1就好了
传统串口应该是接收1个字节,中断一次,如果你的程序是这样设计的,就把10改成1就可以了。
其实本质上这个串口也是接收1个字节,中断一次的,只不过接收的字符没有达到用户设定的数量时,它没有进入接收中断回调函数。
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);
用上面这个函数设置也就在接收定长帧数据时比较方便。不定长的帧数据为了避免遗漏数据,确实要把10改成1的。
改成1之后,如果在接收回调函数里面做数据解析并给线程发送消息,那么很可能紧接着的第二个字节overflow,因为串口只有1个字节的硬件FIFO,非常奇怪st的库用的那么广,难道大家都没遇到问题吗?