基于STM32单片机实现屏幕休眠后OLED屏幕滚动效果
这次做项目时需要实现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 }