打印
[信息]

STM32G070RB探测24-ESP8266(ESP01S)http上传程序优化及获取时间

[复制链接]
445|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
duo点|  楼主 | 2021-3-3 15:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

这篇就上篇的post做个后续处理,发现发送之后发送之后返回数据的接收有问题,因为发送返回的发送成功数据和平台返回的数据并不是一包,按之前数据的接收处理方式会有丢包的情况,我对此进行优化,添加了双缓存处理.之前的数据是接受完包就暂停接收,直至数据用了之后才重新开始,这样会导致在数据接收后到没有处理之前的一段时间有数据发进来,就会导致DMA没打开而丢包,对此进行优化处理,使用双缓存区,DMA缓存区一直接收数据,在接收到转存到待处理缓存区,然后继续接收.下面进行程序优化

1.修改结构体

view plaincopy to clipboardprint?

  • typedef struct
  • {
  •     uint8_t dma_rx_buff[RX_BUF_MAX_LEN];//DMA缓存区
  •     uint8_t rec_rx_buff[RX_BUF_MAX_LEN];//REC缓存区
  •     uint16_t rec_len;    //DMA接收长度
  •     uint16_t dma_len;    //REC接收长度
  •     volatile uint8_t flag;  //用于判断是否接收完 1为接收完
  • }USRAT_RX;

2.修改中断接收函数

view plaincopy to clipboardprint?

  • void USART1_IRQHandler(void)
  • {
  •   /* USER CODE BEGIN USART1_IRQn 0 */
  •   /* USER CODE END USART1_IRQn 0 */
  •   HAL_UART_IRQHandler(&huart1);
  •   /* USER CODE BEGIN USART1_IRQn 1 */
  •   if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)//产生空闲中断(说明接收完一包)
  •     {
  •         __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除空闲中断标志(否则会一直不断进入中断)
  •         HAL_UART_DMAStop(&huart1);//停止本次DMA传输
  •         usart1_rx.dma_len  = RX_BUF_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//计算接收到的数据长度
  •         if(usart1_rx.rec_len>0)//证明数据未处理即还有未完成数据
  •         {
  •             memcpy(&usart1_rx.rec_rx_buff[usart1_rx.rec_len],usart1_rx.dma_rx_buff,usart1_rx.dma_len); //转存到待处理区域
  •             usart1_rx.rec_len += usart1_rx.dma_len;
  •         }
  •         else
  •         {
  •             memcpy(usart1_rx.rec_rx_buff,usart1_rx.dma_rx_buff,usart1_rx.dma_len);//转存到待处理区域
  •             usart1_rx.rec_len = usart1_rx.dma_len;
  •         }
  •         usart1_rx.flag = 1;
  •         if(usart1_rx.rec_len == 0)//防止误入
  •         {
  •             usart1_rx.flag = 0;
  •         }
  •         HAL_UART_Receive_DMA(&huart1, (uint8_t*)usart1_rx.dma_rx_buff, RX_BUF_MAX_LEN);//设置DMA传输,串口2的数据搬运到缓存中
  •         HAL_UART_DMAResume(&huart1);//恢复DMA传输
  •     }
  •   /* USER CODE END USART1_IRQn 1 */
  • }

3.修改清空函数

view plaincopy to clipboardprint?

  • void Clear_Usart(USRAT_RX *usart_rx)//初始化(清空)串口结构体
  • {
  •     memset(&usart_rx->rec_rx_buff[0], 0, RX_BUF_MAX_LEN);//全写0
  •     usart_rx->rec_len = 0;
  •     usart_rx->flag = 0;
  • }

4.将之前的数据处理中的rx_buff全改为rec_rx_buff,len都改为rec_len

5.稍微修改代码

view plaincopy to clipboardprint?

  • Start_Count();
  • OLED_Init();
  • AHT10Init();
  • Clear_Usart(&usart1_rx);//初始化串口结构体
  • __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//使能空闲中断
  • HAL_UART_Receive_DMA(&huart1, (uint8_t*)usart1_rx.dma_rx_buff, RX_BUF_MAX_LEN);//设置DMA传输,串口2的数据搬运到缓存中
  • esp_init();
  • /*电子产品世界*/
  • OLED_ShowCHinese(0u,0u,0);
  • OLED_ShowCHinese(16u,0u,1);
  • OLED_ShowCHinese(32u,0u,2);
  • OLED_ShowCHinese(48u,0u,3);
  • OLED_ShowCHinese(64u,0u,4);
  • OLED_ShowCHinese(80u,0u,5);
  • /**************/
  • /* USER CODE END 2 */
  • /* Infinite loop */
  • /* USER CODE BEGIN WHILE */
  • while (1)
  • {
  •     static uint16_t num;
  •     num++;
  •     BH1750_Send_Cmd(ONCE_H_MODE);//单次模式
  •     sprintf(buf,"tem:%.1f   ",pv.tem);
  •     OLED_P8x16Str(0u,2u,(uint8_t *)buf);
  •     sprintf(buf,"hum:%d%%   ",pv.hum);
  •     OLED_P8x16Str(0u,4u,(uint8_t *)buf);
  •     sprintf(buf,"lux:%d     ",pv.lux_16);
  •     OLED_P8x16Str(0u,6u,(uint8_t *)buf);
  •     AHT10ReadData(&pv.tem,&pv.hum);
  •     BH1750_Read_Dat(pv.lux);//读取数据
  •     pv.lux_16 = BH1750_Dat_To_Lux(pv.lux);//转换数据
  •     if(num>100)
  •     {
  •         num = 0;
  •         printf("lux:%d\r\n",pv.lux_16);
  •         printf("tem:%.1f\r\nhum:%d%%\r\n",pv.tem,pv.hum);
  •         OneNet_SendData();//上传数据
  •         HAL_Delay(200);//等待平台回复
  •     }
  •     if(usart1_rx.flag)//接收到数据
  •     {
  •         ipd_rx = ESP8266_GetIPD();//解析数据
  •         if(ipd_rx.len>0)//判断是否为网络下发数据
  •         {
  •              printf("\r\n\r\nipd_rx.IPD_buff:%s\r\n\r\n",ipd_rx.IPD_buff);
  •         }
  •         Clear_Usart(&usart1_rx);//清空缓存
  •     }
  •     /* USER CODE END WHILE */
  •     /* USER CODE BEGIN 3 */
  • }

6.烧录看结果

返回数据已经完整接收到了

发现,当发送POST数据之后,它能返回一串数据,仔细看,会发现里边有一串时间

这就是GMT时间

GMT时间就是英国格林威治时间,也就是世界标准时间,是本初子午线上的地方时,是0时区的区时,与我国的标准时间北京时间(东八区)相差8小时,即晚8小时

比如GMT时间为14:54:11,北京时间就是(15+8):54:11即为23:54:11,下面就通过字符串操作来取出这段时间,并显示在OLED上,因为我POST的速度并不是很快,所以我只截取了小时和分钟

下面上程序

view plaincopy to clipboardprint?

  • if(usart1_rx.flag)//接收到数据
  • {
  •     ipd_rx = ESP8266_GetIPD();//解析数据
  •     if(ipd_rx.len>0)//判断是否为网络下发数据
  •     {
  •         printf("\r\n\r\nipd_rx.IPD_buff:%s\r\n\r\n",ipd_rx.IPD_buff);
  •         dateadr= strstr((char *)ipd_rx.IPD_buff, "GMT");//找到"GMT"
  •         memcpy(buf,dateadr-9,5);
  •         hour = (buf[0]-0x30)*10+(buf[1]-0x30);
  •         hour+=8;
  •         if(hour>23)
  •             hour-=24;
  •         min  = (buf[3]-0x30)*10+(buf[4]-0x30);
  •         printf("%02d:%02d\r\n",hour,min);
  •         sprintf(buf,"%02d:%02d   EEPW",hour,min);
  •         OLED_P8x16Str(0u,0u,(uint8_t *)buf);
  •     }
  •     Clear_Usart(&usart1_rx);//清空缓存
  • }

思路很简单就是找到GMT的位置,再往前9个字符,然后截取前5个,把小时数加8,超过23就减24,然后显示在OLED上

效果如下

http有POST了,当然不能少了GET,下篇搞一个api get获取天气,制作一个简单的桌面天气


使用特权

评论回复
沙发
一刀一级| | 2021-3-3 15:33 | 只看该作者
目前STM32G070RB大致涨到多少钱一片?有人知道吗?

使用特权

评论回复
板凳
onlycook| | 2021-3-3 15:34 | 只看该作者
确实做的不错的,受益颇多

使用特权

评论回复
地板
内政奇才| | 2021-3-3 15:35 | 只看该作者
代码学的挺不错的

使用特权

评论回复
5
麻花油条| | 2021-3-3 15:35 | 只看该作者
不错,学习了

使用特权

评论回复
6
豌豆爹| | 2021-3-3 15:36 | 只看该作者
楼主很厉害啊,很好的干货,值得学习借鉴

使用特权

评论回复
7
七毛钱| | 2021-3-3 15:37 | 只看该作者
很棒的,支持下楼主哦

使用特权

评论回复
8
里面有晴雨| | 2021-3-3 19:27 | 只看该作者
没有想到串口还可以这么应用,学习到了很多知识,谢谢楼主。

使用特权

评论回复
9
keaibukelian| | 2021-4-2 11:28 | 只看该作者
代码真的好多啊

使用特权

评论回复
10
labasi| | 2021-4-2 11:28 | 只看该作者
处理的很巧妙

使用特权

评论回复
11
paotangsan| | 2021-4-2 11:29 | 只看该作者
怎么使用双缓存区啊

使用特权

评论回复
12
renzheshengui| | 2021-4-2 11:30 | 只看该作者
可以自定义长度吗

使用特权

评论回复
13
wakayi| | 2021-4-2 11:31 | 只看该作者
可以修改一下优先级吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

440

主题

1669

帖子

1

粉丝