基于STM32的家庭气象站

编程入门 行业动态 更新时间:2024-10-28 08:31:02

基于STM32的家庭<a href=https://www.elefans.com/category/jswz/34/1747777.html style=气象站"/>

基于STM32的家庭气象站


本文同步发布于个人博客


项目地址

Maskbugzero/ESP8266-Weather-2021

一个关于STM32+ESP8266+DHT11的家庭气象站。

硬件资源

  1. 战舰V3\精英STM32F103开发板
  2. ALIENTEK 2.8/3.5/4.3/7寸TFTLCD模块(通过FSMC驱动.FSMC_NE4接LCD片选/A10接RS)
  3. 按键KEY0(PE4)/KEY1(PE3)/KEY_UP(PA0.也称之为WK_UP)
  4. ESP8266-12S WIFI模块1个
  5. DHT11模块1个

实现功能

  1. 微信小程序配网
  2. 室内温湿度测量及显示
  3. 室外天气数据获取及显示
  4. 时间显示及网络校准

连接方式

  • 模块与带有无线网卡的电脑或其他wifi设备连接:采用wifi连接
  • 模块与开发板连接:TTL串口方式

ATK-ESP8266 WIFI模块与精英板连接方式

TXD<------------>PB11

RXD<------------>PB10

GND<------------>GND

VCC<------------>3.3V\5V

DHT11模块与精英板连接方式

Data<------------>PE11

主要代码

外设初始化

初始化外设时,若DHT11工作不正常则显示屏无法正常显示。

 	LED_Init();		  			//初始化与LED连接的硬件接口KEY_Init();					//初始化按键LCD_Init();			   		//初始化LCD   RTC_Init();while(DHT11_Init())	//DHT11初始化	{printf("DHT11 出错!\r\n");delay_ms(200);}W25QXX_Init();				//初始化W25Q128tp_dev.init();				//初始化触摸屏usart3_init(115200);		//初始化串口3 my_mem_init(SRAMIN);		//初始化内部内存池exfuns_init();				//为fatfs相关变量申请内存  f_mount(fs[0],"0:",1); 		//挂载SD卡 f_mount(fs[1],"1:",1); 		//挂载FLASH.

微信小程序配网

源码:

//一键配网设置
u8 atk_8266_wifi_config(void)
{int i;while(atk_8266_send_cmd("AT","OK",20))//检查WIFI模块是否在线{atk_8266_quit_trans();//退出透传atk_8266_send_cmd("AT+CIPMODE=0","OK",200);  //关闭透传模式	printf("未检测到模块!!!");delay_ms(800);printf("尝试连接模块..."); } u3_printf("AT+RESTORE");		//恢复出厂设置delay_ms(1000);      //延时3S等待恢复成功delay_ms(1000);delay_ms(1000);printf("恢复出厂设置完成"); atk_8266_send_cmd("AT+RST","OK",20);		//软重启delay_ms(1000);         //延时3S等待重启成功delay_ms(1000);delay_ms(1000);delay_ms(1000);printf("软重启完成");while(atk_8266_send_cmd("ATE0","OK",20));//关闭回显atk_8266_send_cmd("AT+CWMODE=1","OK",50);		//设置WIFI STA模式atk_8266_send_cmd("AT+CWAUTOCONN=1","OK",20);   //使能上电自动连接APdelay_ms(300);atk_8266_send_cmd("AT+CWSTARTSMART=3","OK",20);		//支持ESP-Touch和Airkiss智能配网printf("智能配网已开启  等待30s\r\n");while(i<=30){delay_ms(1000);     //延时30S等待配网成功i++;}
//	while(atk_8266_check_cmd("smartconfig connected wifi"));					//连接目标路由器,并且获得IP
//	delay_ms(300);atk_8266_send_cmd("AT+CWSTOPSMART","OK",20);		//释放快连所占的内存return 0;
}

数据解析

天气数据

源码:(以当天天气数据为例,近3天天气数据类似)

//解析当前天气
u8 parse_now_weather(void)
{cJSON *root;cJSON *pSub;cJSON *arrayItem;cJSON *pItem;cJSON *pSubItem;cJSON *pChildItem;char *pr,*utf8str,*gbkstr;u8 size = 0;int len;u8 res;u8 temperature;root = mymalloc(SRAMIN,sizeof(cJSON));pSub = mymalloc(SRAMIN,sizeof(cJSON));pItem = mymalloc(SRAMIN,sizeof(cJSON));pSubItem = mymalloc(SRAMIN,sizeof(cJSON));pChildItem = mymalloc(SRAMIN,sizeof(cJSON));arrayItem = mymalloc(SRAMIN,sizeof(cJSON));pr = mymalloc(SRAMIN,1000);utf8str = mymalloc(SRAMIN,50);gbkstr = mymalloc(SRAMIN,50);memset(pr,0,1000);memset(gbkstr,0,50);memset(utf8str,0,50);file = mymalloc(SRAMIN,sizeof(FIL));res=f_open(file,(const TCHAR*)APP_ASCII_5427,FA_READ);//打开文件if(res==FR_OK){asc2_5427 = mymalloc(SRAMIN,file->fsize);if(asc2_5427 != NULL){res = f_read(file,asc2_5427,file->fsize,&br);}f_close(file);}printf("jieshou->1dayjson = %s\r\n",USART3_RX_BUF);root = cJSON_Parse((const char*)USART3_RX_BUF);if(root != NULL){pSub = cJSON_GetObjectItem(root,"results");if(pSub != NULL){
//			size = cJSON_GetArraySize(pSub);arrayItem = cJSON_GetArrayItem(pSub,0);  pr = cJSON_Print(arrayItem);   //获取jsom数组pItem = cJSON_Parse(pr);       //对数组,进行升级。if(pItem != NULL){pSubItem = cJSON_GetObjectItem(pItem,"location");if(pSubItem != NULL){pChildItem = cJSON_GetObjectItem(pSubItem,"name");if(pChildItem != NULL){utf8str = pChildItem->valuestring;SwitchToGbk((const u8*)utf8str,strlen(utf8str),(u8 *)gbkstr,&len);  //获取城市名称转换为gbk文件Show_Str(0,0,lcddev.width,lcddev.height,(u8 *)gbkstr,16,0);         //显示城市名称。}}memset(utf8str,0,50); //解决阴华memset(gbkstr,0,50);pSubItem = cJSON_GetObjectItem(pItem,"now");if(pSubItem != NULL){pChildItem = cJSON_GetObjectItem(pSubItem,"text");  //获取天气信息。多云if(pChildItem != NULL){utf8str = pChildItem->valuestring;SwitchToGbk((const u8*)utf8str,strlen(utf8str),(u8 *)gbkstr,&len);Show_Str(220,25,lcddev.width,lcddev.height,(u8 *)gbkstr,16,0);  //显示多云}memset(utf8str,0,50);memset(gbkstr,0,50);pChildItem = cJSON_GetObjectItem(pSubItem,"code");              //获取气象代码if(pChildItem != NULL){gbkstr = pChildItem->valuestring;show_weather_icon((u8 *)gbkstr,0);                           //根据气象代码,更新图片}memset(gbkstr,0,50);pChildItem = cJSON_GetObjectItem(pSubItem,"temperature");     //获取温度信息if(pChildItem != NULL){gbkstr = pChildItem->valuestring;temperature = str2int((u8 *)gbkstr);gui_show_num(140,22,2,RED,54,temperature,0x80);printf("wendu = %d\r\n",temperature);}}pSubItem = cJSON_GetObjectItem(pItem,"last_update");if(pSubItem != NULL)		{gbkstr =pSubItem->valuestring;LCD_ShowString(0,92,200,20,12,(u8*)gbkstr);printf("1day_updata_time = %s\r\n",(u8*)gbkstr);}}cJSON_Delete(pItem);}}cJSON_Delete(root);myfree(SRAMIN,root);myfree(SRAMIN,pSub);myfree(SRAMIN,pItem);myfree(SRAMIN,pSubItem);myfree(SRAMIN,pChildItem);myfree(SRAMIN,arrayItem);myfree(SRAMIN,pr);myfree(SRAMIN,utf8str);myfree(SRAMIN,gbkstr);myfree(SRAMIN,file);myfree(SRAMIN,asc2_5427);return 0;
}

时间数据获取和校准

源码:

u8 get_beijing_time(void)
{u8 *p;u8 res;u8 *resp;u8 *p_end;//	u8 ipbuf[16]; 	//IP缓存p=mymalloc(SRAMIN,40);							//申请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);      //传输模式为:透传	
//	atk_8266_get_wanip(ipbuf);//获取WAN IPUSART3_RX_STA=0;atk_8266_send_cmd("AT+CIPSEND","OK",100);         //开始透传printf("start trans...\r\n");u3_printf("GET /?app=life.time&appkey=58173&sign=4e67ab8533b30580e584c8b9f0a6cc50&format=json\n\n");	delay_ms(20);//延时20ms返回的是指令发送成功的状态
//	atk_8266_at_response(1);USART3_RX_STA=0;	//清零串口3数据delay_ms(1000);
//	atk_8266_at_response(0);if(USART3_RX_STA&0X8000)		//此时再次接到一次数据,为时间的数据{ USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符} resp="datetime_2";p_end = (u8*)strstr((char*)USART3_RX_BUF,(char*)resp);p = p_end-11; //确定串口数据中时间的起止位,如"datetime_1":"2021-03-31 20:09:07","datetime_2":"2021 中nwt.hour = ((*p - 0x30)*10 + (*(p+1) - 0x30));			      nwt.min = ((*(p+3) - 0x30)*10 + (*(p+4) - 0x30));nwt.sec = ((*(p+6) - 0x30)*10 + (*(p+7) - 0x30));nwt.year = ((*(p-11) - 0x30)*1000 + (*(p-10) - 0x30)*100+ (*(p-9) - 0x30)*10+ (*(p-8) - 0x30)); nwt.month = ((*(p-6) - 0x30)*10 + (*(p-5) - 0x30));nwt.date = ((*(p-3) - 0x30)*10 + (*(p-2) - 0x30));
//使用指针方法获取时分秒年月日 				RTC_Set(nwt.year,nwt.month ,nwt.date ,nwt.hour ,nwt.min,nwt.sec); //使用RTC函数设置时间  printf("nwt.year = %d\r\n",nwt.year);printf("nwt.month = %d\r\n",nwt.month);printf("nwt.date = %d\r\n",nwt.date);printf("nwt.hour = %d\r\n",nwt.hour);printf("nwt.min = %d\r\n",nwt.min);printf("nwt.sec = %d\r\n",nwt.sec);//		打印时分秒年月日数据//		parse_now_time();//	Cjson方法解析时间数据atk_8266_quit_trans();//退出透传atk_8266_send_cmd("AT+CIPCLOSE","OK",50);         //关闭连接myfree(SRAMIN,p);return 0;
}

实验现象

注意事项

  1. 4.3寸和7寸屏需要比较大电流,USB供电可能不足,请用外部电源适配器(推荐外接12V 1A电源)。
  2. 本例程在LCD_Init函数里面(在ILI93xx.c),用到了printf,如果不初始化串口1,将导致液晶无法显示!!
  3. 字库更新时,需自备标准SD卡一张(即大卡,也可以用TF卡+卡套),并拷贝光盘:SD卡根目录文件里面的所有内容到SD卡根目录,然后将SD卡插到开发板。
  4. 对于战舰V3开发板,P8需要用跳线短接:PB10(TX)与GBC_RX,PB11(RX)与GBC_TX。
  5. 如果触摸屏不准,请按住KEY0不放,然后按复位,松开复位,进入触摸屏校准。此时松开KEY0,执行校准,即可对屏幕进行校准。

更多推荐

基于STM32的家庭气象站

本文发布于:2023-07-28 17:14:52,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1260078.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:气象站   家庭

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!