這次做項目時需要實現OLED屏幕上字符滾動的功能,從網上找到一個參考:https://blog.csdn.net/tbmmagic/article/details/111999673
int main(void) { delay_init(); //延時函數初始化 NVIC_Configuration(); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級 OLED_Init(); //初始化OLED OLED_Clear(0); //清屏(全黑) OLED_WR_Byte(0x2E,OLED_CMD); //關閉滾動 OLED_WR_Byte(0x26,OLED_CMD); //水平向左或者右滾動 26/27 OLED_WR_Byte(0x00,OLED_CMD); //虛擬字節 OLED_WR_Byte(0x00,OLED_CMD); //起始頁 0 OLED_WR_Byte(0x07,OLED_CMD); //滾動時間間隔 OLED_WR_Byte(0x07,OLED_CMD); //終止頁 7 OLED_WR_Byte(0x00,OLED_CMD); //虛擬字節 OLED_WR_Byte(0xFF,OLED_CMD); //虛擬字節 TEST_MainPage(); //主界面顯示測試 OLED_WR_Byte(0x2F,OLED_CMD); //開啟滾動 } void TEST_MainPage(void) { GUI_ShowString(28,0,"HELLO",16,1); GUI_ShowCHinese(12,16,16,"歡迎來到重慶交通大學",1); delay_ms(1500); delay_ms(1500); }
需要調用按鍵對切換屏幕上的菜單顯示,修改數據。長時間未操作,切換到休眠頁面,休眠時屏幕滾動顯示時間,發生動作時解除休眠。
找到參考代碼后,需要解決的一個問題時在while(1)循環里調用屏幕滾動的函數,出現字符無法滾動的現象。我使用了標志位解決了這個問題。
下面是我進行的改動
1 char row2[22]={0}; 2 u8 weakup_flag=1; //喚醒標志初始為1, 3 //屏幕滾動函數 4 void OLED_SleepShow() 5 { 6 OLED_Init(); //初始化OLED 7 OLED_Clear(); //清屏(全黑) 8 OLED_WR_Byte(0x2E,OLED_CMD); //關閉滾動 9 OLED_WR_Byte(0x26,OLED_CMD); //水平向左或者右滾動 26/27 10 OLED_WR_Byte(0x00,OLED_CMD); //虛擬字節 11 OLED_WR_Byte(0x00,OLED_CMD); //起始頁 0 12 OLED_WR_Byte(0x07,OLED_CMD); //滾動時間間隔 13 OLED_WR_Byte(0x07,OLED_CMD); //終止頁 7 14 OLED_WR_Byte(0x00,OLED_CMD); //虛擬字節 15 OLED_WR_Byte(0xFF,OLED_CMD); //虛擬字節 16 17 //使用snprintf需要#include " " #include "stdio.h"或者#include "string.h" 忘了,百度一下
//這個語句太復雜了,作用就是將轉換得到的str寫入row2,之后顯示在OLED屏幕上
18 snprintf(row2,22," 20%s-%s-%s %s:%s:%s ",convert(tmp_time.year, 2, 0, 1, str),convert(tmp_time.mon, 2, 0, 1, str1), 19 convert(tmp_time.day, 2, 0, 1, str2),convert(tmp_time.hour, 2, 0, 1, str3),convert(tmp_time.min, 2, 0, 1, str4) 20 ,convert(tmp_time.sec, 2, 0, 1 , str5)); 21 OLED_Print(0,2,row2,24); //調用相關的顯示字符函數 22 delay_ms(1500); 23 delay_ms(1500); 24 25 OLED_WR_Byte(0x2F,OLED_CMD); //開啟滾動 26 } 27 28 // /* 29 // * [convert 浮點型輸出為字符串] 30 // * @Author WC 31 // * @DateTime 2019-06-29 32 // * @param data [浮點數] 33 // * @param digit [總位數] 34 // * @param dec_digit [小數位數] 35 // * @param mode [0:空格占位符 1:0占位符] 36 // * @param buf [緩存區] 37 // * @return [字符串] 38 // */ 39 char* convert(float data, u8 digit, u8 dec_digit, u8 mode , char* buf) 40 { 41 if (mode == 0) 42 { 43 sprintf(strformat, "%%%d.%df", digit, dec_digit); 44 } 45 else if (mode == 1) 46 { 47 sprintf(strformat, "%%0%d.%df", digit, dec_digit); 48 } 49 sprintf(buf, strformat, data); 50 return buf; 51 } 52 53 /* 54 屏幕喚醒判斷 55 按鍵按下或者檔位發生變化 喚醒屏幕 56 當前屏幕為主菜單且 57 */ 58 void WeakupScreen(Menu *menu,u8 key) 59 { 60 if((key!=0)||(gearposition!=0)) //按鍵按下或者檔位變化 61 { 62 time_flag=0; 63 weakup_flag=1; //喚醒標志 64 65 } 66 //當前是主菜單並且達到休眠時間,我這里是調用了TIM3定時器,一個溢出中斷立一個time_flag. 67 if((menu->current==0)&&(time_flag>=dp.sleep_time)) 68 { 69 time_flag=0; 70 weakup_flag=0; 71 } 72 } 73 74 75 int main() 76 { 77 while(1) 78 { //如果處於喚醒狀態,就執行主要的功能函數,長時間未操作,休眠,切換標志位 79 if(weakup_flag==1) 80 { 81 // gearposition =GearPostion_Collect(); 82 key_value=KEY_Scan(0); 83 WeakupScreen(&menu,key_value); //通過鍵值得到Weakup標志位的值 84 // key_control(&menu,key_value); 85 // MenuSwitch(&menu,key_value); 86 // ScreenSleepDect(&menu); 87 key_value=0; //清除標志位 88 } 89 //休眠了, 90 if(weakup_flag==0) 91 { 92 OLED_SleepShow(); //滾動屏幕 93 //如果沒有這個while,會因為外面的while(1),導致一直刷新,無法滾動屏幕 94 while(!weakup_flag) 95 { 96 key_value=KEY_Scan(0); 97 WeakupScreen(&menu,key_value);//判斷是否被喚醒 98 key_value=0; 99 } 100 } 101 }