完成AHT10温湿度获取后,开始进行下一步,nb-iot通讯。害,对菜鸟太不友好了,折腾了快十天。
最开始的想法是利用串口接收中断HAL_UART_Transmit_IT来对串口2收到数据进行接收并存储,本来思路是定义一个缓存变量,内存给的够大,这样每次模块返回的数据都能完全存放在这个缓存里。就算数据没装满,没有触发中断,那我去读取缓存里的数值也可以吧,然后下次接收之前再清理缓存。我的思路是这样,没有去研究接收时是不是每次都是从首地址开始,如果从首地址开始,我觉得思路是行的通的。实际操作呢,还是问题多多,返回的指令是可以接收到,但是缓存长度定太大了不行,定太小了也不行,我自己试验是只能定到32,缓存里才有数据,可是这样表面思路是错误的,如果思路可以,那为什么定长一点就不行呢?水平不足,真是折磨人,对HAL理解也不够,这个思路暂时放弃。
于是我百度找思路,将HAL_UART_Transmit_IT();缓存地址长度设为一个字节,每接收一个字节我都进一次回调函数,然后将这个字节存起来,这样等他接受完我在把存储的数据打印出来,心想这样总可以了吧,但事与愿违,还是不行,打印结果为空。害,搞死人啊,内心逐渐自闭。
在这两次实验,我对HAL库函数的不理解,给我造成了很大的困扰,虽然我现在也还没理解,暂时记录着,慢慢琢磨吧。一个是函数的封装流程、逻辑、处理结果。
还有一个是接收进入中断时,如果按照一个字节来,那么这个速度应该是很快的,我延时的话会不会造成数据丢失。这些都有待论证。心烦意乱,只能另寻出路!
最后我采用dma+空闲中断来进行处理,虽然也花了两天实际,但好歹是实现了数据的完整收发。
话不多说,有想说的再补充。首先是STM32cubemx配置
配置完我们看代码。
首先是主函数开启空闲中断
__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()发送指令,效果如下。