基于c8t6的平衡小车(CubeMX+MDK)(1)OLED的多级菜单显示

OLED的多级菜单显示

OLED控制之旋转编码器兼按键

按键

  1. 按键状态
    想想按键有哪些状态呢,按下,断开?,这是最基本的KEYSTATUS,按键还可以有短按,长按,一直按,按多次,这都可以产生不同的按键标志
  2. 扫描按键
    在while循环中不断读取GPIO的数据占用了cpu,那有没有好的办法可以即使读取按键状态又不影响主程序的运行呢?
    有的兄弟,有的,请看按键扫描:
    使用定时器内部计时,触发中断,在中断回调函数中扫描按键状态,通过按键扫描函数区分各种按键状态;
    在主程序中调用handle设置标志位。根据不同标志位,执行不同逻辑,控制不同外设。(如何配置?)
  • 我用短按做确定,进入下一级菜单
  • 我用长按做退出,返回上一级菜单

按键扫描速度非常快,并且扫描时候一次按压可能被扫描很多次,那么如何在有效操作时间内按压记录次数呢(坑+1)

旋转编码器

  1. 旋转编码器的状态
    一样的思路,旋转编码器有哪些状态呢?静止,顺时针转,逆时针转,按下按键(有的编码器是没有的,这取决于外部电路)。这些状态如何获取呢

速食者跳过
曲折
一开始我的想法是判断__HAL_TIM_IS_TIM_COUNTING_DOWN(&htimx)的返回值来获取其旋转状态,但是经过尝试后发现:
这个函数的返回值取决于上次的变化,也就是说上次是顺时针转,哪怕转完静止,调用该函数的返回值依旧是1,令我十分纳闷。

  • 硬件上
    用示波器测AC相的电压,其静止状态下为VCC的电压值,旋转编码器,其信号变为方波,方波的频率随着旋转速度变化而变化。这证明信号是表征其静止状态的。
  • 软件上
    我看了__HAL_TIM_IS_TIM_COUNTING_DOWN(&htimx)的函数定义和查阅其他佬的文章后知道了这个函数的原理:该函数通过访问TIM的控制寄存器1的DIR位来判断计数器的计数方向,也就是说计数方向向下(DIR=1),函数返回1,计数向上(DIR=0),函数返回0;
    因此其无法直接判断旋转编码器状态
    在编码器接口模式下,定时器硬件会根据编码器两个通道(A相和B相)的相位关系自动设置DIR位:

  1. 获取编码器状态
    设置变量last和current用__HAL_TIM_SET_COUNTER(&htimx, 0)获取,比较current和last的大小获取按键状态
    接下来就很简单了,用TIM1配置为encode Mode,设置为TI1单独检测,TI1触发后读取TI2的电平值,判断左右旋转,设置不同标志位控制OLED(如何使用?)
  • 逆时针旋转,切换同级下一项
  • 顺时针旋转,切换同级上一项

OLED的多级菜单

上一级菜单和下一级菜单之间是什么关系呢,我的思考方式是把菜单对象当作树中的节点,创建多叉树,菜单的遍历即为树的遍历
好了,那如何实现呢?
树结构的菜单实现???????????(挖个坑,待我再学一学)
这个项目的多级菜单我只是用MenuIndex这个变量去控制菜单的显示,尽管不便于移植,但是逻辑简单。后续按键标志位的控制均是在控制MenuIndex这个变量实现切换菜单。

CUBEMX配置

编码器

  • 通用定时器(TIM2,TIM3,TIM4)和高级定时器(TIM1)均可以设置为Encoder Mode,
  • Encoder Mode模式下,GPIO有编码模式自定义,无需额外设置。
  • 编码器函数
    HAL_TIM_Encoder_Start(&htimx, TIM_CHANNEL_ALL);开启encoder接口
    __HAL_TIM_GET_COUNTER(&htimx)的返回值得到编码器的脉冲数count
    __HAL_TIM_IS_TIM_COUNTING_DOWN(&htimx)的返回值得到编码器的旋转方向direction,1为逆时针,0为顺时针
    __HAL_TIM_SET_COUNTER(&htimx, 0)将计数器归0

TIM1时钟设置和RCC会产生冲突报错,暂未找到冲突原因,但用旋转编码器测试TIM1的Encoder Mode无误(坑+1)

TIM内部计时

  • 使能TIM时钟为内部时钟,使能NVIC管理中断,创建自定义回调函数HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)HAL_TIM_IRQHandler()调用
    记得检查触发中断的定时器
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim == &htimx){}
}
posted @ 2025-07-16 21:39  loong2525  阅读(105)  评论(0)    收藏  举报