上周末加班,這周末休息,有時(shí)間整理一篇之前做的基于RT-Thread的疫情監(jiān)控平臺(tái)。上一篇文章我們使用STM32F103 MCU裸機(jī)開發(fā)的方式實(shí)現(xiàn)了疫情監(jiān)控平臺(tái)。這次我們玩點(diǎn)高端的,使用RT-Thread Studio來實(shí)現(xiàn)同樣的功能,一起來看看吧!
文章目錄
使用到的軟件包
0.RT-Thread Studio的下載和安裝
1.硬件準(zhǔn)備
2.新建工程
3.添加LED閃爍功能
4.添加ESP8266軟件包
5.疫情數(shù)據(jù)的獲取
6.疫情數(shù)據(jù)的解析
7.疫情數(shù)據(jù)的顯示
開源地址
最終的顯示效果:
顯示效果
有效文件就這9個(gè),其他的就全是圖形化配置:
有效文件
整個(gè)流程下來,如果順利的話,可以在2個(gè)小時(shí)內(nèi)完成。
使用到的軟件包
at device:用于ESP8266配網(wǎng)
webclient:用于發(fā)送HTTPS請(qǐng)求
mbdetls:用于HTTPS加密
cJSON:用于JSON數(shù)據(jù)解析
0.RT-Thread Studio的下載和安裝
一站式的 RT-Thread 開發(fā)工具,通過簡(jiǎn)單易用的圖形化配置系統(tǒng)以及豐富的軟件包和組件資源,讓物聯(lián)網(wǎng)開發(fā)變得簡(jiǎn)單和高效。
RT-Thread Studio
支持多種芯片,STM32全系列
支持創(chuàng)建裸機(jī)工程、RT-Thread Nano和Master工程
強(qiáng)大的代碼編輯功能,基于Eclipse框架
免費(fèi)無版權(quán)限制,基于開源Eclipse和ARM-GCC編譯器。
支持多種仿真器,J-Link,ST-link等,支持在線調(diào)試,變量觀察。
SDK管理器,圖形化配置RT-Thread軟件包,同步RT-Thread最新版本。
集成Putty串口終端工具
更多的使用教程:
https://www.rt-thread.org/page/studio.html
目前最新版本為1.1.3版本,支持3種下載方式,我們選擇最后一個(gè)下載方式,從RT-Thread 官網(wǎng)服務(wù)器上下載。
下載地址:
http://117.143.63.254:9012/www/studio/download/RT-Thread%20Studio-v1.1.3-setup-x86_64_20200731-2100.exe
下載鏈接
安裝過程和常用的軟件安裝方法一樣,選擇安裝路徑,然后Next就行了。
1.硬件準(zhǔn)備
開發(fā)板用的是我在大四時(shí)自己設(shè)計(jì)的STM32開發(fā)板——NiceDay,基于STM32F103RET主控。這是我設(shè)計(jì)的第二塊板子(第一塊是畢業(yè)設(shè)計(jì)兩輪平衡車主板),是在大四快畢業(yè)時(shí),畢設(shè)實(shí)物和論文完成之后還有點(diǎn)時(shí)間,就設(shè)計(jì)了這款板子,最開始是準(zhǔn)備做桌面天氣時(shí)鐘的。
開發(fā)板
2.新建工程
RT-Thread Studio支持創(chuàng)建裸機(jī)工程、包含RT-Thread Nano版本的工程和包含Master版本的工程。這里,我們選擇創(chuàng)建RT-Thread 項(xiàng)目,即包含完整版RT-Thread的工程。
新建項(xiàng)目
工程支持基于芯片創(chuàng)建工程,或者基于已有的BSP創(chuàng)建,這里使用的是我自己設(shè)計(jì)的開發(fā)板,所以選擇基于芯片,選擇芯片型號(hào):STM32F103RE,調(diào)試串口選擇串口1,調(diào)試器選擇J-Link,SWD接口。
新建項(xiàng)目
創(chuàng)建完成之后,直接按Ctrl+B編譯整個(gè)工程,第一次編譯時(shí)間會(huì)長(zhǎng)一點(diǎn),如果修改很少,下次再進(jìn)行編譯就會(huì)很快了,可以看到無警告無錯(cuò)誤。
編譯結(jié)果
使用SWD接口連接JLink調(diào)試器和開發(fā)板,開發(fā)板上電,直接點(diǎn)擊下載按鈕,也可以使用快捷鍵Ctrl+Alt+D下載
下載程序
底部可以看到下載信息,從LOG來看,下載的程序文件是Bin文件,比較,擦除,編程,驗(yàn)證,復(fù)位整個(gè)流程耗時(shí)13s左右。
下載LOG
RT-Thread Studio是自帶Putty串口終端的,點(diǎn)擊終端圖標(biāo):
終端按鈕
選擇串口號(hào)、波特率、文字編碼方式等。
配置終端
底部切換到終端窗口,可以看到串口終端輸出信息:
串口終端
這樣,不到5分鐘,一個(gè)基于STM32F103RET6的工程模板就創(chuàng)建好了,包含RT-Thread完整版操作系統(tǒng),整個(gè)過程不需要寫一行代碼,完全圖形化配置。
3.添加LED閃爍功能
作為單片機(jī)點(diǎn)燈小能手,RT-Thread下如何點(diǎn)燈是必須掌握的。打開RT-Thread組件圖形化配置界面,可以看到默認(rèn)開啟了PIN和串口設(shè)備驅(qū)動(dòng)的。
圖形化配置界面
在main.c文件中添加LED閃爍功能。包含頭文件和添加宏定義
#include
重新編譯,下載。可以看到LED閃爍起來了。工程默認(rèn)是使用內(nèi)部RC作為輸入時(shí)鐘,所以無論你的板子是8M還是12M,都可以正常閃爍。我的開發(fā)板是8M晶體,這里我們配置使用外部HSE作為輸入時(shí)鐘。
打開drivers->stm32f1xx_hal_conf.h文件,修改HSE_VALUE宏定義為8M。
晶體頻率修改
打開drivers->drv_clk.c文件:
時(shí)鐘源修改
配置PLL時(shí)鐘源為HSE,并設(shè)置倍頻系數(shù)為9。
時(shí)鐘源修改
倍頻系數(shù)
這里根據(jù)實(shí)際板子晶體頻率來設(shè)置,如果是12M晶體,倍頻系數(shù)應(yīng)該設(shè)置為6,如果是16M,需要參考時(shí)鐘樹,先2倍分頻,然后9倍倍頻。
#include
這樣就修改為外部8M晶體作為PLL時(shí)鐘源,再次編譯下載,和之前的現(xiàn)象是一樣的。
4.添加ESP8266軟件包
聯(lián)網(wǎng)設(shè)備,我們選擇的是ESP8266-01S,如果看過上一篇疫情監(jiān)控三部曲——在STM32F103 MCU上實(shí)現(xiàn)(裸機(jī)版),里面介紹了如何配置ESP8266 GET HTTPS請(qǐng)求, 配置工作模式 > 連接WiFi > 與服務(wù)器建立SSL連接 > 發(fā)送GET請(qǐng)求獲取數(shù)據(jù)等等,整個(gè)流程固定而繁瑣,那么能不能封裝成一個(gè)模塊,直接拿來使用呢?
esp8266
這里就要介紹RT-Thread的AT Device軟件包了,
AT device 軟件包是由 RT-Thread AT 組件針對(duì)不同 AT 設(shè)備的移植文件和示例代碼組成,目前支持的 AT 設(shè)備有:ESP8266、ESP32、M26、MC20、RW007、MW31、SIM800C、W60X 、SIM76XX、A9/A9G、BC26 、AIR720、ME3616、M6315、BC28、EC200X、M5311系列設(shè)備等,目前上述設(shè)備都完成對(duì) AT socket 功能的移植,及設(shè)備通過 AT 命令實(shí)現(xiàn)標(biāo)準(zhǔn) socket 編程接口,完成 socket 通訊的功能,具體功能介紹可參考 《RT-Thread 編程指南》AT 命令章節(jié) 。
https://www.rt-thread.org/document/site/programming-manual/at/at/
簡(jiǎn)單的說,就是我只需要調(diào)用這個(gè)軟件包,然后修改WiFi賬號(hào)和密碼,就可以直接配置ESP8266聯(lián)網(wǎng)了。
由于AT Device依賴于libc組件,所以在添加AT Device軟件包之前,先開啟libc。
在RT-Thread Settings中點(diǎn)擊libc灰色圖標(biāo),變成彩色說明已經(jīng)開啟。
組件配置
添加AT Device軟件包,點(diǎn)擊立即添加
軟件包
在彈出的軟件包中心,搜索at_device,然后點(diǎn)擊添加,添加到當(dāng)前工程。
軟件包
在at_device軟件包上右鍵,選擇詳細(xì)配置:
軟件包
在彈出的頁(yè)面,選擇我們使用的WiFi模塊類型,樂鑫的ESP8266系列,并配置WiFi賬號(hào)和密碼,WiFi模塊所連接的串口號(hào)。
WiFi配置
點(diǎn)擊保存之后,工程會(huì)重新進(jìn)行配置,添加相應(yīng)的軟件包文件到當(dāng)前工程,重新生成Makefile文件,rtconfig文件等等。
雖然我們?cè)赼t_device配置中選擇了uart2作為at_device設(shè)備連接的串口。但此時(shí)串口2并沒有開啟,還需要我們手動(dòng)使能。
打開drivers->board.h文件,通過宏定義的方式使能串口2。
#defineBSP_USING_UART2 #defineBSP_UART2_TX_PIN"PA2" #defineBSP_UART2_RX_PIN"PA3"
這樣就開啟了UART2的片上外設(shè),Ctrl + B重新進(jìn)行編譯,時(shí)間會(huì)有些長(zhǎng),編譯完成之后,可以看到flash文件大小明顯比之前大了。
編譯結(jié)果
Ctrl + Alt + D重新下載運(yùn)行,打開串口終端:
終端
可以看到,UART2初始化成功,WiFi連接成功。說明我們的串口模塊已經(jīng)可以正常工作了。提示[E/at.clnt] execute command (AT+CIPDNS_CUR?) failed!失敗信息,是因?yàn)楫?dāng)前ESP8266的固件版本不支持AT+CIPDNS_CUR?這條命令,把固件升級(jí)到最新版本就好了。這個(gè)不影響后面的操作,所以就不用在意這個(gè)了。
測(cè)試一下ifconfig和ping命令,都是正常的。
終端
在RT-Thread Studio中配置ESP8266模塊聯(lián)網(wǎng),整個(gè)流程只寫了3行代碼,可以說是非常的快速方便。
5.疫情數(shù)據(jù)的獲取
WiFi模塊連接上互聯(lián)網(wǎng)之后,就可以連接GET疫情數(shù)據(jù)的API接口https://lab.isaaclin.cn/nCoV/api/overall,然后讀取返回的疫情數(shù)據(jù)。在上一篇的裸機(jī)工程中,是通過先和服務(wù)器建立SSL連接,然后發(fā)送GET HTTPS請(qǐng)求,獲取到的返回?cái)?shù)據(jù),那RT-Thread有沒有這樣功能的軟件包呢?這里就需要添加另一個(gè)軟件包webclient。
WebClient 軟件包是 RT-Thread 自主研發(fā)的,基于 HTTP 協(xié)議的客戶端的實(shí)現(xiàn),它提供設(shè)備與 HTTP Server 的通訊的基本功能。
WebClient 軟件包功能特點(diǎn)如下:
支持 IPV4/IPV6 地址;
支持 GET/POST 請(qǐng)求方法;
支持文件的上傳和下載功能;
支持 HTTPS 加密傳輸;
完善的頭部數(shù)據(jù)添加和處理方式。
和添加at_device一樣,在軟件包中心中搜索webclient,
軟件包
然后添加到當(dāng)前工程,右鍵進(jìn)行配置,由于我們的https://lab.isaaclin.cn/nCoV/api/overall這個(gè)疫情數(shù)據(jù)接口是HTTPS類型的,根據(jù)軟件包使用手冊(cè),我們需要選擇TLS模式中的 MbedTLS。勾選添加GET和POST示例。
軟件包配置
保存配置,看一下當(dāng)前已經(jīng)添加了哪些功能,可以看到有一些組件我們并沒有去打開,但是已經(jīng)被開啟了,這是因?yàn)橛行┸浖菚?huì)依賴一些組件的,當(dāng)使能軟件包時(shí),一些依賴的組件也被同時(shí)使能。
軟件包
Ctrl + B編譯,Ctrl + Alt + D下載運(yùn)行。在終端輸入web_get_test測(cè)試GET請(qǐng)求功能。
GET示例
可以看到,執(zhí)行g(shù)et命令之后,會(huì)返回一個(gè)字符串,那么GET的是哪個(gè)地址呢?打開packages->webclient-v2.1.2->samples->webclient_get_sample.c文件,
示例代碼
可以看到GET的是這個(gè)地址:http://www.rt-thread.com/service/rt-thread.txt,我們用電腦上的瀏覽器訪問一下:
瀏覽器訪問
經(jīng)過實(shí)際測(cè)試發(fā)現(xiàn),GET HTTPS請(qǐng)求,還需要使能軟件模擬RTC這個(gè)組件,否則會(huì)報(bào)assertion failed at function:gettimeofday, line number:19錯(cuò)誤。
使能RTC
我們重新寫一個(gè)獲取疫情數(shù)據(jù)的函數(shù),并導(dǎo)出到MSH。
usr_ncov.c文件內(nèi)容
//usr_ncov.c #include"usr_ncov.h" intget_NCOV_Data(void) { char*uri=RT_NULL; structwebclient_session*session=RT_NULL; uint8_t*buffer=RT_NULL; intindex,ret=0; intbytes_read,resp_status; intcontent_length=-1; intbuffer_size=1600; uri=web_strdup(API_NCOV); rt_kprintf("startgetapi:%s ",API_NCOV); if(uri!=RT_NULL) { buffer=(unsignedchar*)web_malloc(buffer_size); if(buffer==RT_NULL) { rt_kprintf("nomemoryforreceivebuffer. "); ret=-RT_ENOMEM; goto__exit; } /*createwebclientsessionandsetheaderresponsesize*/ session=webclient_session_create(buffer_size); if(session==RT_NULL) { ret=-RT_ENOMEM; goto__exit; } /*sendGETrequestbydefaultheader*/ if((resp_status=webclient_get(session,uri))!=200) { rt_kprintf("webclientGETrequestfailed,response(%d)error. ",resp_status); ret=-RT_ERROR; goto__exit; } rt_kprintf("webclientgetresponsedata: "); content_length=webclient_content_length_get(session); if(content_length0) ????????{ ????????????rt_kprintf("webclient?GET?request?type?is?chunked. "); ????????????do ????????????{ ????????????????bytes_read?=?webclient_read(session,?buffer,?buffer_size); ????????????????if?(bytes_read?<=?0) ????????????????????break; ????????????????for?(index?=?0;?index?
usr_ncov.h文件內(nèi)容
#ifndefAPPLICATIONS_USR_NCOV_H_ #defineAPPLICATIONS_USR_NCOV_H_ #include
重新編譯,下載,運(yùn)行。在終端運(yùn)行這個(gè)命令:
命令獲取疫情數(shù)據(jù)
可以看到獲取到了返回的數(shù)據(jù),長(zhǎng)度1366個(gè)字節(jié)。下一步就是對(duì)這個(gè)JSON數(shù)據(jù)進(jìn)行解析,獲取到我們想要的疫情數(shù)據(jù)。
6.疫情數(shù)據(jù)的解析
API返回的數(shù)據(jù)是JSON格式的,關(guān)于JSON的介紹和解析,可以查看使用cJSON庫(kù)解析和構(gòu)建JSON字符串。數(shù)據(jù)的解析使用的開源小巧的cJSON解析庫(kù),我們可以在軟件包管理中心直接添加:
添加cJSON
在進(jìn)行解析之前,先來分析一下JSON原始數(shù)據(jù)的格式:results鍵的值是一個(gè)數(shù)組,數(shù)組只有一個(gè)JSON對(duì)象,獲取這個(gè)對(duì)象對(duì)應(yīng)鍵的值可以獲取到國(guó)內(nèi)現(xiàn)存和新增確診人數(shù)、累計(jì)和新增死亡人數(shù),累計(jì)和新增治愈人數(shù)等數(shù)據(jù)。
全球疫情數(shù)據(jù)保存在globalStatistics鍵里,它的值是一個(gè)JSON對(duì)象,對(duì)象僅包含簡(jiǎn)單的鍵值對(duì),這些鍵的值,就是全球疫情數(shù)據(jù),其中updateTime鍵的值是更新時(shí)間,這是毫秒級(jí)UNIX時(shí)間戳,可以轉(zhuǎn)換為標(biāo)準(zhǔn)北京時(shí)間。
{ "results":[{ "currentConfirmedCount":509, "currentConfirmedIncr":16, "confirmedCount":85172, "confirmedIncr":24, "suspectedCount":1899, "suspectedIncr":4, "curedCount":80015, "curedIncr":8, "deadCount":4648, "deadIncr":0, "seriousCount":106, "seriousIncr":9, "globalStatistics":{ "currentConfirmedCount":4589839, "confirmedCount":9746927, "curedCount":4663778, "deadCount":493310, "currentConfirmedIncr":281, "confirmedIncr":711, "curedIncr":424, "deadIncr":6 }, "updateTime":1593227489355 }], "success":true }
先定義了結(jié)構(gòu)體NCOV_DATA,用于存儲(chǔ)國(guó)內(nèi)和全球疫情數(shù)據(jù):
structNCOV_DATA{ intcurrentConfirmedCount; intcurrentConfirmedIncr; intconfirmedCount; intconfirmedIncr; intcuredCount; intcuredIncr; intdeadCount; intdeadIncr; intseriousCount; intseriousIncr; charupdateTime[20]; };
對(duì)應(yīng)的解析函數(shù):
#include
在數(shù)據(jù)接收完成之后,對(duì)JSON數(shù)據(jù)進(jìn)行解析。
解析結(jié)果
7.疫情數(shù)據(jù)的顯示
數(shù)據(jù)解析出來之后,剩下的就簡(jiǎn)單了,把上一篇文章中9341的驅(qū)動(dòng)文件移植過來就好了。
液晶屏使用的是3.2寸 LCD,IL9341驅(qū)動(dòng)芯片,320*240分辨率,16位并口。由于屏幕分辨率比較低,可顯示的內(nèi)容有限,所以只是顯示了最基本的幾個(gè)疫情數(shù)據(jù)。為了減小程序大小,GUI只實(shí)現(xiàn)了基本的畫點(diǎn),畫線函數(shù),字符的顯示,采用的是部分字符取模,只對(duì)程序中用到的漢字和字符進(jìn)行取模。為了增強(qiáng)可移植性,程序中并沒有使用外置SPI Flash存儲(chǔ)整個(gè)字庫(kù)。
由于RT-Thread Studio使用的HAL庫(kù),所以LCD的GPIO初始化函數(shù)需要修改一下:
voidlcd_gpio_init(void) { GPIO_InitTypeDefGPIO_InitStructure; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); __HAL_AFIO_REMAP_SWJ_NOJTAG(); GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull=GPIO_PULLUP; GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_HIGH; GPIO_InitStructure.Pin=GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_6; HAL_GPIO_Init(GPIOC,&GPIO_InitStructure);//GPIOC GPIO_InitStructure.Pin=GPIO_PIN_8;//背光引腳PA8 HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIOC GPIO_InitStructure.Pin=GPIO_PIN_All; HAL_GPIO_Init(GPIOB,&GPIO_InitStructure); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_6,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_All,GPIO_PIN_SET); }
延時(shí)函數(shù)換成:
rt_thread_mdelay(nms);
還有一點(diǎn),在Keil中,文字編碼選擇GBK編碼,1個(gè)漢字占用2個(gè)字節(jié),而RT-Thread Studio為UTF-8編碼,1個(gè)漢字占用3個(gè)字節(jié),漢字顯示函數(shù)需要調(diào)整:
voidgui_show_chn(uint16_tx0,uint16_ty0,char*chn) { uint8_tidx=0; uint8_t*code[3];//UTF-8:國(guó)=E59BBD uint8_tsize=sizeof(FONT_16X16_TABLE)/sizeof(FONT_16X16_TABLE[0]); /*遍歷漢字,獲取索引*/ for(idx=0;idx
疫情數(shù)據(jù)顯示函數(shù):
voidgui_show_ncov_data(structNCOV_DATAchina,structNCOV_DATAglobal) { uint8_ty0=20; lcd_clear(BLACK); gui_show_bar(); gui_drawLine(0,18,320,DIR_X,WHITE); gui_drawLine(0,38,320,DIR_X,WHITE); gui_drawLine(0,138,320,DIR_X,WHITE); gui_drawLine(0,158,320,DIR_X,WHITE); gui_drawLine(0,220,320,DIR_X,WHITE); /*"國(guó)內(nèi)疫情"*/ gui_show_chn_string(128,y0,"國(guó)內(nèi)疫情"); gui_show_line_data(40,"現(xiàn)存確診:",china.currentConfirmedCount,"較昨日:",china.currentConfirmedIncr); gui_show_line_data(60,"累計(jì)確診:",china.confirmedCount,"較昨日:",china.confirmedIncr); gui_show_line_data(80,"累計(jì)治愈:",china.curedCount,"較昨日:",china.curedIncr); gui_show_line_data(100,"現(xiàn)存重癥:",china.seriousCount,"較昨日:",china.seriousIncr); gui_show_line_data(120,"累計(jì)死亡:",china.deadCount,"較昨日:",china.deadIncr); /*全球疫情*/ gui_show_chn_string(128,140,"全球疫情"); gui_show_line_data(160,"現(xiàn)存確診:",global.currentConfirmedCount,"較昨日:",global.currentConfirmedIncr); gui_show_line_data(180,"累計(jì)治愈:",global.curedCount,"較昨日:",global.curedIncr); gui_show_line_data(200,"累計(jì)死亡:",global.deadCount,"較昨日:",global.deadIncr); gui_show_chn_string(160,222,"更新于:"); gui_show_F8X16_String(230,222,china.updateTime,GREEN); }
最終顯示效果
最終效果
開源地址
代碼已經(jīng)開源,地址在文末,歡迎大家參與,豐富這個(gè)小項(xiàng)目的功能!
基于STM32+RT-Thread的疫情監(jiān)控平臺(tái)
https://github.com/whik/rtt_2019_ncov
基于STM32F103的疫情監(jiān)控平臺(tái)(裸機(jī)版)
https://github.com/whik/stm32_2019_ncov
-
物聯(lián)網(wǎng)
+關(guān)注
關(guān)注
2909文章
44704瀏覽量
374144 -
軟件包
+關(guān)注
關(guān)注
0文章
104瀏覽量
11611 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1293瀏覽量
40211
原文標(biāo)題:基于STM32+RT-Thread的新冠肺炎疫情監(jiān)控平臺(tái)
文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論