本文來源電子發燒友社區,作者:李元江, 帖子地址:https://bbs.elecfans.com/jishu_2026438_1_1.html
上一次帖子,已經通過網絡獲取天氣數據,但是還沒顯示到顯示屏上。今天的帖子我寫的是關于如何取模天氣圖片,并顯示天氣圖標和天氣數據。
一、ssd1306顯存填充
上一次帖子,已經通過網絡獲取天氣數據,但是還沒顯示到顯示屏上。今天的帖子我寫的是關于如何取模天氣圖片,并顯示天氣圖標和天氣數據。
顯示板使用的OLED驅動芯片為SSD1306,我們來看看這款芯片的顯存和該顯存填充方式。下面是從SSD1303芯片手冊上的截圖,可以看得出它的顯存是大小為128*64bit的RAM,并且分成為8頁,PAGE0-PAGE7。顯示板像素點大小為128*64,所以一個像素點對應RAM中的1bit。
往RAM的某一位寫入1或者0,該位對應的像素點就顯示亮點或者不顯示。但是它是按照什么順序寫入數據的。下面也是從芯片手冊上的截圖。
可以看得出RAM填充順序了 ,寫入一個字節數據時,最低位數據寫入一頁中最上面那行,最高位寫入一頁中最下面那行。這樣,使用取模軟件取模圖片或者字符時,我們才能知道按照什么順序取模。之后再寫相應代碼,按照順序把取模數據寫入RAM中。
二、天氣圖標取模
我使用的是下面這款取模軟件,我覺得圖標取模不太好,不知道大家有沒有推薦的。需要根據SSD1306進行取模軟件的設置。比較重要的是取模方式的選擇,這是跟SSD1306顯示填充順序對應的,我們需要選擇列行式。其他數據點陣選擇48,自定義格式選擇C51。
選擇晴圖標,生成如下數組。
上面的小花就是太陽圖標,是有點丑,先湊合用吧。
二、軟件設計
1、顯示天氣圖標
我們已經按照SSD1306顯存填充順序,取模好圖片數據,接下來按照順序把數據寫入RAM就行了,代碼如下。
- typedef enum
- {
- QINGLOGO =0,
- YINGLOGO,
- DUOYULOGO,
- YULOGO,
- LEIYULOGO,
- XUELOGO,
- }WEATHER_TYPE;
- void OLED_ShowWeather(uint8_t x,uint8_t y,WEATHER_TYPE type)
- {
- unsigned char (*temp)[48];
- //if(type ==qinglogo )
- //temp=Qing48;
- switch(type)
- {
- case QINGLOGO: temp=Qing48;break;
- case YINGLOGO: temp=Yin48;break;
- case YULOGO: temp=Yu48;break;
- case LEIYULOGO:temp=LeiYu48;break;
- case DUOYULOGO:temp=DuoYun48;break;
- case XUELOGO: temp=Xue48;break;
- default :
- temp=Qing48;
- break;
- }
- //OledSetPosition(x,y);
- for(uint8_t i=0;i<6;i++){
- OledSetPosition(x,y+i);
- for(uint8_t j = 0;j<48;j++){
- WriteData(temp[i][j]);
- }
- }
- }
OLED顯示板上的兩個按鍵,主要用于界面切換、獲取實時時間、天氣數據。增加了按鍵任務,主要進行這兩個按鍵的處理。右邊按鍵,按下后可以切換界面,現在設置有四個界面。在時間顯示界面按下左鍵,會獲取實時時間。在天氣顯示界面,按下左鍵會獲取實時天氣。
- #include
- #include
- #include
- #include "ohos_init.h"
- #include "cmsis_os2.h"
- #include "wifiiot_gpio.h"
- #include "wifiiot_gpio_ex.h"
- #include "wifiiot_pwm.h"
- #include "wifiiot_adc.h"
- ?
- #include "oled_ssd1306.h"
- ?
- #defineanalog_KEY_CHAN_NAME WIFI_IOT_ADC_CHANNEL_2
- ?
- typedef enum{
- TIMESCREEN=0,
- NOWSCREEN,
- TOSCREEN,
- ATOSCREEN,
- } SCREEN_STATUS;
- extern SCREEN_STATUS Now_Screen ;
- extern SCREEN_STATUS Last_Screen ;
- ?
- typedef enum{
- GET_NORMAL =0 ,
- GET_PROPRESS,
- GET_SUC,
- GET_FAIL,
- }GET_STATUS;
- ?
- GET_STATUS Get_Status = GET_NORMAL;
- GET_STATUS Last_Get_Status = GET_NORMAL;
- ?
- extern void getNtpTime(void);
- extern bool getWeather(void);
- ?
- static float ConvertToVoltage(unsigned short data)
- {
- return (float)data * 1.8 * 4 / 4096; /* adc code equals: voltage/4/1.8*4096*/
- }
- ?
- static void KeyTask(void *arg)
- {
- (void)arg;
- unsigned short data = 0;
- ?
- GpioInit();
- static bool keyflag = false;
- while(1)
- {
- AdcRead(ANALOG_KEY_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0);
- float voltage = ConvertToVoltage(data);
- ?
- if((voltage>0.45 && voltage<0.65)&&(!keyflag))
- {
- keyflag = true;
- //OledShowString(16,7,"Sync time...",1);
- //getNtpTime();
- //OledFillScreen(0);
- switch (Now_Screen){
- case TIMESCREEN:
- //OledShowString(16,7,"Sync time...",1);
- Get_Status = GET_PROPRESS;
- getNtpTime();
- //OledFillScreen(0);
- Get_Status = GET_SUC;
- break;
- case NOWSCREEN:
- //OledShowString(0,7,"Get Weather...",1);
- Get_Status = GET_PROPRESS;
- if(getWeather())
- //OledFillScreen(0);
- Get_Status = GET_SUC;
- else
- {
- //OledShowString(0,7,"Get fail...",1);
- Get_Status = GET_FAIL;
- }
- break;
- case TOSCREEN:
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- break;
- case ATOSCREEN:
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- break;
- ?
- default:
- break;
- }
- }
- else if((voltage>0.9 && voltage<1)&&(!keyflag))
- {
- keyflag = true;
- Now_Screen ++;
- if(Now_Screen > ATOSCREEN)
- {
- Now_Screen = TIMESCREEN;
- }
- }
- ?
- if((!(voltage>0.45 && voltage<0.65)) && (!(voltage>0.9 && voltage<1))) {
- keyflag = false;
- }
- ?
- usleep(300000);
- }
- }
- ?
- static void KeyTaskHandle(void)
- {
- osThreadAttr_t attr;
- attr.name = "KeyTask";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 4096;
- attr.priority = osPriorityNormal+2;
- ?
- if (osThreadNew(KeyTask, NULL, &attr) == NULL) {
- printf("[KeyTaskHandle] Falied to create KeyTask!n");
- }
- }
- APP_FEATURE_INIT(KeyTaskHandle);
修改oled_demo.c內容。增加頁面切換,獲取時間、天氣數據情況提示,顯示天氣數據和天氣圖標。
- typedef enum{
- TIMESCREEN=0,
- NOWSCREEN,
- TOSCREEN,
- ATOSCREEN,
- } SCREEN_STATUS;
- SCREEN_STATUS Now_Screen = TIMESCREEN;
- SCREEN_STATUS Last_Screen = TIMESCREEN;
- ?
- typedef enum{
- GET_NORMAL =0 ,
- GET_PROPRESS,
- GET_SUC,
- GET_FAIL,
- }GET_STATUS;
- extern GET_STATUS Get_Status ;
- extern GET_STATUS Last_Get_Status ;
- ?
- static uint8_t i=0;
- ?
- static void TimeScreenDisp(void)
- {
- //OledShow
- rtc_time_t mData;
- OLED_ShowCHinese(0,3,0);//溫
- OLED_ShowCHinese(16,3,2);//度
- OledShowChar(32,3,':',2);
- sprintf((char *)TimeStr,"%02d",
- (uint32_t)temperature);
- OledShowString(40,3,(char *)TimeStr,2);
- OLED_ShowCHinese(64,3,1);//濕
- OLED_ShowCHinese(80,3,2);//度
- OledShowChar(96,3,':',2);
- sprintf((char *)TimeStr,"%02d",
- (uint32_t)humidity);
- OledShowString(104,3,(char *)TimeStr,2);
- covUnixTimeStp2Beijing(timedata, &mData);
- sprintf((char *)TimeStr,"%04d-%02d-%02d",
- mData.ui8Year, mData.ui8Month, mData.ui8DayOfMonth);
- OledShowString(24,0,(char *)TimeStr,1);
- sprintf((char *)TimeStr,"%02d:%02d:%02d",
- mData.ui8Hour,mData.ui8Minute,mData.ui8Second);
- OledShowString(32,1,(char *)TimeStr,1);
- ?
- if(Get_Status != Last_Get_Status)
- {
- Last_Get_Status = Get_Status;
- switch ( Get_Status)
- {
- case GET_NORMAL:
- break;
- case GET_PROPRESS:
- OledShowString(16,7,"Sync time...",1);
- break;
- case GET_SUC:
- OledClearString(16,7,"Sync time...",1);
- OledShowString(16,7,"Sync Suc...",1);
- break;
- case GET_FAIL:
- OledClearString(16,7,"Sync time...",1);
- OledShowString(16,7,"Sync fail...",1);
- break;
- default:
- break;
- }
- }
- }
- ?
- static void DispWeather(uint8_t x, uint8_t y ,uint8_t code){
- switch(code)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- OLED_ShowWeather(x,y,QINGLOGO);
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- OLED_ShowWeather(x,y,DUOYULOGO);
- break;
- case 9:
- case 10:
- OLED_ShowWeather(x,y,YINGLOGO);
- break;
- case 11:
- case 12:
- ?
- OLED_ShowWeather(x,y,LEIYULOGO);
- break;
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- OLED_ShowWeather(x,y,YULOGO);
- break;
- case 20:
- case 21:
- case 22:
- case 23:
- case 24:
- case 25:
- OLED_ShowWeather(x,y,XUELOGO);
- break;
- case 30:
- //OLED_ShowWeather(x,y,YULOGO);
- //break;
- default:
- OLED_ShowWeather(x,y,QINGLOGO);
- break;
- }
- ?
- }
- ?
- extern weather weatherValue;
- static voidWeatherDisp(SCREEN_STATUS Screen){
- switch (Screen)
- {
- case NOWSCREEN:
- DispWeather(5, 1 ,weatherValue.nowcode);
- OLED_ShowCHinese(56,0,9);//今
- OLED_ShowCHinese(72,0,12);//天
- sprintf((char *)DispStr,"%02d",
- (uint32_t)weatherValue.nowtemp);
- OledShowString(60,5,(char *)DispStr,2);
- OLED_ShowCHinese(76,5,13);//天
- sprintf((char *)DispStr,"%02d/%02d",
- (uint32_t)weatherValue.low[Screen-1],(uint32_t)weatherValue.high[Screen-1]);
- OledShowString(60,3,(char *)DispStr,2);
- sprintf((char *)DispStr,"%d%%",
- (uint32_t)weatherValue.humi[Screen-1]);
- OledShowString(100,5,(char *)DispStr,2);
- break;
- case TOSCREEN:
- DispWeather(5, 1 ,weatherValue.code[Screen-1]);
- OLED_ShowCHinese(56,0,10);//明
- OLED_ShowCHinese(72,0,12);//天
- sprintf((char *)DispStr,"%02d/%02d",
- (uint32_t)weatherValue.low[Screen-1],(uint32_t)weatherValue.high[Screen-1]);
- OledShowString(60,3,(char *)DispStr,2);
- sprintf((char *)DispStr,"%d%%",
- (uint32_t)weatherValue.humi[Screen-1]);
- OledShowString(70,5,(char *)DispStr,2);
- break;
- case ATOSCREEN:
- DispWeather(5, 1 ,weatherValue.code[Screen-1]);
- OLED_ShowCHinese(56,0,11);//后
- OLED_ShowCHinese(72,0,12);//天
- sprintf((char *)DispStr,"%02d/%02d",
- (uint32_t)weatherValue.low[Screen-1],(uint32_t)weatherValue.high[Screen-1]);
- OledShowString(60,3,(char *)DispStr,2);
- sprintf((char *)DispStr,"%d%%",
- (uint32_t)weatherValue.humi[Screen-1]);
- OledShowString(70,5,(char *)DispStr,2);
- break;
- default:
- break;
- }
- if(Get_Status != Last_Get_Status)
- {
- Last_Get_Status = Get_Status;
- switch ( Get_Status)
- {
- case GET_NORMAL:
- break;
- case GET_PROPRESS:
- OledShowString(0,7,"Get Weather...",1);
- break;
- case GET_SUC:
- OledClearString(0,7,"Get Weather...",1);
- OledShowString(0,7,"Get Suc...",1);
- i=0;
- break;
- case GET_FAIL:
- OledClearString(0,7,"Get Weather...",1);
- OledShowString(0,7,"Get fail...",1);
- i=0;
- break;
- default:
- break;
- }
- }
- }
- static void OledTask(void *arg)
- {
- (void)arg;
- GpioInit();
- OledInit();
- OledFillScreen(0x00);
- while (1) {
- if(Now_Screen != Last_Screen)
- {
- Last_Screen = Now_Screen;
- OledFillScreen(0);
- Get_Status = GET_NORMAL;
- Last_Get_Status = GET_NORMAL;
- i=0;
- }
- ?
- if((Get_Status == GET_FAIL) ||(Get_Status == GET_SUC))
- {
- i++;
- if(i > 20)
- {
- Get_Status = GET_NORMAL;
- i=0;
- ?
- switch(Now_Screen){
- case TIMESCREEN:
- OledClearString(16,7,"Sync time...",1);
- break;
- case NOWSCREEN:
- case TOSCREEN:
- ?
- case ATOSCREEN:
- printf("clear oled i = %dn",i);
- OledClearString(0,7,"Get Weather...",1);
- break;
- default :
- break;
- ?
- }
- }
- }
- ?
- switch (Now_Screen){
- ?
- case TIMESCREEN:
- TimeScreenDisp();
- break;
- ?
- case NOWSCREEN:
- WeatherDisp(NOWSCREEN);
- break;
- ?
- case TOSCREEN:
- WeatherDisp(TOSCREEN);
- break;
- ?
- case ATOSCREEN:
- WeatherDisp(ATOSCREEN);
- break;
- ?
- default:
- break;
- }
- usleep(100000);
- }
- }
現在時間調整是通過每一秒時間戳加1,再把時間戳轉化為北京時間,到達時間的更新。為了減少任務中因為其他函數存在,增加時間誤差,所以單獨創建一個任務來進行時間戳的調整。
- #include
- #include
- #include
- ?
- #include "ohos_init.h"
- #include "cmsis_os2.h"
- uint32_t timedata=1608362368;
- ?
- static void RtcTask(void *arg)
- {
- (void)arg;
- while(1)
- {
- timedata++;
- sleep(1);
- }
- }
- ?
- static void RtcTaskHandle(void)
- {
- osThreadAttr_t attr;
- attr.name = "RtcTask";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 512;
- attr.priority = osPriorityNormal;
- ?
- if (osThreadNew(RtcTask, NULL, &attr) == NULL) {
- printf("[RtcTaskHandle] Falied to create KeyTask!n");
- }
- }
- APP_FEATURE_INIT(RtcTaskHandle);
5、修改BUILD.gn
修改OLED文件夾下的BUILD.gn文件,sources中加入keytask.c
按下右邊按鍵,可以切換界面,有四個界面,分別為時間顯示界面,今天、明天、后天天氣顯示界面。在時間顯示界面按下左鍵,會獲取實時時間,在天氣顯示界面,按下左鍵會獲取實時天氣,并且顯示天氣獲取情況提示。
????四、總結
這一篇先寫到這里,下一篇是關于通過一個公網的中轉服務器,進行wifiiot和手機之間的遠程數據傳輸。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
wi-fi
+關注
關注
14文章
2147瀏覽量
124612 -
HarmonyOS
+關注
關注
79文章
1979瀏覽量
30274 -
HiSpark
+關注
關注
1文章
156瀏覽量
6938
發布評論請先 登錄
相關推薦
Wi-Fi 8要來了!未來Wi-Fi技術演進方向揭秘
產品銷售中,雖然Wi-Fi 7產品的銷量份額快速從年初的個位數百分比增長至14%,但Wi-Fi 6產品的銷量份額依然穩定在60%左右。如果從存量設備來看,那么Wi-Fi 7路由器的占比將遠遠小于這個數。 ? 智能手機等終端設備已
華為海思正式進入Wi-Fi FEM賽道?
大家都知道了,2018年11 月離開銳迪科(RDA),前往福建晉江創立三伍微,專注于Wi-Fi射頻前端芯片,從路由器Wi-Fi FEM,到手機Wi-Fi FEM,再到IoT FEM全覆
發表于 12-11 17:42
從Wi-Fi 4到Wi-Fi 7:網速飆升40倍的無線革命
1 Wi-Fi技術的快速發展 每一代新的Wi-Fi協議發布,都會帶來更高的無線速率。 ? 從Wi-Fi 4到Wi-Fi 7:無線網絡技術顯著提升,實現了網速的巨大飛躍。 ? ?
Wi-Fi 7與Wi-Fi 6E有什么區別
也許很多人還在考慮是否要將使用的Wi-Fi設備升級到Wi-Fi 6或Wi-Fi 6E,而這些標準的繼任者卻已經開始“登堂入室”了。Wi-Fi 7是新一代
IR900 Wi-Fi聯網的配置過程
, 通過SSID掃描可以查看;輸入密碼,點擊保存;
在SSID掃描頁面中查看是否連接成功, 如果沒有請檢查認證方式、加密方式、密碼是否輸入正確;
Wi-Fi掃描顯示“已連接”,進入“快速向導-新建WAN
發表于 07-25 06:09
未來的Wi-Fi路由器
轉載自——鐘林談芯 沒有創新就沒有未來,Wi-Fi路由器也是如此。 進入2024年以后,Wi-Fi路由器市場變得更加艱難,利潤大幅下滑,BOM成本價高于市場價,接不接訂單,都陷入兩難。 國內主芯片
DA16200 超低功耗 Wi-Fi 模塊開發套件 Pro數據手冊
電子發燒友網站提供《DA16200 超低功耗 Wi-Fi 模塊開發套件 Pro數據手冊.rar》資料免費下載
發表于 05-30 17:53
?1次下載
DA16200 超低功耗 Wi-Fi 模塊開發套件數據手冊
電子發燒友網站提供《DA16200 超低功耗 Wi-Fi 模塊開發套件數據手冊.rar》資料免費下載
發表于 05-30 17:13
?0次下載
驗證物聯網Wi-Fi HaLow用例的MM6108-EKH08開發套件來啦
驗證物聯網Wi-Fi HaLow用例的MM6108-EKH08開發套件來啦 MM6108-EKH08開發套件專為驗證物聯網Wi-Fi HaLow用例而設計。該
Wi-Fi HaLow和傳統Wi-Fi的區別
Wi-Fi HaLow和傳統Wi-Fi的區別? Wi-Fi是一種無線網絡技術,可以連接到互聯網或局域網,為用戶提供無線上網的便利。隨著科技的發展和互聯網的普及,Wi-Fi也在不斷演進和
康普攜手Wi-Fi聯盟,RUCKUS Wi-Fi 7系列接入點成Wi-Fi
康普高級副總裁兼網絡、智能蜂窩和安全解決方案總裁Bart Giordano對此表示: “我們非常榮幸能與Wi-Fi Alliance形成長期合作伙伴關系,將我們的RUCKUS Wi-Fi 7 接入點平臺作為Wi-Fi CERT
BT Wi-Fi模式是否可以通過ModustoolBox對套件進行編程來實現?
想配置用于分析 CYW43439 的 CY8CPROTO-062S2-43439 原型開發套件。
瀏覽文檔我無法弄清楚如何在不同的 Wi-Fi 和藍牙模式(電源模式、連接模式等)下配置套件。
在
發表于 01-22 06:19
評論