我的小车调试进度之:OLED菜单显示

小车调试进度四更~~


我觉得这个菜单显示方法贼好用!!!!!我的主控板上只留出来了三个按键,但是可以实现很多功能!!!!呱唧呱唧


  • 创建一个结构体:
typedef struct
{
	u8 current;//当前状态索引号
	u8 up;//向上翻索引号
	u8 down;//向下翻索引号
	u8 enter;//确认索引号
	void (*current_operation)(void);//函数指针
}key_table;
  • 确定OLED每个菜单显示界面的内容
    emmm,这个应该是在写程序前就构思好的,有一个大致的框架就可以(后面有想法可以再改),比如说一开始我显示什么样的界面,按下某个按键后进入什么界面,这个要构思清楚,每个显示界面就是一个功能函数,指向我们定义的该结构体里的函数指针。

  • 写出每个显示界面对应的的功能函数
    建议建立一个功能函数的文件fun.c,因为菜单显示界面的显示内容一般比较多,有一个专门的文件来放,后续代码的可读性会比较强,以我的部分功能函数举例:

、、、
void fun1(void)
{
    flagmode = 0;//初始化模式
    OLEDShowString(10, 0, "【蓝牙模式】");
    OLEDShowString(10, 17, " 寻迹模式 ");
    OLEDShowString(10, 33, " PWM调速模式 ");
    OLEDShowString(10, 49, " 返回 ");
    OLED_Refresh_Gram();
}

void fun2(void)
{
    flagmode = 0;
    OLEDShowString(10, 0, " 蓝牙模式 ");
    OLEDShowString(10, 17, "【寻迹模式】");
    OLEDShowString(10, 33, " PWM调速模式 ");
    OLEDShowString(10, 49, " 返回 ");
    OLED_Refresh_Gram();
}
、、、
  • 建立功能函数执行数组
    以我们建立的结构体的元素为功能函数执行数组的每个元素建立功能函数执行数组:
key_table code_table[10]=
{
    {0,0,0,1,(*fun10)},//第0层,显示Welcomem Use!!!!
    
    {1,4,2,5,(*fun1)},//第一层,显示【蓝牙模式】,寻迹模式,PWM调速模式,返回
    {2,1,3,6,(*fun2)},//第一层,显示蓝牙模式,【寻迹模式】,PWM调速模式,返回
    {3,2,4,9,(*fun3)},//第一层,显示蓝牙模式,寻迹模式,【PWM调速模式】,返回
    {4,3,1,0,(*fun4)},//第一层,显示蓝牙模式,寻迹模式,PWM调速模式,【返回】

	{5,5,5,1,(*fun5)},//第二层,蓝牙模式下显示"SuccessEnter!!!"(flagmode = 1)
	{6,6,6,2,(*fun6)},//第二层,寻迹模式下显示"SuccessEnter!!!"(flagmode = 2)
	{7,7,7,8,(*fun7)},//第二层,PWM模式下显示【PWML:】、PWMR:、返回  (flagmode = 3)       	
	{8,8,8,9,(*fun8)},//第二层,PWM模式下显示PWML:、【PWMR:】、返回  
	{9,8,7,4,(*fun9)}, //第二层,PWM模式下显示PWML:、PWMR:、【返回】  
};

{1,4,2,5,(*fun1)}为例,1-current,4-up,2-down,5-enter,fun1即为current_operation。
数组中的第一个元素(current)指向的是当前数组中的功能函数:比如0指向fun10,1指向fun1
再理解一下下面这段代码:

u8 func_index=0;//功能索引号
void (*current_operation_index)(void);//功能索引函数声明
//上面两行是变量和函数声明可以不看,主要理解下面两行
current_operation_index = code_table[func_index].current_operation;
(*current_operation_index)();//执行当前操作函数

如果此时func_index为1,那么code_table[1].current_operation;代表的就是fun1(*current_operation_index)();此行代码实现的功能就是执行功能函数fun1
那么到这里就明确了,我们只需要改变func_index的值,就可以实现不同的功能,什么时候改变呢?当然是按下按键的时候改变!!!!

  • 按键动作函数
void KeyAction(u8 keycode)
{
    if(keycode == 2)//按下按键KEY2
    {
        func_index = code_table[func_index].up;//功能函数的索引值为数组中的up索引值
        OLED_Clear();//注意每次按下按键才清一次屏
    }
    else if(keycode == 1)//按下按键KEY1
    {
        func_index = code_table[func_index].down;//功能函数的索引值为数组中的down索引值
        OLED_Clear();
    }
    else if(keycode == 3)//按下按键KEY3
    {
        func_index = code_table[func_index].enter;//功能函数的索引值为数组中的enter索引值
        OLED_Clear();
    }
}

现在再来理解一下{1,4,2,5,(*fun1)}这个数组,1指向fun1是固定不变的,而4、2、5分别代表的按下对应按键后func_index的值:4是up,那就意味着我们按下KEY2会执行功能函数fun4,2是down,所以按下KEY1执行fun2,那么按下KEY3就执行fun5,这三个数值是我们可以自己设定的。
可以看一下主函数中的内容:

 while (1)
   {
       KeyDriver();
       current_operation_index = code_table[func_index].current_operation;
	(*current_operation_index)();//执行当前操作函数
       if(flagmode == 1)//进入蓝牙模式(蓝牙模式下请把PWML和PWMR调成一致,效果会比较好哦~)
       {
           if(RxdOver)
           {
               RxdOver = 0;
               Read_Kz();
               USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//接收的数据处理完毕后打开接收中断
           }
       }
       else if(flagmode == 2)//进入寻迹模式
       {
           motor(M_REV, M_FOR, M_FOR, M_REV);//左横向
       }
       else if(flagmode == 3)//进入PWM调速模式
       {
           motor(M_FOR, M_FOR, M_FOR, M_FOR);//前进
       }
       else
       {
           motor(M_FREE, M_FREE,M_FREE, M_FREE);//停止
       }
   }

flagmode是当前模式标志,其值在功能函数中改变。


写在最后:

  • 在写代码时一定要注意哪些函数是要放在while(1)里一直执行的,哪些函数是按键按下后才执行的(或者哪些变量是按键按下才改变的)。
  • 功能函数执行数组里的每个量必须是确定的值,比如说,下面的写法就是错误的(emmm,我这么写的时候就报错啦):
u8 x;
{0,0,x,1,(*fun10)},
{1,4,x,5,(*fun1)},
  • 17
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReRrain

觉得写的不错,不妨请我喝杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值