本帖最后由 iCEasy商城-小易 于 2025-9-28 13:49 编辑
本文转载自iCEasy商城口碑评测作者:ZXYYL
欢迎大家戳链接【GD32VW553-IOT V2】基于Socket的天气时钟,与原贴作者互动交流哦~
Socket的使用和服务器任务的搭建
开源口碑分享内容
在这里,使用了GD32VW553 -IOT V2开发板制作了一个天气时钟简易版,由于不想去搞UI所以就通过文字的方式显示数据,这款天气时钟是基于Socket的通信,需要一个VMware服务器(或者云服务器)进行高德天气API的解析,之所以不直接去解析,是因为高德地图API是基于HTTPS的协议进行通信,通过Socket无法简单的制作Https的客户端(和风天气是基于Https的,并且返回的数据被gzip压缩过了,单片机很难直接解析),也就是在完成程序编写以后,才发现SDK里面继集成了MbedTLS库,可以直接与Https的服务器进行文件的传输,所以准备接下来再做一个可以直接交互的Demo,这里我们着重于Socket网络服务器的搭建和单片机Scket的使用,毕竟在服务器环境下,可以看到单片机和服务器的传输情况,而直接去和高德服务器交互的话,如果没有经验,很容易出现各种状况。 首先介绍一下高德地图API的用户Key的获取,个人用户免费的天气API的调用是每个月5000次,也就是每小时最多调取6次,所以使用服务器进行调取,当出现不止一个设备调用天气时,只需要我的服务器读取保存在文件里的天气数据即可,无需再和高德API交互,并且高德地图的天气数据是每隔半小时更新一次,所以在服务器上每隔15分钟更新一次天气数据到文件里,单片机访问数据服务器就读取文件数据返回即可。 首先登录高德地图官方网站,根据使用手册引导注册好用户Key,注册好的Key如下(当然可使用其他的天气API,通过python解析还是蛮方便的): 接下来就是按照官方的手册进行url的编写: 服务器的代码编写如下: - import requests
- import json
- def Weather_Data_Write_To_File():
- Weather_Data = [None] * 8
- dict = Weathet_Data_Get()
- print(dict)
- print(dict['lives'][0]["weather"])
- Weather_Data[0] = dict['lives'][0]['province']
- Weather_Data[1] = dict['lives'][0]['city']
- Weather_Data[2] = dict['lives'][0]['weather']
- Weather_Data[4] = dict['lives'][0]['windpower']
- Weather_Data[5] = dict['lives'][0]['temperature_float']
- Weather_Data[6] = dict['lives'][0]['humidity_float']
- Weather_Data[7] = dict['lives'][0]['reporttime']
- if dict['lives'][0]['winddirection'] == '无风向':
- Weather_Data[3] = 'No_Wind'
- elif dict['lives'][0]['winddirection'] == '东北':
- Weather_Data[3] = 'NorthEast'
- elif dict['lives'][0]['winddirection'] == '东':
- Weather_Data[3] = 'East'
- elif dict['lives'][0]['winddirection'] == '东南':
- Weather_Data[3] = 'SouthEast'
- elif dict['lives'][0]['winddirection'] == '南':
- Weather_Data[3] = 'South'
- elif dict['lives'][0]['winddirection'] == '西':
- Weather_Data[3] = 'West'
- elif dict['lives'][0]['winddirection'] == '西北':
- Weather_Data[3] = 'NorthWest'
- elif dict['lives'][0]['winddirection'] == '北':
- Weather_Data[3] = 'North'
- else:
- Weather_Data[3] = 'Direction_Unknown'
- print(Weather_Data)
- with open('Weather_Data/Weather_Data.wea','a') as f:
- f.write("{}!{}!{}!{}!{}!{}!{}!{}!{}\r\n".format(Weather_Data[0],Weather_Data[1],Weather_Data[2],Weather_Data[3],Weather_Data[4], \
- Weather_Data[5],Weather_Data[6],str(Weather_Data[7]).split(' ',1)[0], \
- str(Weather_Data[7]).split(' ',1)[1]))
- print(Weather_Data[7])
- def Weathet_Data_Get():
- Weather = requests.get('https://restapi.amap.com/v3/weather/weatherInfo?city=320582&key=<your_Key>')
- return Weather.json()
- if __name__ == "__main__":
- Weather_Data_Write_To_File()
注意,由于返回的Json格式如下,所以使用单片机解析中文显示需要对中文的编码进行解析,这样的话需要更多的操作,写起来也不是很方便,作为简单的项目,这里直接把返回的城市列表和天气进行翻译成英文,直接显示即可。 - {
- "status" :
- "1",
- "count" :
- "1",
- "info" :
- "OK",
- "infocode" :
- "10000",
- "lives" :
- [
- "0" :
- {
- "province" :
- "北京",
- "city" :
- "东城区",
- "adcode" :
- "110101",
- "weather" :
- "阴",
- "temperature" :
- "18",
- "winddirection" :
- "西南",
- "windpower" :
- "≤3",
- "humidity" :
- "65",
- "reporttime" :
- "2025-09-18 22:33:38",
- "temperature_float" :
- "18.0",
- "humidity_float" :
- "65.0"
- }
- ]
- }
天气部分由于很多,单片机处理起来很不方便,所以选择翻译好以后回传显示即可(通过一个字典)。 服务器需要进行定时任务进行天气数据的获取,获取的文件保存在.wea文件里。 需要使用crontab进行定时任务的编写。 - # Edit this file to introduce tasks to be run by cron.
- #
- # Each task to run has to be defined through a single line
- # indicating with different fields when the task will be run
- # and what command to run for the task
- #
- # To define the time you can provide concrete values for
- # minute (m), hour (h), day of month (dom), month (mon),
- # and day of week (dow) or use '*' in these fields (for 'any').
- #
- # Notice that tasks will be started based on the cron's system
- # daemon's notion of time and timezones.
- #
- # Output of the crontab jobs (including errors) is sent through
- # email to the user the crontab file belongs to (unless redirected).
- #
- # For example, you can run a backup of all your user accounts
- # at 5 a.m every week with:
- # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
- #
- # For more information see the manual pages of crontab(5) and cron(8)
- #
- # m h dom mon dow command
- */30 * * * * /usr/bin/python3 /home/zzk/Socket/Weather.py >> /home/zzk/Socket/Log.lg 2>&1
- python脚本的输出在Log.lg文件里保存。
- 我们的任务是每隔半小时进行数据的获取。
- 接下来开始进行和单片机交互的Socket服务器的编写:
- import socket
- import threading
- import time
- def handle_client(client_socket, client_address):
- """处理客户端连接,接收数据并返回相同数据"""
- print(f"新连接: {client_address}")
- try:
- # 持续接收客户端数据
- while True:
- # 接收数据,缓冲区大小为1024字节
- data = client_socket.recv(1024)
- # 如果没有收到数据,说明客户端已断开连接
- if not data:
- print(f"客户端 {client_address} 断开连接")
- break
- Receive_Data = data.decode('utf-8')
- print(f"从 {client_address} 收到数据: {Receive_Data}")
- # 将收到的数据原样返回给客户端
- if Receive_Data == "Get_Time":
- Time = time.strftime("%Y:%m:%d:%H:%M:%S",time.localtime())
- client_socket.sendall(Time.encode('ascii'))
- print(f"传回数据:{Time}")
- elif Receive_Data == "Get_Weather":
- client_socket.sendall(Weather_Data_Get().encode('ascii'))
- print(f"传回数据:{Weather_Data_Get()}")
- else:
- client_socket.sendall("Mesange_Error".encode('ascii'))
- print(f"回传数据:{'Mesange_Error'}")
- except Exception as e:
- print(f"处理客户端 {client_address} 时出错: {e}")
- finally:
- # 关闭客户端连接
- client_socket.close()
- def Weather_Data_Get():
- with open("/home/zzk/Socket/Weather_Data/Weather_Data.wea","r",encoding="utf-8") as Fw:
- Wea_Str = Fw.readlines()
- Wea_List = Wea_Str[-1].split('!',8)
- Wea_List[2] = Weather_Condition_Deal(Wea_List[2])
- Wea_List[0] = 'Jiangsu'
- Wea_List[1] = 'ZhangjiaGang'
- if Wea_List[4] == '≤3':
- Wea_List[4] = '<3'
- Deal_Str = (f"{Wea_List[0]}_{Wea_List[1]}_{Wea_List[2]}_{Wea_List[3]}_{Wea_List[4]}_{Wea_List[5]}_"
- f"{Wea_List[6]}_{Wea_List[7]}_{Wea_List[8].strip()}")
- print(f"Log:{Deal_Str}")
- return Deal_Str
- def start_server(host='127.0.0.1', port=1234): # 修改为 0.0.0.0
- """启动服务器并监听连接"""
- # 创建TCP socket
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 允许端口重用,避免程序重启时出现"地址已在使用"错误
- server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- try:
- # 绑定到指定的IP和端口
- server_socket.bind((host, port))
- print(f"服务器已绑定到 {host}:{port}")
- # 开始监听,最大连接数为5
- server_socket.listen(5)
- print(f"服务器开始监听,等待连接...")
- while True:
- # 接受客户端连接
- client_socket, client_address = server_socket.accept()
- # 创建线程处理客户端请求,实现多客户端同时连接
- client_thread = threading.Thread(
- target=handle_client,
- args=(client_socket, client_address)
- )
- client_thread.start()
- except Exception as e:
- print(f"服务器出错: {e}")
- finally:
- # 关闭服务器socket
- server_socket.close()
- print("服务器已关闭")
- def Weather_Condition_Deal(Condition : str):
- weather_translation = {
- "晴": "Sunny",
- "少云": "Partly Cloudy",
- "晴间多云": "Sun & Clouds",
- "多云": "Cloudy",
- "阴": "Overcast",
- "有风": "Windy",
- "平静": "Calm",
- "微风": "Light Breeze",
- "和风": "Mod Breeze",
- "清风": "Fresh Breeze",
- "强风/劲风": "Strong Wind",
- "疾风": "Near Gale",
- "大风": "Gale",
- "烈风": "Strong Gale",
- "风暴": "Storm",
- "狂爆风": "Violent Storm",
- "飓风": "Hurricane",
- "热带风暴": "Trop Storm",
- "霾": "Haze",
- "中度霾": "Mod Haze",
- "重度霾": "Heavy Haze",
- "严重霾": "Severe Haze",
- "阵雨": "Showers",
- "雷阵雨": "Thunder Showers",
- "雷阵雨并伴有冰雹": "T-Storm w/Hail",
- "小雨": "Light Rain",
- "中雨": "Mod Rain",
- "大雨": "Heavy Rain",
- "暴雨": "Torrential Rain",
- "大暴雨": "Heavy Downpour",
- "特大暴雨": "Extreme Rain",
- "强阵雨": "Heavy Showers",
- "强雷阵雨": "Heavy T-Storm",
- "极端降雨": "Extreme Rainfall",
- "毛毛雨/细雨": "Drizzle",
- "雨": "Rain",
- "小雨-中雨": "Light-Mod Rain",
- "中雨-大雨": "Mod-Heavy Rain",
- "大雨-暴雨": "Heavy-Torrential",
- "暴雨-大暴雨": "Torrential-Heavy",
- "大暴雨-特大暴雨": "Heavy-Extreme",
- "雨雪天气": "Rain & Snow",
- "雨夹雪": "Sleet",
- "阵雨夹雪": "Showers w/Snow",
- "冻雨": "Freezing Rain",
- "雪": "Snow",
- "阵雪": "Snow Showers",
- "小雪": "Light Snow",
- "中雪": "Mod Snow",
- "大雪": "Heavy Snow",
- "暴雪": "Blizzard",
- "小雪-中雪": "Light-Mod Snow",
- "中雪-大雪": "Mod-Heavy Snow",
- "大雪-暴雪": "Heavy Snow-Bliz",
- "浮尘": "Dust",
- "扬沙": "Blowing Sand",
- "沙尘暴": "Sandstorm",
- "强沙尘暴": "Severe Sandstorm",
- "龙卷风": "Tornado",
- "雾": "Fog",
- "浓雾": "Dense Fog",
- "强浓雾": "Heavy Fog",
- "轻雾": "Mist",
- "大雾": "Thick Fog",
- "特强浓雾": "Extreme Fog",
- "热": "Hot",
- "冷": "Cold",
- "未知": "Unknown"
- }
- return weather_translation[Condition]
- if __name__ == "__main__":
- # 启动服务器,默认使用1234端口
- # 如需更改端口,可以修改port参数,如start_server(port=9999)
- start_server(host = '0.0.0.0')
如此实现了最多5个设备并发的交互的方法了,由于设备数量少,5个连接即可满足使用(因为还有自己编写的调试脚本)。 调试脚本如下: - import socket
- def start_client():
- # 创建TCP/IP套接字
- client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 服务器地址和端口
- server_address = ("127.0.0.1", 1234)
- print(f"连接到服务器 {server_address[0]}:{server_address[1]}")
- try:
- # 连接到服务器
- client_socket.connect(server_address)
- # 发送数据
- message = "Get_Weather"
- print(f"发送消息: {message}")
- client_socket.sendall(message.encode('utf-8'))
- # 接收服务器响应
- data = client_socket.recv(1024)
- print(f"收到服务器响应: {data.decode('ascii')}")
- # 发送数据
- message = "Get_Time"
- print(f"发送消息: {message}")
- client_socket.sendall(message.encode('utf-8'))
- # 接收服务器响应
- data = client_socket.recv(1024)
- print(f"收到服务器响应: {data.decode('ascii')}")
- finally:
- # 关闭套接字
- client_socket.close()
- print("客户端已关闭连接")
- if __name__ == "__main__":
- start_client()
响应如下: 这就是响应的数据格式,接下来就可以进行数据的解析操作了。 数据解析依赖Freertos的SDK操作,通过官方的SDK进行开发操作。 - /*
- * My_Wifi_Connect.h
- *
- * Created on: 2025年9月10日
- * Author: 19651
- */
- #ifndef MY_WIFI_CONNECT_H_
- #define MY_WIFI_CONNECT_H_
- void wifi_connect_ap(void * para);
- void wifi_start_ap(void *para);
- void LED_Blink(void *para);
- void wifi_start_ap_1(void *para);
- void Socket_Test(void);
- void Get_Data_Manage(void* Para);
- void Socket_Deal(void *Para);
- void OLED_Show(void *Para);
- void OLED_Control(void *Para);
- void Get_Data_Deal(void);
- typedef enum{
- OLED_Clock,
- OLED_Weather_Condition,
- OLED_Weather_Tem_Hyd,
- }OLED_WEATHER;
- typedef enum{
- Wifi_Socket_Get_Error,
- Wifi_Socket_Server_Error,
- Wifi_Socket_Normal
- }Wifi_Data_condition;
- typedef enum{
- Socket_Get_Time,
- Socket_Get_Weather
- }Which_Data_To_GET;
- typedef enum{
- OLED_Wifi_Connect,
- OLED_Wifi_Disconnect
- }Wifi_Connect_STATUS;
- typedef struct{
- char Provience[10];
- char Location[15];
- char Weather_Condition[21];
- char Hyd[5];
- char TEM[5];
- char Update_Date[11];
- char Update_Tim[11];
- char Wind_Direction[11];
- char Wind_Intensity[2];
- }WEATHER_DATA;
- #endif /* MY_WIFI_CONNECT_H_ */
- /*
- * My_Wifi_Connect.c
- *
- * Created on: 2025年9月10日
- * Author: 19651
- */
- #include "wifi_management.h"
- #include "My_Wifi_Connect.h"
- #include <stdint.h>
- #include "gd32vw55x_gpio.h"
- #include "My_Wifi_Connect.h"
- #include "stdbool.h"
- #include "OLED.h"
- #include "wrapper_os.h"
- #include "sockets.h"
- #include "string.h"
- void* WIFI_Connect_Status = NULL;
- OLED_WEATHER OLED_Weather = OLED_Weather_Tem_Hyd;
- Wifi_Data_condition Wifi_Data_Condition = Wifi_Socket_Normal;
- Which_Data_To_GET Which_Data_To_Get = Socket_Get_Weather;
- //Which_Data_To_GET Which_Data_To_Get = Socket_Get_Time;
- Wifi_Connect_STATUS Wifi_Connect_Status = OLED_Wifi_Disconnect;
- WEATHER_DATA Weather_Data ;
- extern rtc_parameter_struct RTC_Init;
- static bool Oled_Status_Chnaged = false;
- void wifi_connect_ap(void * para)
- {
- while(1)
- {
- int status = 0;
- char *ssid = "你的wifi账号";
- char *password = "你的Wifi密码";
- status = wifi_management_connect(ssid, password, true);
- if (status != 0) {
- }
- printf("Wifi_connect_Task\r\n");
- sys_task_notify(WIFI_Connect_Status,false);
- printf("Wifi_connect_Weak_Up\r\n");
- sys_task_delete(NULL);
- }
- }
- void LED_Blink(void *para)
- {
- for(;;)
- {
- gpio_bit_set(GPIOA,GPIO_PIN_3);
- sys_ms_sleep(500);
- gpio_bit_reset(GPIOA,GPIO_PIN_3);
- sys_ms_sleep(500);
- }
- }
- void *Socket_Para = NULL;
- void Socket_Deal(void *Para)
- {
- int vif_idx = WIFI_VIF_INDEX_DEFAULT;
- bool Wifi_Status;
- static bool Socket_Creat = true;
- for(;;)
- {
- Wifi_Status = wifi_vif_is_sta_connected(vif_idx);
- if(Wifi_Status)
- {
- Wifi_Connect_Status = OLED_Wifi_Connect;
- if(Socket_Creat)
- {
- Socket_Para = sys_task_create(NULL, (const uint8_t *)"Socket_Manager", NULL, 512, 0, 0, OS_TASK_PRIORITY(3), Get_Data_Manage, NULL);
- Socket_Creat = false;
- }
- sys_ms_sleep(500);
- }
- else
- {
- Wifi_Connect_Status = OLED_Wifi_Disconnect;
- //Socket_Creat = true;
- sys_task_create(NULL, (const uint8_t *)"Wifi_Connect2", NULL, 256, 0, 0, OS_TASK_PRIORITY(0), wifi_connect_ap, NULL);
- sys_task_wait_notification(-1);
- }
- sys_ms_sleep(200);
- }
- }
- char Buffer1[90];
- void Socket_Test(void)
- {
- struct sockaddr_in server_addr;
- int fd;
- const char *send_data;
- if(Which_Data_To_Get == Socket_Get_Time)
- {
- send_data = "Get_Time";
- }
- else
- {
- send_data = "Get_Weather";
- }
- int send_len = strlen(send_data);
- int recv_len;
- // 初始化服务器地址
- memset(&server_addr, 0, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(你的服务器端口);
- server_addr.sin_addr.s_addr = inet_addr("你的服务器ipv4地址");
- memset(Buffer1, 0, sizeof(Buffer1)); // 使用sizeof更安全
- // 1. 创建TCP socket
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd < 0)
- {
- sys_ms_sleep(5000);
- return;
- }
- // 2. 连接服务器
- if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
- {
- close(fd);
- sys_ms_sleep(5000);
- return;
- }
- printf("Connect_Success Send Data...\r\n");
- // 3. 发送数据并检查结果
- if (send(fd, send_data, send_len, 0) != send_len)
- {
- printf("Send_Error\r\n");
- close(fd);
- sys_ms_sleep(5000);
- return;
- }
- // 4. 接收数据 - 调整缓冲区大小,正确处理非阻塞模式
- recv_len = recv(fd, Buffer1, 90, 0);
- if (recv_len < 0)
- {
- Wifi_Data_Condition = Wifi_Socket_Get_Error;
- }
- else if (recv_len == 0)
- {
- Wifi_Data_Condition = Wifi_Socket_Server_Error;
- }
- // 5. 显示数据(缩小临界区范围)
- printf("Receive:%s\r\n",Buffer1);
- Get_Data_Deal();
- // 6. 关闭连接
- close(fd);
- }
- void Get_Data_Manage(void* Para)
- {
- for(;;)
- {
- if(Which_Data_To_Get == Socket_Get_Time)
- {
- Which_Data_To_Get = Socket_Get_Weather;
- Socket_Test();
- printf("Get_Time_Task\r\n");
- sys_ms_sleep(60000);
- }
- else
- {
- Which_Data_To_Get = Socket_Get_Time;
- Socket_Test();
- printf("Get_Weather_Task\r\n");
- sys_ms_sleep(2000);
- }
- }
- }
- void Get_Data_Deal(void)
- {
- if(Which_Data_To_Get == Socket_Get_Time)
- {
- sys_enter_critical();
- RTC_Init.year = (strtol (strtok(Buffer1,":"),NULL,16)) & 0xff;
- RTC_Init.month = strtol (strtok(NULL,":"),NULL,16);
- RTC_Init.date = strtol (strtok(NULL,":"),NULL,16);
- RTC_Init.hour = strtol (strtok(NULL,":"),NULL,16);
- RTC_Init.minute = strtol (strtok(NULL,":"),NULL,16);
- RTC_Init.second = strtol (strtok(NULL,":"),NULL,16);
- printf("%x,%x,%x\r\n",RTC_Init.month,RTC_Init.minute,RTC_Init.second);
- rtc_init_mode_enter();
- rtc_init(&RTC_Init);
- rtc_init_mode_exit();
- sys_exit_critical();
- }
- else
- {
- char *p = strtok(Buffer1,"_");
- strcpy(Weather_Data.Provience,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Location,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Weather_Condition,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Wind_Direction,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Wind_Intensity,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.TEM,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Hyd,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Update_Date,p);
- p = strtok(NULL,"_");
- strcpy(Weather_Data.Update_Tim,p);
- }
- }
- char Buffer[20];
- rtc_parameter_struct Rtc_Oled;
- void OLED_Show(void *Para)
- {
- for(;;)
- {
- sys_enter_critical();
- if(Oled_Status_Chnaged)
- {
- OLED_Clear();
- Oled_Status_Chnaged = false;
- }
- if(OLED_Weather == OLED_Clock)
- {
- sprintf(Buffer," Current_Time ");
- OLED_ShowString(1, 1, Buffer);
- printf("OLED_Task1\r\n");
- rtc_current_time_get(&Rtc_Oled);
- sprintf(Buffer," 20%02x:%02x:%02x ",Rtc_Oled.year,Rtc_Oled.month,Rtc_Oled.date);
- OLED_ShowString(2, 1, Buffer);
- sprintf(Buffer," %02x:%02x:%02x ",Rtc_Oled.hour,Rtc_Oled.minute,Rtc_Oled.second);
- OLED_ShowString(3, 1, Buffer);
- if(Wifi_Connect_Status ==OLED_Wifi_Disconnect)
- {
- OLED_ShowString(4, 1, " Wifi_Disconnect");
- }
- else if(Wifi_Connect_Status == OLED_Wifi_Connect)
- {
- OLED_ShowString(4, 1, " Wifi_Connect ");
- }
- }
- else if(OLED_Weather == OLED_Weather_Condition)
- {
- sprintf(Buffer,"Pro:%s",Weather_Data.Provience);
- OLED_ShowString(1,1,Buffer);
- sprintf(Buffer,"Loc:%s",Weather_Data.Location);
- OLED_ShowString(2,1,Buffer);
- sprintf(Buffer,"Weather: %02x:%02x",RTC_Init.hour,RTC_Init.minute);
- OLED_ShowString(3,1,Buffer);
- sprintf(Buffer,"%s",Weather_Data.Weather_Condition);
- OLED_ShowString(4,1,Buffer);
- }
- else if(OLED_Weather == OLED_Weather_Tem_Hyd)
- {
- sprintf(Buffer,"Tem:%sHyd:%s",Weather_Data.TEM,Weather_Data.Hyd);
- OLED_ShowString(1,1,Buffer);
- sprintf(Buffer,"%s %s",Weather_Data.Wind_Direction,Weather_Data.Wind_Intensity);
- OLED_ShowString(2,1,Buffer);
- sprintf(Buffer,"Up_Dt:%s",Weather_Data.Update_Date);
- OLED_ShowString(3,1,Buffer);
- sprintf(Buffer,"Up_Tim:%s",Weather_Data.Update_Tim);
- OLED_ShowString(4,1,Buffer);
- }
- sys_exit_critical();
- sys_ms_sleep(1000);
- }
- }
- void OLED_Control(void *Para)
- {
- for(;;)
- {
- if(OLED_Weather == OLED_Clock)
- {
- OLED_Weather = OLED_Weather_Condition;
- }
- else if(OLED_Weather == OLED_Weather_Condition)
- {
- OLED_Weather = OLED_Weather_Tem_Hyd;
- }
- else if(OLED_Weather == OLED_Weather_Tem_Hyd)
- {
- OLED_Weather = OLED_Clock;
- }
- Oled_Status_Chnaged = true;
- sys_ms_sleep(5500);
- }
- }
- main.c:
- /*!
- \file main.c
- \brief Main loop of GD32VW55x SDK.
- \version 2023-07-20, V1.0.0, firmware for GD32VW55x
- */
- /*
- Copyright (c) 2023, GigaDevice Semiconductor Inc.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holder nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- OF SUCH DAMAGE.
- */
- #include <stdint.h>
- #include "wifi_export.h"
- #include "gd32vw55x_platform.h"
- #include "uart.h"
- #include "ble_init.h"
- #include "gd32vw55x.h"
- #include "wrapper_os.h"
- #include "cmd_shell.h"
- #include "atcmd.h"
- #include "util.h"
- #include "wlan_config.h"
- #include "wifi_init.h"
- #include "user_setting.h"
- #include "version.h"
- #include "_build_date.h"
- #ifdef CONFIG_FATFS_SUPPORT
- #include "fatfs.h"
- #endif
- #include "ble_app_config.h"
- #include "app_cmd.h"
- #ifdef CONFIG_AZURE_IOT_SUPPORT
- #include "azure_entry.h"
- #endif
- #include "My_Wifi_Connect.h"
- #include "OLED.h"
- #include <string.h>
- #include "W25Q64.h"
- uint8_t Data[256];
- uint8_t Read[256];
- rtc_parameter_struct RTC_Init = {0} ;
- void LED_BSP_Init(void);
- /*!
- \brief Init applications.
- This function is called to initialize all the applications.
- \param[in] none.
- \param[out] none.
- \retval none.
- */
- static void application_init(void)
- {
- #if defined CONFIG_BASECMD || defined CONFIG_RF_TEST_SUPPORT || defined CONFIG_BLE_DTM_SUPPORT
- if (cmd_shell_init()) {
- dbg_print(ERR, "cmd shell init failed\r\n");
- }
- #endif
- #ifdef CONFIG_ATCMD
- if (atcmd_init()) {
- dbg_print(ERR, "atcmd init failed\r\n");
- }
- #endif
- util_init();
- user_setting_init();
- #ifdef CFG_BLE_SUPPORT
- #ifdef CONFIG_BLE_ALWAYS_ENABLE
- ble_init(true);
- #else
- ble_init(false);
- #endif // CONFIG_BLE_DEFAULT_INIT
- #endif // CFG_BLE_SUPPORT
- #ifdef CFG_WLAN_SUPPORT
- if (wifi_init()) {
- dbg_print(ERR, "wifi init failed\r\n");
- }
- #endif
- #ifdef CONFIG_FATFS_SUPPORT
- fatfs_mk_mount(NULL);
- #endif
- #ifdef CFG_MATTER
- MatterInit();
- #endif
- #ifdef CONFIG_AZURE_F527_DEMO_SUPPORT
- azure_task_start();
- #endif
- }
- #ifdef PLATFORM_OS_RTTHREAD
- /*!
- \brief Start task.
- This function is called to initialize all the applications in thread context.
- \param[in] param parameter passed to the task
- \param[out] none
- \retval none.
- */
- static void start_task(void *param)
- {
- (void)param;
- application_init();
- sys_task_delete(NULL);
- }
- #endif
- /*!
- \brief Main entry point.
- This function is called right after the booting process has completed.
- \param[in] none
- \param[out] none
- \retval none.
- */
- void OLED_Init_Config(void *para);
- void OLED_Show(void *Para);
- void Random_Data_Get(uint8_t Num);
- void W25q64_Test(void *Para);
- void W25Q64_Config(void);
- void Task_Delete(void *Para);
- void RTC_BSP_Init(void);
- void* W25Q64_Task = NULL;
- extern void* WIFI_Connect_Status;
- int main(void)
- {
- sys_os_init();
- platform_init();
- dbg_print(NOTICE, "SDK Version: %s\n", WIFI_GIT_REVISION);
- dbg_print(NOTICE, "Build date: %s\n", SDK_BUILD_DATE);
- #ifdef PLATFORM_OS_RTTHREAD
- if (sys_task_create_dynamic((const uint8_t *)"start_task",
- START_TASK_STACK_SIZE, OS_TASK_PRIORITY(START_TASK_PRIO), start_task, NULL) == NULL) {
- dbg_print(ERR, "Create start task failed\r\n");
- }
- #else
- application_init();
- #endif
- LED_BSP_Init();
- RTC_BSP_Init();
- W25Q64_Config();
- sys_task_create(NULL, (const uint8_t *)"oled_init", NULL, 1024, 0, 0, OS_TASK_PRIORITY(5), OLED_Init_Config, NULL);
- sys_task_create(NULL, (const uint8_t *)"LED_Blink", NULL, 256, 0, 0, OS_TASK_PRIORITY(1), LED_Blink, NULL);
- sys_task_create(NULL, (const uint8_t *)"oled_control", NULL, 256, 0, 0, OS_TASK_PRIORITY(4), OLED_Control, NULL);
- sys_task_create(NULL, (const uint8_t *)"Oled_Show", NULL, 512, 0, 0, OS_TASK_PRIORITY(4), OLED_Show, NULL);
- WIFI_Connect_Status = sys_task_create(NULL, (const uint8_t *)"Wifi_Status", NULL, 256, 0, 0, OS_TASK_PRIORITY(0), Socket_Deal, NULL);
- sys_os_start();
- }
- void OLED_Init_Config(void *para)
- {
- for(;;)
- {
- sys_enter_critical();
- OLED_Init();
- sys_exit_critical();
- sys_ms_sleep(100);
- sys_task_delete(NULL);
- }
- }
- void W25Q64_Config(void)
- {
- W25Q64_Init();
- }
- void Random_Data_Get(uint8_t Num)
- {
- int i=0;
- int32_t Get;
- for(i=0; i < Num ; i++)
- {
- Get = sys_random_bytes_get(Data+i,2);
- if(Get != 0)
- {
- printf("Random_Data_Generate_Error!\r\n");
- return;
- }
- }
- }
- void Buffer_Data_Print(uint8_t *BUffer)
- {
- for(int i=0;i < 256 / 8;i++)
- {
- {
- printf("%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\r\n",BUffer[0+i*8],BUffer[1+i*8],BUffer[2+i*8],\
- BUffer[3+i*8],BUffer[4+i*8],BUffer[5+i*8],BUffer[6+i*8],BUffer[7+i*8]);
- }
- }
- printf("-----------\r\n");
- }
- void RTC_BSP_Init(void)
- {
- uint32_t prescaler_a = 0, prescaler_s = 0;
- rcu_periph_clock_enable(RCU_PMU);
- pmu_backup_write_enable();
- rcu_osci_on(RCU_IRC32K);
- rcu_osci_stab_wait(RCU_IRC32K);
- rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
- prescaler_s = 0x13F;
- prescaler_a = 0x63;
- rcu_periph_clock_enable(RCU_RTC);
- rtc_register_sync_wait();
- RTC_Init.year = 0x00;
- RTC_Init.month = 0;
- RTC_Init.date = 0;
- RTC_Init.month = 0;
- RTC_Init.minute = 0;
- RTC_Init.second = 0;
- RTC_Init.factor_asyn = prescaler_a;
- RTC_Init.factor_syn = prescaler_s;
- rtc_init(&RTC_Init);
- }
- void W25q64_Test(void *Para)
- {
- for(;;)
- {
- sys_enter_critical();
- //Random_Data_Get(256);
- memset(Data, 0x55,256);
- Buffer_Data_Print(Data);
- //W25Q64_SectorErase(0);
- //W25Q64_PageProgram(0,Data,256);
- W25Q64_ReadData(0,Read,256);
- Buffer_Data_Print(Read);
- sys_exit_critical();
- sys_ms_sleep(1000);
- }
- }
- void LED_BSP_Init(void)
- {
- rcu_periph_clock_enable(RCU_GPIOB);
- gpio_mode_set(GPIOB,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_2);
- gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_2);
这就是对整个天气时钟的创建函数,对于OLED的函数和W25q64的代码,这里可以通过移植得到,这里就不给出了。 最后看一下效果吧: 时钟部分: 天气的省份地区和天气状况,时间的时和秒: 温湿度,风速风向和服务器获取到天气数据的时间:
这三个界面每隔5.5秒切换一次,没做过渡效果,直接切换,可以考虑在天气时钟的第二代版本里面去增加。 这就是如何在服务器上通过Socket与GD32VW553进行数据交换的方法。
|