stm32 基于蓝桥物联网赛 oled屏使用

[复制链接]
发表于 2025-10-19 13:47:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
oled屏是物联网物联网赛道必考的标题,其综合了I2C协定等等知识,不讲原理,纯讲应用,现在开始。
增补资源代码

资源包给我们的代码是不全的,好比oled屏中的OLED_Write函数并没有界说,因此我们须要先将该函数补全。这个补全的代码可以写在I2C.c文件中,留意,要写在代码插销内里。该代码是要死记硬背的,没有本事可言。。。
  1. void OLED_Write(uint8_t ucType,uint8_t ucData)
  2. {
  3.     uint16_t pdata[2] = {0};
  4.     pdata[0] = ucType;
  5.     pdata[1] = ucData;
  6.     HAL_I2C_Master_Transmit(&hi2cl,0x78,pdata,2,10);
  7. }
复制代码
当我们增补完代码以后,就应该初始化oled了,在main函数内里写上OLED_Init函数。
task.h文件

我们平 平常使用oled屏幕,一样平常不会只使用它的一个功能,因此我们须要设置状态机。我们另开一个.c和.h文件,用于编写我们的任务函数。
oled状态机

起首我们先界说一个罗列参数,内里生存着状态机的状态,分为主状态和时间表现状态。令主状态为0,则时间表现状态就为1.oled一样平常来说贯彻整个项目,因此我们extern一个状态变量,使其可以在整个项目中使用,便于变革。
  1. typedef enum      //oled屏幕的状态(状态机
  2. {
  3.         State_Main = 0,
  4.         State_Time_Num
  5. }interface;
  6. extern interface state; //定义一个全文件变量,可以被项目中所有文件使用
复制代码
按键当前状态

 按键状态我们使用经典三段式,up体现按键松开,down体现按键按下,old体现的是旧状态。团结经典三段消抖代码,可以做到有用消除呆板抖动。
  1. typedef struct
  2. {
  3.         uint8_t Key_Up;
  4.         uint8_t Key_Down;
  5.         uint8_t Key_Old;
  6. }Key_State;
复制代码
任务时间gap(革新率)

界说一个布局体,内里用于存放两个变乱的革新频率,在两个任务开始的时间,都会举行判断。这两个参数会在滴答计时器内里举行累加。由于此次我们代码想要实现的就是数字的累加,因此额外界说了一个参数来存放时间参数。
  1. typedef struct           //定义一个结构体,保存事件的运行间隔时间,在systick中断函数中进行累加。
  2. {
  3.         uint16_t Oled_Time;
  4.         uint16_t Key_Time;
  5.        
  6. }Task_Time;
  7. extern Task_Time task_time;
  8. extern uint16_t Time_Num;
复制代码
  1.         task_time.Key_Time++;
  2.         task_time.Oled_Time++;
  3.         Time_Num++;//滴答中断中补充代码
复制代码
 宏界说

在.h文件中实现一些宏界说,起首界说oled和按键的革新时间,这代表了oled和按键工作函数每几秒工作一次。接着是按键的宏界说。无需严格写成如许子,只要三个数据差别即可。
  1. #define Oled_Min_Time 200                //定义oled和按键的最小刷新时间
  2. #define Key_Min_Time        20               
  3. #define Asw_None 0x00    //定义按键,为后续的逻辑运算做准备
  4. #define Asw_1 0x01                                        //二进制为0001
  5. #define Asw_2 0x02                         //二进制为0010  #define 后面不需要加;号
复制代码
task.c文件

全局参数界说

界说四大件,纵然在.h文件中已经界说过,但是在.c文件中还是得在界说一次。界说已往的状态是为了实现革新,假如我们没有举行公道的革新,会导致屏幕在切换的时间处于叠加状态,这是显然不可的。
  1. interface state = State_Main;                         //定义当前状态
  2. interface old_state = State_Main;       //定位过去状态
  3. Task_Time task_time;                                        //gap时间
  4. Key_State Key;                                                        //按键状态
  5. uint16_t Time_Num;
复制代码
 OLED处置惩罚函数

oled函数中须要实现的就是屏幕表现的题目。起首界说oled的数据缓冲区,这是一个uint8_t范例的数组,一样平常来说只须要20个单元即可。接着判断是否已经到了革新时间,假如到了,即oled累加以后的时间已经大于最小革新时间了,那就革新即工作一次,接着把oled屏的时间置零。假如没到,那就直接return,不革新屏幕。接着进入switch选择,选择的目标是我们设定的state,state的改变由按键处置惩罚函数决定。假如当前设定为主界面,那就判断现在的界面和老界面是否一样,假如不一样,那就把老界面改为新界面的状态,保持状态划一,而且把老界面举行一次整理;接着将想要表现的写入数据缓冲中,然后break;时间界面也是同理。在处置惩罚完这些后,表现oled。
  1. void Oled_Proc()
  2. {
  3.         uint8_t Oled_buf_line1 [20] = {0};                        //定义第一行要显示的数据
  4.         uint8_t Oled_buf_line2 [20] = {0};                        //定义第二行要显示的数据
  5.        
  6.         if(task_time.Oled_Time < Oled_Min_Time)        return;                                //判断是否到了刷新时间
  7.         task_time.Oled_Time = 0;                                                                                                                        //如果到了刷新时间,就把记时清零
  8.         switch(state)                                                                                                                                                                //判断目前状态
  9.         {                                                       
  10.                 case State_Main:
  11.                                 if(state!=old_state)                           //如果当前状态和之前状态不一样,就刷新oled
  12.                                 {
  13.                                         old_state = state;
  14.                                         OLED_Clear();
  15.                                 }
  16.                                 sprintf((char*)Oled_buf_line1,"HELLO WORLD");                //主页面就打印hello world,把数据写入line1缓冲区
  17.                                 break;
  18.                 case State_Time_Num:
  19.                                 if(state!=old_state)
  20.                                 {
  21.                                         old_state = state;
  22.                                         OLED_Clear();
  23.                                 }
  24.                                 sprintf((char*)Oled_buf_line1,"Time:%05d",Time_Num);        //时间界面打印时间,所以把时间数据写入line2缓存区
  25.                                 break;
  26.         }
  27.                 OLED_ShowString(0,0,Oled_buf_line1,16);                                                                        //oled的显示
  28.                 OLED_ShowString(0,0,Oled_buf_line2,16);       
  29. }
复制代码
按键处置惩罚函数 

按键处置惩罚函数刚开始也是同理,先判断按键革新时间到了没,接着界说一个代表按键的值,Key_Value.由于现在我们任务要的是asw1按下,那么我们就判断asw的状态,假如asw按下(即asw为reset状态),则把Key_Value设置为Asw_1.假如不是,那就把他设置为Asw_None。接着就是经典三段防抖。up的判断逻辑是先确定是否有状态的改变(Key_Value ^ Key.Key_Old),然后与上Key_Value,这是判断现在是松按键的时间。down也是同理。而oled_old只要每次在末了革新一下即可。接着就是朴素无华的检测,假如按下以后是Asw_1那就切换页面,假如不是,那就不进if
  1. void Key_Proc()
  2. {
  3.                 if(task_time.Key_Time < Key_Min_Time)        return;                                                //判断是否到key_proc的刷新时间
  4.                 task_time.Key_Time = 0;
  5.                         uint16_t Key_Value;
  6.                 if(HAL_GPIO_ReadPin(ASW1_GPIO_Port,ASW1_Pin) == GPIO_PIN_RESET)      //判断按下的是不是asw1,如果是,就赋值,如果不是甚至没按,就为0
  7.                 {
  8.                         Key_Value = Asw_1;
  9.                 }
  10.                 else   
  11.                 {
  12.                         Key_Value = Asw_None;
  13.                 }
  14.                 Key.Key_Up = Key_Value &(Key_Value ^ Key.Key_Old);                                        //三段经典消除按键抖动
  15.                 Key.Key_Down = ~Key_Value &(Key_Value ^ Key.Key_Old);       
  16.                 Key.Key_Old = Key_Value;
  17.        
  18.         if(Key.Key_Down == Asw_1)                                                                                                                                                //确定按下了,就开始切换工作
  19.         {
  20.                 if(state == State_Main) state = State_Time_Num;
  21.                 else state = State_Main;
  22.                 Key.Key_Down = Asw_None;                                                                                                                                                //复位key_down
  23.         }                               
  24. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表