大家遇到什么什么题,可以私聊我。

近期由于某些原因,玩了一下stm32+WiFi获取网络天气和网络时间。之前一直觉得这个东西会有点难度,其实,做完了才发现,其实那只是想象中的难而已。现在,将这几天的成果分享一下,做个学习记录,也分享给有需要的伙伴。

有关原文链接如下:
原文地址

在文末有改良好的代码,问题肯定是有的,但是比之前,好很多,有需要的朋友可以自己下载。

上面链接给的代码其实是有问题的,经过测试,发现三点不足:
1.RTC时钟,仅仅只是RTC时间;
2.程序运行一段时间后(三个小时内),100%会死机,因此基本可以判断出,程序是有问题的具体原因不详,貌似是堆栈溢出导致的;
3.天气更新情况,在没有死机的情况下,看似是在更新,其实从串口调试助手可以看到,人机交互界面并没有更新。

经过改善,满足了以下要求:
1.开机获取网络时间,之后将会由这个时间借助RTC继续运行;
2.在测试的三个小时内没有再出现死机的情况;
3.在测试的三个小时内,天气每隔一段时间都会自动更新,并体现在LCD屏幕上。

一、测试要求(只说我用到的)

1.硬件:

①stm32f103ZET6(我用的战舰板,请用RAM容量尽量大的芯片)②TFTLCD屏(我的是4.3寸)③ESP8266 WIFI串口模块(串口3)④Jlink(程序烧录)⑤串口线⑥路由器

2.软件

①keil5
②串口调试助手

二、相关设置

这里就不做过多的介绍,只做简单的说明,有疑问请参考上面给出的链接。
①WiFi串口模块固件为AT固件
②jlink需要安装对应的驱动,用于程序的调试和烧录
③串口也需要对应的驱动,用于输出调试信息

三、程序流程

其实简单点说,就几个步骤而已,我把他转换成几条AT指令,只需要按照下面步骤控制WiFi模块,就可以获取到网络天气和时间信息,如下:
1.首先来看看获取当前天气情况

①AT    ack:OK                          //判断WiFi模块是否存在以及是否支持AT指令
②ATE0    ack: OK                        //取消回显,可要可不要,为了方便接下来演示,这句我就不写进去了
③AT+CWMODE=1  ack:OK      //设置WiFi模块为STA模式
④AT+RST  ack:OK                           //复位WiFi模块
⑥AT+CIPMUX=0  ack:OK          //单连接模式
⑦AT+CWJAP="HUAWEI nova 5","b12345678"   ack:WIFI GOT IP //连接热点,对应的是热点名和热点密码,注意,务必等待该条指令返回WIFI GOT IP后再发送下面的指令
⑧AT+CIPSTART="TCP","api.seniverse.com",80     ack:OK  //建立TCP连接
⑨AT+CIPMODE=1  ack:OK   //透传模式
⑩AT+CIPSEND  ack:OK     //AT+CIPMODE=1并且作为客户端模式下,进入透传模式(需要支持硬件流控,否则大量数据情况下会丢数据)模块收到指令后先换行返回”>”,然后会发送串口接收到的数据。

发送完上面的指令,并正确返回后,发送下面一串数据(不需要换行)

GET https://api.seniverse.com/v3/weather/now.json?key=SWaCmu3LmzT_kS21g&location=changsha&language=zh-Hans&unit=c
//发送获取天气信息的网址,记得前面的GET,不可少

最后,记得发送一条退出透传的指令,否则后面AT指令将无法发送:

+++(不需要换行,也不要有空格)
AT+CIPCLOSE  ack:OK

为了方便大家查看,我保存了串口调试助手发送指令以及模块返回情况,如下图:

上图中,最后一行,就是发送指令联网后返回来的一串字符串,有些是乱码,乱码部分其实就是中文,只不多串口没有对应的协议,没办法解析而已。这一串就是当前天气情况,也是我们需要解析的部分,中文部分,我们是需要把它转换成utf8格式的(具体请看代码),整个解析过程代码(其实很简单的)如下:

//解析当前天气
void parse_now_weather(void)
{u16 i = 0,j = 0,line = 0;int len = 0;char gbkstr[50] = {0};Now_Weather *weather_Structure = mymalloc(SRAMIN,sizeof(Now_Weather));printf("jieshou->1dayjson = %s\r\n",USART3_RX_BUF);for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 'n' && USART3_RX_BUF[i+1] == 'a' && USART3_RX_BUF[i+2] == 'm' && USART3_RX_BUF[i+3] == 'e'){while(USART3_RX_BUF[i+7] != '"')weather_Structure->m_CityName[j++] = USART3_RX_BUF[7+(i++)];weather_Structure->m_CityName[j] = '\0';break;}}SwitchToGbk((const u8*)weather_Structure->m_CityName,strlen(weather_Structure->m_CityName),(u8 *)gbkstr,&len);  //获取城市名称转换为gbk文件if(strstr(gbkstr,"衡阳") != NULL)LCD_ShowString(0,20,sizeof("hengyang")*8,16,16,"hengyang");else if(strstr(gbkstr,"长沙") != NULL)  LCD_ShowString(0,140,sizeof("changsha")*8,16,16,"changsha");j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 't' && USART3_RX_BUF[i+1] == 'e' && USART3_RX_BUF[i+2] == 'x' && USART3_RX_BUF[i+3] == 't'){while(USART3_RX_BUF[i+7] != '"')weather_Structure->m_Text[j++] = USART3_RX_BUF[7+(i++)];weather_Structure->m_Text[j] = '\0';break;}}memset(gbkstr,0,sizeof(gbkstr));if(flag == 1) line = 160;//长沙else if(flag == 2) line = 40;//衡阳SwitchToGbk((const u8*)weather_Structure->m_Text,strlen(weather_Structure->m_Text),(u8 *)gbkstr,&len);if(strstr(gbkstr,"阴") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"overcast      ");else if(strstr(gbkstr,"多云") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"cloudy        ");else if(strstr(gbkstr,"晴") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"fine day      ");else if(strstr(gbkstr,"小雨") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"light rain    ");else if(strstr(gbkstr,"中雨") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"moderate rain ");else if(strstr(gbkstr,"大雨") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"heavy rain    ");else if(strstr(gbkstr,"雷阵雨") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"thunder shower");else if(strstr(gbkstr,"阵雨") != NULL)LCD_ShowString(88,line,sizeof("overcast      ")*8,16,16,"shower        ");j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 't' && USART3_RX_BUF[i+1] == 'e' && USART3_RX_BUF[i+2] == 'm' && USART3_RX_BUF[i+3] == 'p'){while(USART3_RX_BUF[i+14] != '"')weather_Structure->m_Temp[j++] = USART3_RX_BUF[14+(i++)];weather_Structure->m_Temp[j] = '\0';break;}}if(flag == 1) line = 220;//长沙else if(flag == 2) line = 100;//衡阳LCD_ShowString(100,line,25,20,16,(u8*)weather_Structure->m_Temp);   printf("wendu = %s\r\n",weather_Structure->m_Temp);j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 'l' && USART3_RX_BUF[i+1] == 'a' && USART3_RX_BUF[i+2] == 's' && USART3_RX_BUF[i+3] == 't'){while(USART3_RX_BUF[i+14] != '"')weather_Structure->m_LastUpdataTime[j++] = USART3_RX_BUF[14+(i++)];weather_Structure->m_LastUpdataTime[j] = '\0';break;}}if(flag == 1) line = 140;else if(flag == 2)line = 20;LCD_ShowString(210,line,200,20,16,(u8*)weather_Structure->m_LastUpdataTime);printf("1day_updata_time = %s\r\n",(u8*)weather_Structure->m_LastUpdataTime);myfree(SRAMIN,weather_Structure);
}

2.未来三天天气情况:
和上面类似的,我就不演示了,直接上AT指令:

①AT    ack:OK                          //判断WiFi模块是否存在以及是否支持AT指令
②ATE0    ack: OK                        //取消回显,可要可不要,为了方便接下来演示,这句我就不写进去了
③AT+CWMODE=1  ack:OK      //设置WiFi模块为STA模式
④AT+RST  ack:OK                           //复位WiFi模块
⑥AT+CIPMUX=0  ack:OK          //单连接模式
⑦AT+CWJAP="HUAWEI nova 5","b12345678"   ack:WIFI GOT IP //连接热点,对应的是热点名和热点密码,注意,务必等待该条指令返回WIFI GOT IP后再发送下面的指令
⑧AT+CIPSTART="TCP","api.seniverse.com",80     ack:OK  //建立TCP连接
⑨AT+CIPMODE=1  ack:OK   //透传模式
⑩AT+CIPSEND  ack:OK     //AT+CIPMODE=1并且作为客户端模式下,进入透传模式(需要支持硬件流控,否则大量数据情况下会丢数据)模块收到指令后先换行返回”>”,然后会发送串口接收到的数据。

完事之后,发送下面一串字符串,用于获取未来三天天气情况:

GET https://api.seniverse.com/v3/weather/daily.json?key=SWaCmu3LmzT_kS21g&location=changsha&language=zh-Hans&unit=c&start=0&days=5

最后,关闭透传,发送和上面一样的指令。

数据解析代码如下:

//解析3天天气
void parse_3days_weather(void)
{u16 i = 0,j = 0,line = 0;int len = 0;char gbkstr[50] = {0};Now_Weather *weather_Structure = mymalloc(SRAMIN,sizeof(Now_Weather));printf("jieshou->1dayjson = %s\r\n",USART3_RX_BUF);for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 'w' && USART3_RX_BUF[i+1] == 'i' && USART3_RX_BUF[i+2] == 'n' && USART3_RX_BUF[i+3] == 'd'){while(USART3_RX_BUF[i+17] != '"')weather_Structure->m_WindDir[j++] = USART3_RX_BUF[17+(i++)];weather_Structure->m_WindDir[j] = '\0';break;}}SwitchToGbk((const u8*)weather_Structure->m_WindDir,strlen(weather_Structure->m_WindDir),(u8 *)gbkstr,&len);  //获取城市名称转换为gbk文件if(flag == 1) line = 200;//长沙else if(flag == 2) line = 80;//衡阳LCD_Fill(220,45,320,61,BLACK);if(strstr(gbkstr,"北") != NULL)           {if(strstr(gbkstr,"西") != NULL)       LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"Northwest wind   ");else if(strstr(gbkstr,"东") != NULL)  LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"Northeastern wind");                                     else LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"northerly        ");}else if(strstr(gbkstr,"南") != NULL)  {if(strstr(gbkstr,"西") != NULL)      LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"Southwest wind   ");else if(strstr(gbkstr,"东") != NULL) LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"Southeast wind   ");else LCD_ShowString(0,line,sizeof("southerly        ")*8,16,16,"southerly        ");}j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 's' && USART3_RX_BUF[i+1] == 'p' && USART3_RX_BUF[i+2] == 'e' && USART3_RX_BUF[i+3] == 'e'){while(USART3_RX_BUF[i+8] != '"')weather_Structure->m_WindSpeed[j++] = USART3_RX_BUF[8+(i++)];weather_Structure->m_WindSpeed[j] = '\0';break;}}LCD_ShowString(200,line,sizeof(weather_Structure->m_WindSpeed)*8,16,16,(u8 *)weather_Structure->m_WindSpeed);   //显示风速km/hj = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 's' && USART3_RX_BUF[i+1] == 'c' && USART3_RX_BUF[i+2] == 'a' && USART3_RX_BUF[i+3] == 'l'){while(USART3_RX_BUF[i+8] != '"')weather_Structure->m_WindGrade[j++] = USART3_RX_BUF[8+(i++)];weather_Structure->m_WindGrade[j] = '\0';break;}}LCD_ShowString(160,line,sizeof(weather_Structure->m_WindGrade)*8,16,16,(u8 *)weather_Structure->m_WindGrade);j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 'h' && USART3_RX_BUF[i+1] == 'u' && USART3_RX_BUF[i+2] == 'm' && USART3_RX_BUF[i+3] == 'i'){while(USART3_RX_BUF[i+11] != '"')weather_Structure->m_Humi[j++] = USART3_RX_BUF[11+(i++)];weather_Structure->m_Humi[j] = '\0';break;}}if(flag == 1) line = 220;//长沙else if(flag == 2) line = 100;//衡阳LCD_ShowString(160,line,sizeof(weather_Structure->m_Humi)*8,16,16,(u8 *)weather_Structure->m_Humi);j = 0;for(i = 0; i < strlen((char *)USART3_RX_BUF); i++){if(USART3_RX_BUF[i] == 'l' && USART3_RX_BUF[i+1] == 'a' && USART3_RX_BUF[i+2] == 's' && USART3_RX_BUF[i+3] == 't'){while(USART3_RX_BUF[i+14] != '"')weather_Structure->m_LastUpdataTime[j++] = USART3_RX_BUF[14+(i++)];weather_Structure->m_LastUpdataTime[j] = '\0';break;}}LCD_ShowString(0,300,200,20,12,(u8*)weather_Structure->m_LastUpdataTime);printf("1day_updata_time = %s\r\n",(u8*)weather_Structure->m_LastUpdataTime);myfree(SRAMIN,weather_Structure);
}

3.获取网络时间
套路类似的:

①AT    ack:OK                          //判断WiFi模块是否存在以及是否支持AT指令
②ATE0    ack: OK                        //取消回显,可要可不要,为了方便接下来演示,这句我就不写进去了
③AT+CWMODE=1  ack:OK      //设置WiFi模块为STA模式
④AT+RST  ack:OK                           //复位WiFi模块
⑥AT+CIPMUX=0  ack:OK          //单连接模式
⑦AT+CWJAP="HUAWEI nova 5","b12345678"   ack:WIFI GOT IP //连接热点,对应的是热点名和热点密码,注意,务必等待该条指令返回WIFI GOT IP后再发送下面的指令
⑧AT+CIPSTART="TCP","cgi.im.qq.com",80     ack:OK  //建立TCP连接
⑨AT+CIPMODE=1  ack:OK   //透传模式
⑩AT+CIPSEND  ack:OK     //AT+CIPMODE=1并且作为客户端模式下,进入透传模式(需要支持硬件流控,否则大量数据情况下会丢数据)模块收到指令后先换行返回”>”,然后会发送串口接收到的数据。

发送完上面的指令后,发送下面一串字符

GET http://cgi.im.qq.com

最后一样,需要关闭透传模式。

数据解析格式如下:

//获取北京时间
u8 get_beijing_time(void)
{u8 *p;u8 res;u8 *resp;u8 *p_end;
//  u8 ipbuf[16];   //IP缓存p=mymalloc(SRAMIN,40);                           //申请40字节内存resp=mymalloc(SRAMIN,10);p_end=mymalloc(SRAMIN,40);sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",TIME_SERVERIP,TIME_PORTNUM);    //配置目标TCP服务器res = atk_8266_send_cmd(p,"OK",200);//连接到目标TCP服务器if(res==1){myfree(SRAMIN,p);return 1;}delay_ms(300);atk_8266_send_cmd("AT+CIPMODE=1","OK",100);      //传输模式为:透传  printf("设备 %s\r\n",p);CLR_BUF();atk_8266_send_cmd("AT+CIPSEND","OK",100);         //开始透传printf("start trans...\r\n");u3_printf("GET http://cgi.im.qq.com\n\n");delay_ms(20);CLR_BUF();   delay_ms(1000);if(USART3_RX_STA != 0){strncpy((char *)resp,"Date",5);USART3_RX_BUF[USART3_RX_STA] = 0;//printf("get_tim_srt:%s\r\n",USART3_RX_BUF);if(strstr((char*)USART3_RX_BUF,(char*)resp)) {       strncpy((char *)resp,"GMT",4);p_end = (u8*)strstr((char*)USART3_RX_BUF,(char*)resp);p = p_end - 9; //printf("get_net_str %s\r\n",p);nwt.hour = ((*p - 0x30)*10 + (*(p+1) - 0x30) + 8) % 24;  //GMT0-->GMT8nwt.min = ((*(p+3) - 0x30)*10 + (*(p+4) - 0x30)) % 60;nwt.sec = ((*(p+6) - 0x30)*10 + (*(p+7) - 0x30)) % 60;nwt.year = ((*(p-5) - 0x30)*1000 + (*(p-4) - 0x30)*100+ (*(p-3) - 0x30)*10+ (*(p-2) - 0x30)); nwt.date = ((*(p-12) - 0x30)*10 + (*(p-11) - 0x30)); if        ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Jan")) nwt.month=1; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Feb")) nwt.month=2; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Mar")) nwt.month=3; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Apr")) nwt.month=4; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "May")) nwt.month=5; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Jun")) nwt.month=6; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Jul")) nwt.month=7; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Aug")) nwt.month=8; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Sep")) nwt.month=9; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Oct")) nwt.month=10; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Nov")) nwt.month=11; else if   ((u8*)strstr((char*)USART3_RX_BUF,(char*) "Dec")) nwt.month=12;CLR_BUF();printf("uddate:nettime!!!");RTC_Set(nwt.year,nwt.month ,nwt.date ,nwt.hour ,nwt.min,nwt.sec);                                            }CLR_BUF();                                                     }               atk_8266_quit_trans();//退出透传atk_8266_send_cmd("AT+CIPCLOSE","OK",50);         //关闭连接myfree(SRAMIN,p);myfree(SRAMIN,resp);myfree(SRAMIN,p_end);return 0;
}

最后附上代码,请自行下载,谢谢:
代码资料

stm32 + ESP8266 wifi获取网络时间和天气 stm32天气预报相关推荐

  1. esp32获取网络时间和天气

    @[esp32获取网络时间和天气] esp32获取网络时间和天气 目录 一.库的获取 二.esp32连接wifi 三.oled显示 四.汉字或图片取模放在oled中显示 五.esp32获取网络时间 六 ...

  2. ESP32通过WIFI获取网络时间

    title: ESP32通过WIFI获取网络时间 一.这里首先要知道esp32的wifi如何连接,才能获取到网络服务器的时间 不知道wifi怎么连接的这里有相关链接--esp32wifi连接网络 二. ...

  3. 【STM32训练—WiFi模块】第一篇、STM32驱动ESP8266WiFi模块获取网络时间

    目录 第一部分.写在前面 1.硬件准备 2.相关的AT指令 3.参考博客 第二部分.电脑串口助手调试ESP8266模块获取网络时间 1.ESP8266获取时间的流程 2.具体实现步骤 第三部分.STM ...

  4. ESP8266+STM32获取网络时间、OLED显示时间图片视频。

    学习过程不易,发文共享以下学习过程~ 先说说我的设计内容的组成: 目录 学习过程不易,发文共享以下学习过程~ 1. STM32控制ESP8266获取网络时间 第一步:电脑控制ESP8266获取时间数据 ...

  5. esp8266获取网络时间

    esp8266获取网络时间 我们使用的手机都有 "使用网络上的时间,自动调整日期和时间" 的功能.如果我们自己做的电子时钟也有自动调整时间的功能,那就很方便,而且不怕时间不准了. ...

  6. ESP8266获取网络时钟、天气

    硬件平台 正点原子ESP8266 前提 烧录到ESP8266的固件版本不要太老了,用比较新的(具体界限不清楚) 以安信可官网提供的AT固件举例,第5个不支持获取网络时间(AT指令不支持),我用的是第4 ...

  7. CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC

    CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC 引言 FTP代码库的移植 Cubemx配置SNTP以及RTC RTC配置方法 SNTP配置方法 FATFS载入RT ...

  8. Arduino ESP32 获取网络时间并同步本地RTC时钟

    Arduino ESP32 获取网络时间并同步本地RTC时钟 相关篇<Arduino ESP32 最简单直接获取网络时间方法> 在 ArduinoESP32核心支持库当中已经包含相关的获取 ...

  9. 51单片机利用8266获取网络时间

    51单片机利用8266获取网络时间 我现在是成都一所不出名的二本院校大三学生,第一次来到CSDN,趁有时间,把我之前做的项目,其中一个模块拿出来和大家分享,我也是小白,希望提出宝贵意见.OK,废话不多 ...

最新文章

  1. 2021年大数据Kafka(十二):❤️Kafka配额限速机制❤️
  2. 用好 Spring AOP,天降大锅从容应对!
  3. 宅家学习秘密武器!让时间从视频流和朋友圈中回到程序员的视野中吧!
  4. sql server操作案例
  5. docker项目部署 php_「Docker部署PHP+Vue项目」- 海风纷飞Blog
  6. 【51单片机快速入门指南】4.5:I2C 与 TCA6416实现双向 IO 扩展
  7. Spring Security(02)——关于登录
  8. 加密狗工作原理和破解方法简介
  9. scrapy 官方中文文档地址
  10. kaptcha配置java_java之kaptcha验证码
  11. 【淘宝静态页面HTML部分】
  12. python定时发送qq消息_自动给qq好友发消息
  13. 微信文章排版技巧和相关排版工具
  14. java国际化之时区问题处理
  15. Python 小写数字转为大写
  16. 某版本瑞数解决方案-爬虫
  17. 【学习笔记】SQL数据库
  18. pygame教程实例(四)小球弹跳(事件)
  19. 国内5款优秀的WEB前端框架
  20. 小强升职记:时间管理故事书

热门文章

  1. LOL:各服务器王者段位人数改动,越南菲律宾与韩国并列共300人
  2. [NIPS2017]Attention is all you need
  3. Linux查看被拦截的日志,imperva拦截日志的实时报警
  4. 企业微信三方开发(五):扫码登录
  5. table固定列html5,css+js简单实现table固定首行首列
  6. 用html写除法竖式代码,除法的竖式写法
  7. resure挽救笔记本系统和一些相关的操作记录
  8. 机器人开发--设计范式
  9. 什么牌子的护眼灯最好?分享四款护眼灯合格的品牌
  10. java8 Predicate