0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Renesas GUI挑戰(zhàn)—天氣日歷設(shè)計

冬至配餃子 ? 來源:EPTmachine ? 作者:EPTmachine ? 2023-09-15 15:53 ? 次閱讀

摘要

本次參加HMI-Boardt挑戰(zhàn)賽,提交的作品是天氣萬年歷,實現(xiàn)的功能主要有以下幾點:
顯示當前的日期,包括年月日,本地時間等信息;
顯示當前的天氣、溫度等信息;
選擇該項目的主要原因是該項目涉及到了Wifi、http客戶端、網(wǎng)絡(luò)數(shù)據(jù)抓取等,屬于典型的物聯(lián)網(wǎng)應(yīng)用,同時天氣日歷的邏輯很簡單,很適合作為初學者的入門項目,能夠接觸到物聯(lián)網(wǎng)開發(fā)的各個關(guān)鍵組件,配合RT-Thread豐富的生態(tài),在培養(yǎng)興趣的同時,可以將書本上的知識轉(zhuǎn)化為貼近生活的實際應(yīng)用。

1.1 程序整體介紹

本項目使用到的外設(shè)主要有TFT屏幕、RTC模塊、RW007Wifi模塊。
屏幕的分辨率為480x272,屏幕上顯示的信息包括當前月份的日歷(以邊框形式在日歷中顯示當天的信息)、城市、溫度、天氣以及時間信息。程序的整體流程如下所示

1.jpg

項目中使用到的軟件包如下所示:

1.jpg

項目中的代碼主要集中在hal_entry.c以及lvgl_demo.c中,具體的文件分布如下圖所示:

1.jpg

1.2 模塊說明

1.2.1 顯示部分

RT-Thread提供的HMI-Board的SDK中已經(jīng)為用戶編寫了顯示和觸摸的驅(qū)動程序,同時lvgl中以為RT-Thread做了適配,在RT-Thread的啟動序列中添加了lvgl線程的創(chuàng)建、調(diào)用lvgl初始化以及初始外設(shè)的函數(shù),用戶只需要編寫lv_user_gui_init函數(shù),設(shè)計應(yīng)用相關(guān)的代碼即可。

本項目的顯示代碼如下。

//導入額外的字體
LV_FONT_DECLARE(font_calendar_han_bold_20);
/* display demo; you may replace with your LVGL application at here */
//設(shè)定城市信息標簽的外觀和位置
city_label=lv_label_create(lv_scr_act());
lv_obj_set_style_text_font(city_label,&font_calendar_han_bold_20,0);
//lv_label_set_text(city_label, weather_data.name);
lv_obj_set_pos(city_label, 10,5);
//設(shè)定溫度信息標簽的外觀和位置
temp_label=lv_label_create(lv_scr_act());
lv_obj_set_style_text_font(temp_label,&font_calendar_han_bold_20,0);
//lv_label_set_text(temp_label, weather_data.temp);
lv_obj_set_pos(temp_label, 10, 30);
//設(shè)定天氣信息標簽的外觀和位置
weather_label=lv_label_create(lv_scr_act());
lv_obj_set_style_text_font(weather_label,&font_calendar_han_bold_20,0);
//abel_set_text(weather_label, weather_data.text);
lv_obj_set_pos(weather_label, 90, 30);
//創(chuàng)建時間標簽控件,用于顯示當前的時間信息
time_label=lv_label_create(lv_scr_act());
lv_obj_set_style_text_font(time_label,&font_calendar_han_bold_20,0);
lv_label_set_text(time_label, time_label_text);
lv_obj_set_pos(time_label, 10, 55);
//設(shè)定日歷控件的外觀和位置
calendar = lv_calendar_create(lv_scr_act());
lv_obj_set_x(calendar,10);
lv_obj_set_y(calendar,80);
lv_obj_set_size(calendar, 185, 185);
lv_obj_add_event_cb(calendar, event_handler, LV_EVENT_ALL, NULL);
lv_calendar_set_today_date(calendar, 2021, 02, 23);
lv_calendar_set_showed_date(calendar, 2021, 02);
/*Highlight a few days*/
static lv_calendar_date_t highlighted_days[3];       /*Only its pointer will be saved so should be static*/
highlighted_days[0].year = 2021;
highlighted_days[0].month = 02;
highlighted_days[0].day = 6;
highlighted_days[1].year = 2021;
highlighted_days[1].month = 02;
highlighted_days[1].day = 11;
highlighted_days[2].year = 2022;
highlighted_days[2].month = 02;
highlighted_days[2].day = 22;
lv_calendar_set_highlighted_dates(calendar, highlighted_days, 3);

#if LV_USE_CALENDAR_HEADER_DROPDOWN
lv_calendar_header_dropdown_create(calendar);
#elif LV_USE_CALENDAR_HEADER_ARROW
lv_calendar_header_arrow_create(calendar);
#endif
lv_calendar_set_showed_date(calendar, 2021, 10);

為了在屏幕上顯示中文,首先準備需要用到的字體文件(項目中使用的是),在lvgl官方提供的字體轉(zhuǎn)換工具中,根據(jù)自己的需要對字體的大小和字符集進行選擇,最后得到字體文件,添加到項目中,使用lvgl的字體導入命令將要使用的字體導入,在需要使用的控件上使用該字體即可。

項目的界面效果如圖所示。

1.2.2 Wifi連接、NTP校時部分

開發(fā)板上帶有RW007Wifi模塊,通過其可以連接到互聯(lián)網(wǎng),從而可以獲取互聯(lián)上提供的信息服務(wù),比如NTP(網(wǎng)絡(luò)時間協(xié)議)用于更新本地的RTC時間。

根據(jù)HMI-Board指南中的RW007模塊使用,開啟RW007模塊的Wifi通訊功能,調(diào)用rt_wlan_connect函數(shù)連接到指定的Wifi,從而可以方位互聯(lián)網(wǎng)服務(wù)。

開啟物聯(lián)網(wǎng)服務(wù)中的NTP服務(wù)和本地的RTC服務(wù),可以通過訪問NTP服務(wù)器,從而獲取網(wǎng)絡(luò)時間,對本地的時間進行校準。

1.jpg

相關(guān)的代碼如下所示:

rt_device_t device = RT_NULL;
//連接到指定的Wifi
app_connect_wifi();
/*尋找設(shè)備*/
device = rt_device_find(RTC_NAME);
if (!device)
{
  rt_kprintf("find %s failed!", RTC_NAME);
  return;
}
/*初始化RTC設(shè)備*/
if(rt_device_open(device, 0) != RT_EOK)
{
  rt_kprintf("open %s failed!", RTC_NAME);
  return;
}
//同步NTP到RTC
while(!ntp_sync_to_rtc(RT_NULL));
rt_sem_release(time_sync);

lvgl中提供了定時功能,初始化定時器后,設(shè)定定時器的回調(diào)函數(shù)以及尋魂次數(shù)(這里參數(shù)給-1,表示無限循環(huán)),回調(diào)函數(shù)用于更新時間以及發(fā)送獲取天氣信息的信號量,具體代碼如下:

sec_timer=lv_timer_create(sec_timer_cb, 500, NULL);
lv_timer_set_repeat_count(sec_timer, -1);

void sec_timer_cb(lv_timer_t* timer)
{
static uint16_t count=0;
count++;
app_get_time();
lv_label_set_text(time_label, time_label_text);
if(count==1800)
{
count=0;
rt_sem_release(get_weather);
}
}

1.2.3 獲取天氣信息并提取相應(yīng)的信息

在main中hal_entry函數(shù)中,獲取到訪問天氣數(shù)據(jù)的信號量后,創(chuàng)建WebClient,通過心知天氣的API訪問當前的天氣信息,數(shù)據(jù)形式為JSON字符,根據(jù)官方提供的數(shù)據(jù)格式,對其中的數(shù)據(jù)進行解析,提取出相應(yīng)的字段,用于在標簽控件上顯示信息。相關(guān)的代碼如下所示:

#define GET_HEADER_BUFSZ 1024 //頭部大小
#define GET_RESP_BUFSZ 1024 //響應(yīng)緩沖區(qū)大小
static char *weather_url = "http://api.seniverse.com/v3/weather/now.json?key=SG-nLPzA3pyLEy9Tw&location=wuxi&language=zh-Hans&unit=c";
weather_t weather_data;
/* 天氣數(shù)據(jù)解析 */
void weather_data_parse(rt_uint8_t *data)
{
cJSON *root = RT_NULL, *array=RT_NULL,*object = RT_NULL, *element=RT_NULL, *item=RT_NULL;
memset(&weather_data,0,sizeof(weather_data));
root = cJSON_Parse((const char *)data);
if (!root)
{
rt_kprintf("No memory for cJSON root!n");
return;
}
//獲取結(jié)果對象
array = cJSON_GetObjectItem(root, "results");
//獲取數(shù)組中的第一個元素
object = cJSON_GetArrayItem(array, 0);
//提取location的信息
element=cJSON_GetObjectItem(object,"location");
item=cJSON_GetObjectItem(element,"id");
memcpy(weather_data.id,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"name");
memcpy(weather_data.name,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"country");
memcpy(weather_data.country,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"path");
memcpy(weather_data.country,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"timezone");
memcpy(weather_data.country,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"tz_offset");
memcpy(weather_data.country,item->valuestring,strlen(item->valuestring));
//提取當前的天氣信息
element=cJSON_GetObjectItem(object,"now");
item=cJSON_GetObjectItem(element,"text");
memcpy(weather_data.text,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"code");
memcpy(weather_data.code,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(element,"temperature");
memcpy(weather_data.temp,item->valuestring,strlen(item->valuestring));
//提取上次天氣更新的時間信息
element=cJSON_GetObjectItem(object,"last_update");
memcpy(weather_data.last_update,element->valuestring,strlen(element->valuestring));
if (root != RT_NULL)
cJSON_Delete(root);
}
void weather(void)
{
rt_uint8_t *buffer = RT_NULL;
int resp_status;
struct webclient_session *session = RT_NULL;
int content_length = -1, bytes_read = 0;
int content_pos = 0;
/* 創(chuàng)建會話并且設(shè)置響應(yīng)的大小 */
session = webclient_session_create(GET_HEADER_BUFSZ);
if (session == RT_NULL)
{
rt_kprintf("No memory for get header!n");
goto __exit;
}
/* 發(fā)送 GET 請求使用默認的頭部 */
if ((resp_status = webclient_get(session, weather_url)) != 200)
{
rt_kprintf("webclient GET request failed, response(%d) error.n", resp_status);
goto __exit;
}
/* 分配用于存放接收數(shù)據(jù)的緩沖 */
buffer = rt_calloc(1, GET_RESP_BUFSZ);
if (buffer == RT_NULL)
{
rt_kprintf("No memory for data receive buffer!n");
goto __exit;
}
content_length = webclient_content_length_get(session);
if (content_length < 0)
{
/* 返回的數(shù)據(jù)是分塊傳輸?shù)? */
do
{
bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ);
if (bytes_read <= 0)
{
break;
}
}while (1);
}
else
{
do
{
bytes_read = webclient_read(session, buffer,
content_length - content_pos > GET_RESP_BUFSZ ?
GET_RESP_BUFSZ : content_length - content_pos);
if (bytes_read <= 0)
{
break;
}
content_pos += bytes_read;
}while (content_pos < content_length);
}
/* 天氣數(shù)據(jù)解析 */
weather_data_parse(buffer);
__exit:
/* 關(guān)閉會話 */
if (session != RT_NULL)
webclient_close(session);
/* 釋放緩沖區(qū)空間 */
if (buffer != RT_NULL)
rt_free(buffer);
}

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 物聯(lián)網(wǎng)
    +關(guān)注

    關(guān)注

    2894

    文章

    43301

    瀏覽量

    366368
  • GUI
    GUI
    +關(guān)注

    關(guān)注

    3

    文章

    631

    瀏覽量

    39290
  • WLAN技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    9249
  • wifi模塊
    +關(guān)注

    關(guān)注

    60

    文章

    374

    瀏覽量

    72915
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1239

    瀏覽量

    39427
收藏 人收藏

    評論

    相關(guān)推薦

    為全志D1開發(fā)板移植LVGL日歷控件和顯示天氣

    利用TCP封裝HTTP包請求天氣信息 Linux還真是逐步熟悉中,現(xiàn)在才了解到Linux即沒有原生的GUI,也沒有應(yīng)用層協(xié)議棧,所以要實現(xiàn)HTTP應(yīng)用,必須利用TCP然后自己封裝HTTP數(shù)據(jù)包。本篇
    發(fā)表于 02-21 09:59

    飛雪桌面日歷 V6.5.0 官方版

    日歷、月歷、世界時鐘、倒計時時鐘、定時關(guān)機、備忘錄、便簽、節(jié)日生日定制、系統(tǒng)熱鍵、光驅(qū)控制、網(wǎng)絡(luò)校時、壁紙切換、郵件檢查、語音報時、網(wǎng)絡(luò)收音機、天氣預(yù)報、MD5計算等。內(nèi)含從公元1580-5000年
    發(fā)表于 04-01 22:21

    天氣預(yù)警收音機方案

    天氣預(yù)警收音機是在天氣和災(zāi)害預(yù)警監(jiān)測下, 提供安全的信息。天氣預(yù)警收音機接收國家氣象服務(wù)頒發(fā)的所有危險、天氣警報、緊急信息提供給公眾。功能/規(guī)格:一、 液晶顯示:NOAA 警報/
    發(fā)表于 05-20 17:56

    DIY電子日歷

    把以前做的電子日歷那出來曬曬,有點灰塵了,不過好像還能用,只是最后的那個8*8點陣好像壞了一條線。我設(shè)計開發(fā)的是一種新型“電子日歷鐘”它可以全方面顯示時間,年,月,日。星期,提供中文顯示,農(nóng)歷顯示
    發(fā)表于 02-15 08:45

    項目源碼--Android天氣日歷精致UI源碼

    技術(shù)要點:1. 天氣日歷精致UI2. Android的Http通信技術(shù)3. Android的天氣信息解析4. Android的日歷信息的統(tǒng)計5. Andorid的地理位置的管理6.源碼
    發(fā)表于 08-24 16:33

    項目源碼--Android天氣日歷精致UI源碼

    ` 本帖最后由 2yuanma 于 2013-8-24 16:37 編輯 下載源碼:技術(shù)要點:1. 天氣日歷精致UI2. Android的Http通信技術(shù)3. Android的天氣信息解析4. Android的
    發(fā)表于 08-24 16:35

    樹莓派多功能數(shù)碼壁掛日歷

    本帖最后由 348081236 于 2016-1-12 11:29 編輯 還在用筆在日歷上的重要日子畫圈寫字嗎?如果是那你就OUT了。上圖這個數(shù)碼壁掛日歷除了日歷的基本功能,它還能預(yù)測
    發(fā)表于 01-12 11:27

    RENESAS的相關(guān)資料推薦

    品牌:RENESAS型號:R5F1006AASP#X0封裝:SSOP20包裝:2500年份:1825+產(chǎn)地:JP數(shù)量:750000瑞利誠科技(深圳)有限公司RENESAS 誠信經(jīng)銷商瑞利誠科技(深圳
    發(fā)表于 11-29 07:41

    360攜手HarmonyOS打造獨特的“天氣大師”

    大師。 選擇天氣這個品類,首先是因為成本低,因為我們已有360天氣的設(shè)計經(jīng)驗和全套代碼,是可以快速復用的。 其次則是認為用戶對天氣日歷的需求,天然適合用HarmonyOS所倡導的
    發(fā)表于 03-03 17:29

    基于靜態(tài)分析的Android GUI遍歷方法

    分析Android應(yīng)用程序數(shù)據(jù)流的基礎(chǔ)之上,構(gòu)建程序活動轉(zhuǎn)換圖和函數(shù)調(diào)用圖,解析程序CUI元素,進而編寫測試腳本動態(tài)遍歷應(yīng)用程序CUI元素。將該方法應(yīng)用于訂票日歷、WiFi萬能鑰匙和360天氣應(yīng)用的實際測試,結(jié)果表明:Activity的平均覆蓋率達到76%,明顯高于人工測
    發(fā)表于 12-11 11:32 ?0次下載
    基于靜態(tài)分析的Android <b class='flag-5'>GUI</b>遍歷方法

    日歷列表視圖控件使用案例

    日歷列表視圖提供了一種日歷選擇日期的簡便方法 用法 1.在布局xml文件中聲明一個DayPickerView
    發(fā)表于 03-30 11:18 ?1次下載

    基于STM32設(shè)計的指針式電子鐘與日歷

    這是基于STM32設(shè)計的一個指針式電子鐘+萬年歷小項目,采用3.5寸的LCD屏顯示時鐘,日歷、溫度、天氣,支持觸摸屏調(diào)整設(shè)置時間,設(shè)置鬧鐘,查看日歷等等。整體項目主要是技術(shù)點就是LCD屏的圖形繪制。比如: 時鐘的時針繪制、分針、
    的頭像 發(fā)表于 05-18 11:10 ?5962次閱讀
    基于STM32設(shè)計的指針式電子鐘與<b class='flag-5'>日歷</b>

    二三極管在電子日歷產(chǎn)品中的應(yīng)用

    、鬧鐘、記事本等。電子日歷的簡單、簡潔特點深得廣大用戶喜愛,很多電子日歷還有鬧鐘、播報天氣、裝飾和電子畫冊的功能。
    的頭像 發(fā)表于 02-20 11:24 ?804次閱讀

    開發(fā)活動 | 嵌入式GUI挑戰(zhàn)賽報名開啟!參賽申領(lǐng)開發(fā)板

    開發(fā)挑戰(zhàn)賽 RT-Thread社區(qū)聯(lián)合LVGL社區(qū),及合作伙伴瑞薩電子正式開啟2023嵌入式GUI挑戰(zhàn)賽,歡迎你來挑戰(zhàn)! 在本次大賽中,我們歡迎所有參賽者來構(gòu)建全面的嵌入式
    的頭像 發(fā)表于 07-03 12:10 ?645次閱讀
    開發(fā)活動 | 嵌入式<b class='flag-5'>GUI</b><b class='flag-5'>挑戰(zhàn)</b>賽報名開啟!參賽申領(lǐng)開發(fā)板

    嵌入式GUI挑戰(zhàn)賽獲獎名單公布!

    6月份RT-Thread 社區(qū)聯(lián)合 LVGL 社區(qū),及合作伙伴瑞薩電子正式開啟2023嵌入式GUI挑戰(zhàn)賽!經(jīng)過3個月的激烈角逐,參賽者們提交了許多令人驚喜的作品,以超酷的新方式在嵌入式設(shè)備上去
    的頭像 發(fā)表于 10-18 16:05 ?472次閱讀
    嵌入式<b class='flag-5'>GUI</b><b class='flag-5'>挑戰(zhàn)</b>賽獲獎名單公布!