HAL库实现USART2与BC20通讯,利用usart2+dma+空闲中断

      完成AHT10温湿度获取后,开始进行下一步,nb-iot通讯。害,对菜鸟太不友好了,折腾了快十天。

      最开始的想法是利用串口接收中断HAL_UART_Transmit_IT来对串口2收到数据进行接收并存储,本来思路是定义一个缓存变量,内存给的够大,这样每次模块返回的数据都能完全存放在这个缓存里。就算数据没装满,没有触发中断,那我去读取缓存里的数值也可以吧,然后下次接收之前再清理缓存。我的思路是这样,没有去研究接收时是不是每次都是从首地址开始,如果从首地址开始,我觉得思路是行的通的。实际操作呢,还是问题多多,返回的指令是可以接收到,但是缓存长度定太大了不行,定太小了也不行,我自己试验是只能定到32,缓存里才有数据,可是这样表面思路是错误的,如果思路可以,那为什么定长一点就不行呢?水平不足,真是折磨人,对HAL理解也不够,这个思路暂时放弃。

     于是我百度找思路,将HAL_UART_Transmit_IT();缓存地址长度设为一个字节,每接收一个字节我都进一次回调函数,然后将这个字节存起来,这样等他接受完我在把存储的数据打印出来,心想这样总可以了吧,但事与愿违,还是不行,打印结果为空。害,搞死人啊,内心逐渐自闭。

     在这两次实验,我对HAL库函数的不理解,给我造成了很大的困扰,虽然我现在也还没理解,暂时记录着,慢慢琢磨吧。一个是函数的封装流程、逻辑、处理结果。

还有一个是接收进入中断时,如果按照一个字节来,那么这个速度应该是很快的,我延时的话会不会造成数据丢失。这些都有待论证。心烦意乱,只能另寻出路!

     最后我采用dma+空闲中断来进行处理,虽然也花了两天实际,但好歹是实现了数据的完整收发。

     话不多说,有想说的再补充。首先是STM32cubemx配置

HAL库实现USART2与BC20通讯,利用usart2+dma+空闲中断

HAL库实现USART2与BC20通讯,利用usart2+dma+空闲中断

HAL库实现USART2与BC20通讯,利用usart2+dma+空闲中断

配置完我们看代码。

首先是主函数开启空闲中断

 __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);

然后找到stm32*****it.c函数,对中断2的服务函数修改一下,判断空闲中断触发没有,触发了就清除标志,因为我不需要进入回调函数里面操作什么,所以没写。

 1 void USART2_IRQHandler(void)
 2 {
 3   /* USER CODE BEGIN USART2_IRQn 0 */
 4   if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) != 0x00u)
 5     {
 6         __HAL_UART_CLEAR_IDLEFLAG(&huart2);
 7         //HAL_UART_IdleCallback(&huart2);
 8     }
 9   /* USER CODE END USART2_IRQn 0 */
10   HAL_UART_IRQHandler(&huart2);
11   /* USER CODE BEGIN USART2_IRQn 1 */
12 
13   /* USER CODE END USART2_IRQn 1 */
14 }

没啥了,放.c代码

 1 #include "bc20.h"
 2 #include "usart.h"
 3 #include "stdio.h"
 4 #include <string.h>
 5 #include "user_platform.h"
 6 uint8_t uSend_Buf[SEND_LENG];
 7 uint8_t uRec_Buf[SEND_LENG];
 8 USART_BUF usart2 = 
 9 {
10    uSend_Buf,
11    uRec_Buf,
12 };
13 
14 void BC20_Run(void)
15 {
16 
17     printf("bc20 start run\r\n");
18   SendAt("AT\r\n","OK",2,1000);
19     SendAt("ATE0\r\n","OK",2,1000);
20     SendAt("AT+CGMR\r\n","OK",2,1000);
21     SendAt("AT+CIMI\r\n","OK",2,1000);
22     SendAt("AT+CMEE=1\r\n","OK",2,1000);
23     SendAt("AT+CGSN=1\r\n","OK",2,1000);
24     SendAt("AT+QBAND?\r\n","OK",2,1000);
25     SendAt("AT+CEREG=1\r\n","OK",2,1000);
26     
27     
28     __HAL_UART_DISABLE_IT(&huart2,UART_IT_IDLE);
29     if(HAL_UART_DMAStop(&huart2)==HAL_OK)
30   {
31         printf("Stop uart2 rxdma\r\n");
32     }
33 }
34 /*  发送AT指令 
参数为:指令,返回值,错误重发次数,延时时间 */ 35 void SendAt(char* Send_data, char* Rec_check,uint8_t temp,uint16_t timeout) 36 { 37 char* const uSend_data = Send_data; 38 char* const uRec_check = Rec_check; 39 uint8_t ret ,errcount1,errcount2; 40 errcount1 = temp;//ÔÊÐí´íÎó´ÎÊý 41 errcount2 = temp; 42 DMA_Receive_Set(); 43 do{ 44 ret = SendString(uSend_data); 45 errcount1--; 46 HAL_Delay(timeout); 47 }while(ret != HAL_OK && errcount1 != 0);//·¢ËÍʧ°ÜÔٴη¢ËÍ 48 while(strstr((const char*)usart2.Rec_Buffer,uRec_check)==NULL && temp !=0)//¼ì²é·µ»ØÊý¾ÝÊÇ·ñÕýÈ·£¬Ê§°ÜÖØз¢ËͽÓÊÕ 49 { 50 User_DBG(" Data receiving error £º%s \r\n",uSend_data); 51 DMA_Receive_Set(); 52 --temp; 53 do{ 54 errcount2--; 55 ret = SendString(uSend_data); 56 HAL_Delay(timeout); 57 }while(ret != HAL_OK && errcount2 != 0);;//·¢ËÍʧ°ÜÔٴη¢ËÍ 58 } 59 printf("%s",usart2.Rec_Buffer); 60 } 61 62 //我用的是阻塞发送哈,没用DMA模式。 63 void SendArray(char* p_Arr,uint16_t LEN)//发送数组 64 { 65 HAL_UART_Transmit_DMA(&huart2,(uint8_t*)p_Arr,LEN); 66 } 67 68 uint8_t SendString(char* p_Str)//发送字符串指令 69 { 70 uint8_t ret; 71 //HAL_UART_Transmit_DMA(&huart2,p_Str,strlen((const char*)p_Str)); 72 ret = HAL_UART_Transmit(&huart2,(uint8_t*)p_Str,strlen((const char*)p_Str),0xFFFF); 73 if(ret == HAL_OK){ 74 printf("send:%s\r\n",p_Str); 75 return ret; 76 } 77 printf("send fail!!!\r\n"); 78 return HAL_ERROR; 79 } 80 81 82 void DMA_Receive_Set(void) 83 { 84 HAL_UART_DMAStop(&huart2);//停止串口DMA 85 Memory_Clr(usart2.Rec_Buffer,strlen((const char*)usart2.Rec_Buffer));//清楚缓存 86 HAL_UART_Receive_DMA(&huart2,usart2.Rec_Buffer,REC_LENG);//打开DMA接收 87 } 88 89 90 void Memory_Clr(uint8_t *clr_buf,uint16_t Leng)//内存清除 91 { 92 for(int i=0;i<Leng;i++) 93 { 94 *(clr_buf+i) = (uint8_t)0; 95 } 96 }

 1 #ifndef _BC20_H_
 2 #define _BC20_H_
 3 
 4 #include "stm32l1xx_hal.h"
 5 #define SEND_LENG 20
 6 #define REC_LENG 128
 7 typedef struct 
 8 {
 9     uint8_t* Send_Buffer;
10   uint8_t* Rec_Buffer;
11 
12 
13 }USART_BUF;
14 
15 extern USART_BUF usart2;
16 void BC20_Run(void);
17 void DMA_Receive_Set(void);
18 void SendAt(char* Send_data, char* Rec_check,uint8_t temp,uint16_t timeout);
19 void SendArray(char* p_Arr,uint16_t LEN);
20 uint8_t SendString(char* p_Str);
21 void Memory_Clr(uint8_t *clr_buf,uint16_t Leng);
22 #endif    

上面是.h的。很简单,害,搞了我这么久。用sendat()发送指令,效果如下。

HAL库实现USART2与BC20通讯,利用usart2+dma+空闲中断

 

上一篇:STM32的USART串口配置——学习笔记(5)


下一篇:摇杆控制LED灯的亮度