【GD32VW553-IOT V2】基于Socket的天气时钟

[复制链接]
674|0
本帖最后由 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的编写:
服务器的代码编写如下:
  1. import requests
  2. import json
  3. def Weather_Data_Write_To_File():
  4. Weather_Data = [None] * 8
  5. dict = Weathet_Data_Get()
  6. print(dict)
  7. print(dict['lives'][0]["weather"])
  8. Weather_Data[0] = dict['lives'][0]['province']
  9. Weather_Data[1] = dict['lives'][0]['city']
  10. Weather_Data[2] = dict['lives'][0]['weather']
  11. Weather_Data[4] = dict['lives'][0]['windpower']
  12. Weather_Data[5] = dict['lives'][0]['temperature_float']
  13. Weather_Data[6] = dict['lives'][0]['humidity_float']
  14. Weather_Data[7] = dict['lives'][0]['reporttime']
  15. if dict['lives'][0]['winddirection'] == '无风向':
  16. Weather_Data[3] = 'No_Wind'
  17. elif dict['lives'][0]['winddirection'] == '东北':
  18. Weather_Data[3] = 'NorthEast'
  19. elif dict['lives'][0]['winddirection'] == '东':
  20. Weather_Data[3] = 'East'
  21. elif dict['lives'][0]['winddirection'] == '东南':
  22. Weather_Data[3] = 'SouthEast'
  23. elif dict['lives'][0]['winddirection'] == '南':
  24. Weather_Data[3] = 'South'
  25. elif dict['lives'][0]['winddirection'] == '西':
  26. Weather_Data[3] = 'West'
  27. elif dict['lives'][0]['winddirection'] == '西北':
  28. Weather_Data[3] = 'NorthWest'
  29. elif dict['lives'][0]['winddirection'] == '北':
  30. Weather_Data[3] = 'North'
  31. else:
  32. Weather_Data[3] = 'Direction_Unknown'
  33. print(Weather_Data)
  34. with open('Weather_Data/Weather_Data.wea','a') as f:
  35. f.write("{}!{}!{}!{}!{}!{}!{}!{}!{}\r\n".format(Weather_Data[0],Weather_Data[1],Weather_Data[2],Weather_Data[3],Weather_Data[4], \
  36. Weather_Data[5],Weather_Data[6],str(Weather_Data[7]).split(' ',1)[0], \
  37. str(Weather_Data[7]).split(' ',1)[1]))
  38. print(Weather_Data[7])
  39. def Weathet_Data_Get():
  40. Weather = requests.get('https://restapi.amap.com/v3/weather/weatherInfo?city=320582&key=<your_Key>')
  41. return Weather.json()
  42. if __name__ == "__main__":
  43. Weather_Data_Write_To_File()
注意,由于返回的Json格式如下,所以使用单片机解析中文显示需要对中文的编码进行解析,这样的话需要更多的操作,写起来也不是很方便,作为简单的项目,这里直接把返回的城市列表和天气进行翻译成英文,直接显示即可。
  1. {
  2. "status" :
  3. "1",
  4. "count" :
  5. "1",
  6. "info" :
  7. "OK",
  8. "infocode" :
  9. "10000",
  10. "lives" :
  11. [
  12. "0" :
  13. {
  14. "province" :
  15. "北京",
  16. "city" :
  17. "东城区",
  18. "adcode" :
  19. "110101",
  20. "weather" :
  21. "阴",
  22. "temperature" :
  23. "18",
  24. "winddirection" :
  25. "西南",
  26. "windpower" :
  27. "≤3",
  28. "humidity" :
  29. "65",
  30. "reporttime" :
  31. "2025-09-18 22:33:38",
  32. "temperature_float" :
  33. "18.0",
  34. "humidity_float" :
  35. "65.0"
  36. }
  37. ]
  38. }
天气部分由于很多,单片机处理起来很不方便,所以选择翻译好以后回传显示即可(通过一个字典)。
服务器需要进行定时任务进行天气数据的获取,获取的文件保存在.wea文件里。
需要使用crontab进行定时任务的编写。
  1. # Edit this file to introduce tasks to be run by cron.
  2. #
  3. # Each task to run has to be defined through a single line
  4. # indicating with different fields when the task will be run
  5. # and what command to run for the task
  6. #
  7. # To define the time you can provide concrete values for
  8. # minute (m), hour (h), day of month (dom), month (mon),
  9. # and day of week (dow) or use '*' in these fields (for 'any').
  10. #
  11. # Notice that tasks will be started based on the cron's system
  12. # daemon's notion of time and timezones.
  13. #
  14. # Output of the crontab jobs (including errors) is sent through
  15. # email to the user the crontab file belongs to (unless redirected).
  16. #
  17. # For example, you can run a backup of all your user accounts
  18. # at 5 a.m every week with:
  19. # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
  20. #
  21. # For more information see the manual pages of crontab(5) and cron(8)
  22. #
  23. # m h dom mon dow command
  24. */30 * * * * /usr/bin/python3 /home/zzk/Socket/Weather.py >> /home/zzk/Socket/Log.lg 2>&1
  25. python脚本的输出在Log.lg文件里保存。

  26. 我们的任务是每隔半小时进行数据的获取。

  27. 接下来开始进行和单片机交互的Socket服务器的编写:

  28. import socket
  29. import threading
  30. import time
  31. def handle_client(client_socket, client_address):
  32. """处理客户端连接,接收数据并返回相同数据"""
  33. print(f"新连接: {client_address}")

  34. try:
  35. # 持续接收客户端数据
  36. while True:
  37. # 接收数据,缓冲区大小为1024字节
  38. data = client_socket.recv(1024)

  39. # 如果没有收到数据,说明客户端已断开连接
  40. if not data:
  41. print(f"客户端 {client_address} 断开连接")
  42. break
  43. Receive_Data = data.decode('utf-8')
  44. print(f"从 {client_address} 收到数据: {Receive_Data}")
  45. # 将收到的数据原样返回给客户端
  46. if Receive_Data == "Get_Time":
  47. Time = time.strftime("%Y:%m:%d:%H:%M:%S",time.localtime())
  48. client_socket.sendall(Time.encode('ascii'))
  49. print(f"传回数据:{Time}")
  50. elif Receive_Data == "Get_Weather":
  51. client_socket.sendall(Weather_Data_Get().encode('ascii'))
  52. print(f"传回数据:{Weather_Data_Get()}")
  53. else:
  54. client_socket.sendall("Mesange_Error".encode('ascii'))
  55. print(f"回传数据:{'Mesange_Error'}")
  56. except Exception as e:
  57. print(f"处理客户端 {client_address} 时出错: {e}")

  58. finally:
  59. # 关闭客户端连接
  60. client_socket.close()
  61. def Weather_Data_Get():
  62. with open("/home/zzk/Socket/Weather_Data/Weather_Data.wea","r",encoding="utf-8") as Fw:
  63. Wea_Str = Fw.readlines()
  64. Wea_List = Wea_Str[-1].split('!',8)
  65. Wea_List[2] = Weather_Condition_Deal(Wea_List[2])
  66. Wea_List[0] = 'Jiangsu'
  67. Wea_List[1] = 'ZhangjiaGang'
  68. if Wea_List[4] == '≤3':
  69. Wea_List[4] = '<3'
  70. Deal_Str = (f"{Wea_List[0]}_{Wea_List[1]}_{Wea_List[2]}_{Wea_List[3]}_{Wea_List[4]}_{Wea_List[5]}_"
  71. f"{Wea_List[6]}_{Wea_List[7]}_{Wea_List[8].strip()}")
  72. print(f"Log:{Deal_Str}")
  73. return Deal_Str

  74. def start_server(host='127.0.0.1', port=1234): # 修改为 0.0.0.0
  75. """启动服务器并监听连接"""
  76. # 创建TCP socket
  77. server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  78. # 允许端口重用,避免程序重启时出现"地址已在使用"错误
  79. server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

  80. try:
  81. # 绑定到指定的IP和端口
  82. server_socket.bind((host, port))
  83. print(f"服务器已绑定到 {host}:{port}")

  84. # 开始监听,最大连接数为5
  85. server_socket.listen(5)
  86. print(f"服务器开始监听,等待连接...")

  87. while True:
  88. # 接受客户端连接
  89. client_socket, client_address = server_socket.accept()

  90. # 创建线程处理客户端请求,实现多客户端同时连接
  91. client_thread = threading.Thread(
  92. target=handle_client,
  93. args=(client_socket, client_address)
  94. )
  95. client_thread.start()

  96. except Exception as e:
  97. print(f"服务器出错: {e}")

  98. finally:
  99. # 关闭服务器socket
  100. server_socket.close()
  101. print("服务器已关闭")
  102. def Weather_Condition_Deal(Condition : str):
  103. weather_translation = {
  104. "晴": "Sunny",
  105. "少云": "Partly Cloudy",
  106. "晴间多云": "Sun & Clouds",
  107. "多云": "Cloudy",
  108. "阴": "Overcast",
  109. "有风": "Windy",
  110. "平静": "Calm",
  111. "微风": "Light Breeze",
  112. "和风": "Mod Breeze",
  113. "清风": "Fresh Breeze",
  114. "强风/劲风": "Strong Wind",
  115. "疾风": "Near Gale",
  116. "大风": "Gale",
  117. "烈风": "Strong Gale",
  118. "风暴": "Storm",
  119. "狂爆风": "Violent Storm",
  120. "飓风": "Hurricane",
  121. "热带风暴": "Trop Storm",
  122. "霾": "Haze",
  123. "中度霾": "Mod Haze",
  124. "重度霾": "Heavy Haze",
  125. "严重霾": "Severe Haze",
  126. "阵雨": "Showers",
  127. "雷阵雨": "Thunder Showers",
  128. "雷阵雨并伴有冰雹": "T-Storm w/Hail",
  129. "小雨": "Light Rain",
  130. "中雨": "Mod Rain",
  131. "大雨": "Heavy Rain",
  132. "暴雨": "Torrential Rain",
  133. "大暴雨": "Heavy Downpour",
  134. "特大暴雨": "Extreme Rain",
  135. "强阵雨": "Heavy Showers",
  136. "强雷阵雨": "Heavy T-Storm",
  137. "极端降雨": "Extreme Rainfall",
  138. "毛毛雨/细雨": "Drizzle",
  139. "雨": "Rain",
  140. "小雨-中雨": "Light-Mod Rain",
  141. "中雨-大雨": "Mod-Heavy Rain",
  142. "大雨-暴雨": "Heavy-Torrential",
  143. "暴雨-大暴雨": "Torrential-Heavy",
  144. "大暴雨-特大暴雨": "Heavy-Extreme",
  145. "雨雪天气": "Rain & Snow",
  146. "雨夹雪": "Sleet",
  147. "阵雨夹雪": "Showers w/Snow",
  148. "冻雨": "Freezing Rain",
  149. "雪": "Snow",
  150. "阵雪": "Snow Showers",
  151. "小雪": "Light Snow",
  152. "中雪": "Mod Snow",
  153. "大雪": "Heavy Snow",
  154. "暴雪": "Blizzard",
  155. "小雪-中雪": "Light-Mod Snow",
  156. "中雪-大雪": "Mod-Heavy Snow",
  157. "大雪-暴雪": "Heavy Snow-Bliz",
  158. "浮尘": "Dust",
  159. "扬沙": "Blowing Sand",
  160. "沙尘暴": "Sandstorm",
  161. "强沙尘暴": "Severe Sandstorm",
  162. "龙卷风": "Tornado",
  163. "雾": "Fog",
  164. "浓雾": "Dense Fog",
  165. "强浓雾": "Heavy Fog",
  166. "轻雾": "Mist",
  167. "大雾": "Thick Fog",
  168. "特强浓雾": "Extreme Fog",
  169. "热": "Hot",
  170. "冷": "Cold",
  171. "未知": "Unknown"
  172. }
  173. return weather_translation[Condition]
  174. if __name__ == "__main__":
  175. # 启动服务器,默认使用1234端口
  176. # 如需更改端口,可以修改port参数,如start_server(port=9999)
  177. start_server(host = '0.0.0.0')
如此实现了最多5个设备并发的交互的方法了,由于设备数量少,5个连接即可满足使用(因为还有自己编写的调试脚本)。
调试脚本如下:
  1. import socket


  2. def start_client():
  3. # 创建TCP/IP套接字
  4. client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

  5. # 服务器地址和端口
  6. server_address = ("127.0.0.1", 1234)
  7. print(f"连接到服务器 {server_address[0]}:{server_address[1]}")

  8. try:
  9. # 连接到服务器
  10. client_socket.connect(server_address)

  11. # 发送数据
  12. message = "Get_Weather"
  13. print(f"发送消息: {message}")
  14. client_socket.sendall(message.encode('utf-8'))

  15. # 接收服务器响应
  16. data = client_socket.recv(1024)
  17. print(f"收到服务器响应: {data.decode('ascii')}")
  18. # 发送数据
  19. message = "Get_Time"
  20. print(f"发送消息: {message}")
  21. client_socket.sendall(message.encode('utf-8'))

  22. # 接收服务器响应
  23. data = client_socket.recv(1024)
  24. print(f"收到服务器响应: {data.decode('ascii')}")

  25. finally:
  26. # 关闭套接字
  27. client_socket.close()
  28. print("客户端已关闭连接")


  29. if __name__ == "__main__":
  30. start_client()
响应如下:
这就是响应的数据格式,接下来就可以进行数据的解析操作了。
数据解析依赖Freertos的SDK操作,通过官方的SDK进行开发操作。
  1. /*
  2. * My_Wifi_Connect.h
  3. *
  4. * Created on: 2025年9月10日
  5. * Author: 19651
  6. */

  7. #ifndef MY_WIFI_CONNECT_H_
  8. #define MY_WIFI_CONNECT_H_
  9. void wifi_connect_ap(void * para);
  10. void wifi_start_ap(void *para);
  11. void LED_Blink(void *para);
  12. void wifi_start_ap_1(void *para);
  13. void Socket_Test(void);
  14. void Get_Data_Manage(void* Para);
  15. void Socket_Deal(void *Para);
  16. void OLED_Show(void *Para);
  17. void OLED_Control(void *Para);
  18. void Get_Data_Deal(void);
  19. typedef enum{
  20. OLED_Clock,
  21. OLED_Weather_Condition,
  22. OLED_Weather_Tem_Hyd,
  23. }OLED_WEATHER;
  24. typedef enum{
  25. Wifi_Socket_Get_Error,
  26. Wifi_Socket_Server_Error,
  27. Wifi_Socket_Normal


  28. }Wifi_Data_condition;
  29. typedef enum{
  30. Socket_Get_Time,
  31. Socket_Get_Weather
  32. }Which_Data_To_GET;
  33. typedef enum{
  34. OLED_Wifi_Connect,
  35. OLED_Wifi_Disconnect

  36. }Wifi_Connect_STATUS;
  37. typedef struct{
  38. char Provience[10];
  39. char Location[15];
  40. char Weather_Condition[21];
  41. char Hyd[5];
  42. char TEM[5];
  43. char Update_Date[11];
  44. char Update_Tim[11];
  45. char Wind_Direction[11];
  46. char Wind_Intensity[2];
  47. }WEATHER_DATA;
  48. #endif /* MY_WIFI_CONNECT_H_ */


  49. /*
  50. * My_Wifi_Connect.c
  51. *
  52. * Created on: 2025年9月10日
  53. * Author: 19651
  54. */
  55. #include "wifi_management.h"
  56. #include "My_Wifi_Connect.h"
  57. #include <stdint.h>
  58. #include "gd32vw55x_gpio.h"
  59. #include "My_Wifi_Connect.h"
  60. #include "stdbool.h"
  61. #include "OLED.h"
  62. #include "wrapper_os.h"
  63. #include "sockets.h"
  64. #include "string.h"
  65. void* WIFI_Connect_Status = NULL;
  66. OLED_WEATHER OLED_Weather = OLED_Weather_Tem_Hyd;
  67. Wifi_Data_condition Wifi_Data_Condition = Wifi_Socket_Normal;
  68. Which_Data_To_GET Which_Data_To_Get = Socket_Get_Weather;
  69. //Which_Data_To_GET Which_Data_To_Get = Socket_Get_Time;
  70. Wifi_Connect_STATUS Wifi_Connect_Status = OLED_Wifi_Disconnect;
  71. WEATHER_DATA Weather_Data ;
  72. extern rtc_parameter_struct RTC_Init;
  73. static bool Oled_Status_Chnaged = false;
  74. void wifi_connect_ap(void * para)
  75. {
  76. while(1)
  77. {
  78. int status = 0;
  79. char *ssid = "你的wifi账号";
  80. char *password = "你的Wifi密码";
  81. status = wifi_management_connect(ssid, password, true);
  82. if (status != 0) {
  83. }
  84. printf("Wifi_connect_Task\r\n");
  85. sys_task_notify(WIFI_Connect_Status,false);
  86. printf("Wifi_connect_Weak_Up\r\n");
  87. sys_task_delete(NULL);

  88. }
  89. }
  90. void LED_Blink(void *para)
  91. {
  92. for(;;)
  93. {
  94. gpio_bit_set(GPIOA,GPIO_PIN_3);
  95. sys_ms_sleep(500);
  96. gpio_bit_reset(GPIOA,GPIO_PIN_3);
  97. sys_ms_sleep(500);
  98. }

  99. }
  100. void *Socket_Para = NULL;
  101. void Socket_Deal(void *Para)
  102. {
  103. int vif_idx = WIFI_VIF_INDEX_DEFAULT;
  104. bool Wifi_Status;
  105. static bool Socket_Creat = true;
  106. for(;;)
  107. {

  108. Wifi_Status = wifi_vif_is_sta_connected(vif_idx);

  109. if(Wifi_Status)
  110. {
  111. Wifi_Connect_Status = OLED_Wifi_Connect;
  112. if(Socket_Creat)
  113. {
  114. Socket_Para = sys_task_create(NULL, (const uint8_t *)"Socket_Manager", NULL, 512, 0, 0, OS_TASK_PRIORITY(3), Get_Data_Manage, NULL);
  115. Socket_Creat = false;
  116. }
  117. sys_ms_sleep(500);

  118. }
  119. else
  120. {
  121. Wifi_Connect_Status = OLED_Wifi_Disconnect;
  122. //Socket_Creat = true;
  123. sys_task_create(NULL, (const uint8_t *)"Wifi_Connect2", NULL, 256, 0, 0, OS_TASK_PRIORITY(0), wifi_connect_ap, NULL);
  124. sys_task_wait_notification(-1);

  125. }
  126. sys_ms_sleep(200);


  127. }

  128. }
  129. char Buffer1[90];
  130. void Socket_Test(void)
  131. {
  132. struct sockaddr_in server_addr;
  133. int fd;
  134. const char *send_data;
  135. if(Which_Data_To_Get == Socket_Get_Time)
  136. {
  137. send_data = "Get_Time";
  138. }
  139. else
  140. {
  141. send_data = "Get_Weather";
  142. }
  143. int send_len = strlen(send_data);
  144. int recv_len;

  145. // 初始化服务器地址
  146. memset(&server_addr, 0, sizeof(server_addr));
  147. server_addr.sin_family = AF_INET;
  148. server_addr.sin_port = htons(你的服务器端口);
  149. server_addr.sin_addr.s_addr = inet_addr("你的服务器ipv4地址");
  150. memset(Buffer1, 0, sizeof(Buffer1)); // 使用sizeof更安全

  151. // 1. 创建TCP socket
  152. fd = socket(AF_INET, SOCK_STREAM, 0);
  153. if (fd < 0)
  154. {
  155. sys_ms_sleep(5000);
  156. return;
  157. }

  158. // 2. 连接服务器
  159. if (connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  160. {
  161. close(fd);
  162. sys_ms_sleep(5000);
  163. return;
  164. }

  165. printf("Connect_Success Send Data...\r\n");

  166. // 3. 发送数据并检查结果
  167. if (send(fd, send_data, send_len, 0) != send_len)
  168. {
  169. printf("Send_Error\r\n");
  170. close(fd);
  171. sys_ms_sleep(5000);
  172. return;
  173. }

  174. // 4. 接收数据 - 调整缓冲区大小,正确处理非阻塞模式
  175. recv_len = recv(fd, Buffer1, 90, 0);
  176. if (recv_len < 0)
  177. {
  178. Wifi_Data_Condition = Wifi_Socket_Get_Error;
  179. }
  180. else if (recv_len == 0)
  181. {
  182. Wifi_Data_Condition = Wifi_Socket_Server_Error;
  183. }

  184. // 5. 显示数据(缩小临界区范围)
  185. printf("Receive:%s\r\n",Buffer1);
  186. Get_Data_Deal();
  187. // 6. 关闭连接
  188. close(fd);

  189. }

  190. void Get_Data_Manage(void* Para)
  191. {
  192. for(;;)
  193. {
  194. if(Which_Data_To_Get == Socket_Get_Time)
  195. {
  196. Which_Data_To_Get = Socket_Get_Weather;
  197. Socket_Test();
  198. printf("Get_Time_Task\r\n");
  199. sys_ms_sleep(60000);

  200. }
  201. else
  202. {
  203. Which_Data_To_Get = Socket_Get_Time;
  204. Socket_Test();
  205. printf("Get_Weather_Task\r\n");
  206. sys_ms_sleep(2000);
  207. }
  208. }
  209. }

  210. void Get_Data_Deal(void)
  211. {
  212. if(Which_Data_To_Get == Socket_Get_Time)
  213. {
  214. sys_enter_critical();
  215. RTC_Init.year = (strtol (strtok(Buffer1,":"),NULL,16)) & 0xff;
  216. RTC_Init.month = strtol (strtok(NULL,":"),NULL,16);
  217. RTC_Init.date = strtol (strtok(NULL,":"),NULL,16);
  218. RTC_Init.hour = strtol (strtok(NULL,":"),NULL,16);
  219. RTC_Init.minute = strtol (strtok(NULL,":"),NULL,16);
  220. RTC_Init.second = strtol (strtok(NULL,":"),NULL,16);
  221. printf("%x,%x,%x\r\n",RTC_Init.month,RTC_Init.minute,RTC_Init.second);
  222. rtc_init_mode_enter();
  223. rtc_init(&RTC_Init);
  224. rtc_init_mode_exit();
  225. sys_exit_critical();
  226. }
  227. else
  228. {
  229. char *p = strtok(Buffer1,"_");
  230. strcpy(Weather_Data.Provience,p);
  231. p = strtok(NULL,"_");
  232. strcpy(Weather_Data.Location,p);
  233. p = strtok(NULL,"_");
  234. strcpy(Weather_Data.Weather_Condition,p);
  235. p = strtok(NULL,"_");
  236. strcpy(Weather_Data.Wind_Direction,p);
  237. p = strtok(NULL,"_");
  238. strcpy(Weather_Data.Wind_Intensity,p);
  239. p = strtok(NULL,"_");
  240. strcpy(Weather_Data.TEM,p);
  241. p = strtok(NULL,"_");
  242. strcpy(Weather_Data.Hyd,p);
  243. p = strtok(NULL,"_");
  244. strcpy(Weather_Data.Update_Date,p);
  245. p = strtok(NULL,"_");
  246. strcpy(Weather_Data.Update_Tim,p);
  247. }

  248. }

  249. char Buffer[20];
  250. rtc_parameter_struct Rtc_Oled;
  251. void OLED_Show(void *Para)
  252. {
  253. for(;;)
  254. {
  255. sys_enter_critical();
  256. if(Oled_Status_Chnaged)
  257. {
  258. OLED_Clear();
  259. Oled_Status_Chnaged = false;
  260. }
  261. if(OLED_Weather == OLED_Clock)
  262. {

  263. sprintf(Buffer," Current_Time ");
  264. OLED_ShowString(1, 1, Buffer);
  265. printf("OLED_Task1\r\n");
  266. rtc_current_time_get(&Rtc_Oled);
  267. sprintf(Buffer," 20%02x:%02x:%02x ",Rtc_Oled.year,Rtc_Oled.month,Rtc_Oled.date);
  268. OLED_ShowString(2, 1, Buffer);
  269. sprintf(Buffer," %02x:%02x:%02x ",Rtc_Oled.hour,Rtc_Oled.minute,Rtc_Oled.second);
  270. OLED_ShowString(3, 1, Buffer);
  271. if(Wifi_Connect_Status ==OLED_Wifi_Disconnect)
  272. {
  273. OLED_ShowString(4, 1, " Wifi_Disconnect");
  274. }
  275. else if(Wifi_Connect_Status == OLED_Wifi_Connect)
  276. {
  277. OLED_ShowString(4, 1, " Wifi_Connect ");
  278. }
  279. }
  280. else if(OLED_Weather == OLED_Weather_Condition)
  281. {

  282. sprintf(Buffer,"Pro:%s",Weather_Data.Provience);
  283. OLED_ShowString(1,1,Buffer);
  284. sprintf(Buffer,"Loc:%s",Weather_Data.Location);
  285. OLED_ShowString(2,1,Buffer);
  286. sprintf(Buffer,"Weather: %02x:%02x",RTC_Init.hour,RTC_Init.minute);
  287. OLED_ShowString(3,1,Buffer);
  288. sprintf(Buffer,"%s",Weather_Data.Weather_Condition);
  289. OLED_ShowString(4,1,Buffer);
  290. }
  291. else if(OLED_Weather == OLED_Weather_Tem_Hyd)
  292. {

  293. sprintf(Buffer,"Tem:%sHyd:%s",Weather_Data.TEM,Weather_Data.Hyd);
  294. OLED_ShowString(1,1,Buffer);
  295. sprintf(Buffer,"%s %s",Weather_Data.Wind_Direction,Weather_Data.Wind_Intensity);
  296. OLED_ShowString(2,1,Buffer);
  297. sprintf(Buffer,"Up_Dt:%s",Weather_Data.Update_Date);
  298. OLED_ShowString(3,1,Buffer);
  299. sprintf(Buffer,"Up_Tim:%s",Weather_Data.Update_Tim);
  300. OLED_ShowString(4,1,Buffer);
  301. }
  302. sys_exit_critical();
  303. sys_ms_sleep(1000);
  304. }
  305. }
  306. void OLED_Control(void *Para)
  307. {
  308. for(;;)
  309. {
  310. if(OLED_Weather == OLED_Clock)
  311. {
  312. OLED_Weather = OLED_Weather_Condition;

  313. }
  314. else if(OLED_Weather == OLED_Weather_Condition)
  315. {
  316. OLED_Weather = OLED_Weather_Tem_Hyd;

  317. }
  318. else if(OLED_Weather == OLED_Weather_Tem_Hyd)
  319. {
  320. OLED_Weather = OLED_Clock;

  321. }
  322. Oled_Status_Chnaged = true;
  323. sys_ms_sleep(5500);

  324. }
  325. }







  326. main.c:



  327. /*!
  328. \file main.c
  329. \brief Main loop of GD32VW55x SDK.

  330. \version 2023-07-20, V1.0.0, firmware for GD32VW55x
  331. */

  332. /*
  333. Copyright (c) 2023, GigaDevice Semiconductor Inc.

  334. Redistribution and use in source and binary forms, with or without modification,
  335. are permitted provided that the following conditions are met:

  336. 1. Redistributions of source code must retain the above copyright notice, this
  337. list of conditions and the following disclaimer.
  338. 2. Redistributions in binary form must reproduce the above copyright notice,
  339. this list of conditions and the following disclaimer in the documentation
  340. and/or other materials provided with the distribution.
  341. 3. Neither the name of the copyright holder nor the names of its contributors
  342. may be used to endorse or promote products derived from this software without
  343. specific prior written permission.

  344. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  345. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  346. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  347. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  348. INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  349. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  350. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  351. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  352. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  353. OF SUCH DAMAGE.
  354. */

  355. #include <stdint.h>
  356. #include "wifi_export.h"
  357. #include "gd32vw55x_platform.h"
  358. #include "uart.h"
  359. #include "ble_init.h"
  360. #include "gd32vw55x.h"
  361. #include "wrapper_os.h"
  362. #include "cmd_shell.h"
  363. #include "atcmd.h"
  364. #include "util.h"
  365. #include "wlan_config.h"
  366. #include "wifi_init.h"
  367. #include "user_setting.h"
  368. #include "version.h"
  369. #include "_build_date.h"
  370. #ifdef CONFIG_FATFS_SUPPORT
  371. #include "fatfs.h"
  372. #endif
  373. #include "ble_app_config.h"
  374. #include "app_cmd.h"
  375. #ifdef CONFIG_AZURE_IOT_SUPPORT
  376. #include "azure_entry.h"
  377. #endif
  378. #include "My_Wifi_Connect.h"
  379. #include "OLED.h"
  380. #include <string.h>
  381. #include "W25Q64.h"
  382. uint8_t Data[256];
  383. uint8_t Read[256];
  384. rtc_parameter_struct RTC_Init = {0} ;
  385. void LED_BSP_Init(void);
  386. /*!
  387. \brief Init applications.
  388. This function is called to initialize all the applications.
  389. \param[in] none.
  390. \param[out] none.
  391. \retval none.
  392. */
  393. static void application_init(void)
  394. {
  395. #if defined CONFIG_BASECMD || defined CONFIG_RF_TEST_SUPPORT || defined CONFIG_BLE_DTM_SUPPORT
  396. if (cmd_shell_init()) {
  397. dbg_print(ERR, "cmd shell init failed\r\n");
  398. }
  399. #endif
  400. #ifdef CONFIG_ATCMD
  401. if (atcmd_init()) {
  402. dbg_print(ERR, "atcmd init failed\r\n");
  403. }
  404. #endif
  405. util_init();

  406. user_setting_init();

  407. #ifdef CFG_BLE_SUPPORT
  408. #ifdef CONFIG_BLE_ALWAYS_ENABLE
  409. ble_init(true);
  410. #else
  411. ble_init(false);
  412. #endif // CONFIG_BLE_DEFAULT_INIT
  413. #endif // CFG_BLE_SUPPORT

  414. #ifdef CFG_WLAN_SUPPORT
  415. if (wifi_init()) {
  416. dbg_print(ERR, "wifi init failed\r\n");
  417. }
  418. #endif
  419. #ifdef CONFIG_FATFS_SUPPORT
  420. fatfs_mk_mount(NULL);
  421. #endif
  422. #ifdef CFG_MATTER
  423. MatterInit();
  424. #endif

  425. #ifdef CONFIG_AZURE_F527_DEMO_SUPPORT
  426. azure_task_start();
  427. #endif
  428. }

  429. #ifdef PLATFORM_OS_RTTHREAD
  430. /*!
  431. \brief Start task.
  432. This function is called to initialize all the applications in thread context.
  433. \param[in] param parameter passed to the task
  434. \param[out] none
  435. \retval none.
  436. */
  437. static void start_task(void *param)
  438. {
  439. (void)param;

  440. application_init();

  441. sys_task_delete(NULL);
  442. }
  443. #endif

  444. /*!
  445. \brief Main entry point.
  446. This function is called right after the booting process has completed.
  447. \param[in] none
  448. \param[out] none
  449. \retval none.
  450. */
  451. void OLED_Init_Config(void *para);
  452. void OLED_Show(void *Para);
  453. void Random_Data_Get(uint8_t Num);
  454. void W25q64_Test(void *Para);
  455. void W25Q64_Config(void);
  456. void Task_Delete(void *Para);
  457. void RTC_BSP_Init(void);
  458. void* W25Q64_Task = NULL;
  459. extern void* WIFI_Connect_Status;
  460. int main(void)
  461. {

  462. sys_os_init();
  463. platform_init();

  464. dbg_print(NOTICE, "SDK Version: %s\n", WIFI_GIT_REVISION);
  465. dbg_print(NOTICE, "Build date: %s\n", SDK_BUILD_DATE);
  466. #ifdef PLATFORM_OS_RTTHREAD
  467. if (sys_task_create_dynamic((const uint8_t *)"start_task",
  468. START_TASK_STACK_SIZE, OS_TASK_PRIORITY(START_TASK_PRIO), start_task, NULL) == NULL) {
  469. dbg_print(ERR, "Create start task failed\r\n");
  470. }
  471. #else
  472. application_init();
  473. #endif
  474. LED_BSP_Init();
  475. RTC_BSP_Init();
  476. W25Q64_Config();
  477. sys_task_create(NULL, (const uint8_t *)"oled_init", NULL, 1024, 0, 0, OS_TASK_PRIORITY(5), OLED_Init_Config, NULL);
  478. sys_task_create(NULL, (const uint8_t *)"LED_Blink", NULL, 256, 0, 0, OS_TASK_PRIORITY(1), LED_Blink, NULL);
  479. sys_task_create(NULL, (const uint8_t *)"oled_control", NULL, 256, 0, 0, OS_TASK_PRIORITY(4), OLED_Control, NULL);
  480. sys_task_create(NULL, (const uint8_t *)"Oled_Show", NULL, 512, 0, 0, OS_TASK_PRIORITY(4), OLED_Show, NULL);
  481. WIFI_Connect_Status = sys_task_create(NULL, (const uint8_t *)"Wifi_Status", NULL, 256, 0, 0, OS_TASK_PRIORITY(0), Socket_Deal, NULL);

  482. sys_os_start();
  483. }
  484. void OLED_Init_Config(void *para)
  485. {
  486. for(;;)
  487. {
  488. sys_enter_critical();
  489. OLED_Init();
  490. sys_exit_critical();
  491. sys_ms_sleep(100);
  492. sys_task_delete(NULL);
  493. }

  494. }

  495. void W25Q64_Config(void)
  496. {
  497. W25Q64_Init();
  498. }
  499. void Random_Data_Get(uint8_t Num)
  500. {
  501. int i=0;
  502. int32_t Get;
  503. for(i=0; i < Num ; i++)
  504. {
  505. Get = sys_random_bytes_get(Data+i,2);
  506. if(Get != 0)
  507. {
  508. printf("Random_Data_Generate_Error!\r\n");
  509. return;
  510. }
  511. }
  512. }
  513. void Buffer_Data_Print(uint8_t *BUffer)
  514. {
  515. for(int i=0;i < 256 / 8;i++)
  516. {
  517. {
  518. printf("%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\r\n",BUffer[0+i*8],BUffer[1+i*8],BUffer[2+i*8],\
  519. BUffer[3+i*8],BUffer[4+i*8],BUffer[5+i*8],BUffer[6+i*8],BUffer[7+i*8]);

  520. }

  521. }
  522. printf("-----------\r\n");
  523. }

  524. void RTC_BSP_Init(void)
  525. {
  526. uint32_t prescaler_a = 0, prescaler_s = 0;
  527. rcu_periph_clock_enable(RCU_PMU);
  528. pmu_backup_write_enable();
  529. rcu_osci_on(RCU_IRC32K);
  530. rcu_osci_stab_wait(RCU_IRC32K);
  531. rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
  532. prescaler_s = 0x13F;
  533. prescaler_a = 0x63;
  534. rcu_periph_clock_enable(RCU_RTC);
  535. rtc_register_sync_wait();
  536. RTC_Init.year = 0x00;
  537. RTC_Init.month = 0;
  538. RTC_Init.date = 0;
  539. RTC_Init.month = 0;
  540. RTC_Init.minute = 0;
  541. RTC_Init.second = 0;
  542. RTC_Init.factor_asyn = prescaler_a;
  543. RTC_Init.factor_syn = prescaler_s;
  544. rtc_init(&RTC_Init);
  545. }
  546. void W25q64_Test(void *Para)
  547. {
  548. for(;;)
  549. {
  550. sys_enter_critical();
  551. //Random_Data_Get(256);
  552. memset(Data, 0x55,256);
  553. Buffer_Data_Print(Data);
  554. //W25Q64_SectorErase(0);
  555. //W25Q64_PageProgram(0,Data,256);
  556. W25Q64_ReadData(0,Read,256);
  557. Buffer_Data_Print(Read);
  558. sys_exit_critical();
  559. sys_ms_sleep(1000);
  560. }
  561. }

  562. void LED_BSP_Init(void)
  563. {
  564. rcu_periph_clock_enable(RCU_GPIOB);
  565. gpio_mode_set(GPIOB,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,GPIO_PIN_2);
  566. gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_2);
这就是对整个天气时钟的创建函数,对于OLED的函数和W25q64的代码,这里可以通过移植得到,这里就不给出了。
最后看一下效果吧:
时钟部分:
天气的省份地区和天气状况,时间的时和秒:
温湿度,风速风向和服务器获取到天气数据的时间:

这三个界面每隔5.5秒切换一次,没做过渡效果,直接切换,可以考虑在天气时钟的第二代版本里面去增加。
这就是如何在服务器上通过Socket与GD32VW553进行数据交换的方法。








您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

9

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部