用msp430和按键实现菜单功能
旋转编码器和两个按键串联在一个r-2r电阻网络中,使用adc检测输入电压,判断三者的状态,使用两个按键作为上下选择选项的按钮,使用旋转编码器按下作为确认键,实现二级菜单,并实现了一些基础的功能,比如字体大小的变换,简单的图片。
标签
嵌入式系统
2023寒假在家练
菜单
jupiter
更新2023-03-28
西安电子科技大学
390

项目的实现和关键(末尾有项目文件)

项目需求:

使用msp430,lunchpad和io拓展版上的1.44寸屏幕和一个旋转编码器以及两个按键实现一个简单的二级菜单。旋转编码器和按键作为上翻、下翻和确定键。

程序流程图:

FoctKmQXx2Uf-N3MwZfosRlfObS2

完成的功能:

1.按键检测

本次项目的重点在于检测2个按键和1个旋转编码器的状态,通过读取adc值,判断按键是否被按下,以及旋转编码器的旋转和按下。我们将第一个按键作为上翻键,第二个按键作为下翻键,旋转编码器按下作为确定键,旋转编码器的旋转作为一些操作键,比如调节字体的颜色和大小中使用。

Frsms1LEhZ7zQ_2GMaUGxIWbVvHY

经过实验:

  • 没有按键按下时,电压值在3.13V
  • 当按键1按下时,电压值在2.35V
  • 当按键2按下时,电压值在1.54V
  • 旋转编码器按下,电压在2.75V
  • 旋转编码器顺时针旋转,电压在3.06V
  • 旋转编码器逆时针旋转,电压在2.95V

在代码中,先读取adc,再判断adc值符不符合上述的电压值,由于adc有一定的偏差,在判断时需要加上一定的误差范围。

float fabs(float m)
{
    if(m>=0) return m;
    else return -m;
}
uint8_t key_scan(KEY_FIFO* fifo)
{
    float volat = Read_AD()*3.3/4096;
    if(fabs(volat-2.35)<=0.05) //按键1按下
    {
        key_fifo_push(fifo,KEY1DOWN);
        return KEY1DOWN;
    }
    else if(fabs(volat-1.54)<=0.05) //按键2按下
    {
        key_fifo_push(fifo,KEY2DOWN);
        return KEY2DOWN;
    }
    else if(fabs(volat-2.75)<=0.05) //旋转编码器按下
    {   
        key_fifo_push(fifo,ENCODERDWON);
        return ENCODERDWON;
    }
    else if(fabs(volat-3.06)<=0.02) 
    {
        key_fifo_push(fifo,ENCODERROTATING);//旋转编码器顺时针旋转
        return ENCODERROTATING;
    }
    else if(fabs(volat-2.95)<=0.02) 
    {   
        key_fifo_push(fifo,ENCODERREVERSE);//旋转编码器逆时针旋转
        return ENCODERREVERSE;
    }
    else return 0;
}

在这里,同时使用了一个循环队列,但是效果并不是很好。

2.菜单实现

菜单的实现使用了数组查表法,主要是将每个菜单进行编号,使用结构体关联上下和确认后的菜单,并将菜单放入菜单数组中,将菜单编号和数组下标对应,如此就能实现菜单的选择,上翻和下翻。

 

typedef struct menu{
    uint8_t current;
    uint8_t down;
    uint8_t up;
    uint8_t next;
    void (*operation)();
}menu_t;

比如当我们当前的下标为1,执行fun1,显示主菜单指针指向了Image,当我们按下下时,下标跳转为2,执行fun2对应函数。Fj1Fn5BCHitz1OYpJOx7SZ0TGXzZ

Fjocm1FOf79TKrq4pL3cyH_noNGw

每个菜单结构体中,还有一个执行函数,用于执行对应菜单的功能。

menu_t menu_list[22] = 
{
    //第0层
    {0,1,1,1,(*fun0)},
    
    //第1层
    {1,2,4,5,(*fun1)},//image
    {2,3,1,8,(*fun2)},//font_size
    {3,4,2,11,(*fun3)},//game
    {4,1,3,0,(*fun4)},//back

    //第2层
    //图片
    {5,6,7,14,(*fun5)},//1
    {6,7,5,15,(*fun6)},//2
    {7,5,6,1,(*fun7)},//back

    //字体
    {8,9,10,16,(*fun8)},//size
    {9,10,8,17,(*fun9)},//color
    {10,8,9,2,(*fun10)},//back

    //游戏
    {11,12,13,20,(*fun11)},//snake
    {12,13,11,21,(*fun12)},//box
    {13,11,12,3,(*fun13)},//back

    //last
    {14,14,14,5,(*fun14)},//image1
    {15,15,15,6,(*fun15)},//image2

    {16,16,16,8,(*fun16)},//size
    {17,18,19,9,(*fun17)},//color_r
    {18,19,17,9,(*fun18)},//color_g
    {19,17,18,9,(*fun19)},//color_b
    
    {20,20,20,11,(*fun20)},//snake
    {21,21,21,12,(*fun21)}//box
};

在主函数中,首先检测按键状态,如果有按键按下,就改变当前的菜单下标。

void main()
{
    WDT_A_hold(WDT_A_BASE);
    GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN4);
    GPIO_setOutputLowOnPin(GPIO_PORT_P1,GPIO_PIN4);
    SystemClock_Init();
    spi_init();
    Lcd_Init();
    Lcd_Clear(BLACK);
	ADC_Init();
    __bis_SR_register(GIE);
    void (*operation)()=menu_list[menu_index].operation;
    KEY_FIFO*   KEY_BUF = NULL;
    KEY_BUF = key_fifo_init(fifosize);
    fifodatatype key_down = 0;
    operation();
	while(1)
    {
        key_scan(KEY_BUF);
        key_down = key_fifo_pop(KEY_BUF);
        while(key_down==KEY_BUF->data[KEY_BUF->tail]&&(key_down==ENCODERROTATING||key_down==ENCODERREVERSE))
        {
            key_down = key_fifo_pop(KEY_BUF);
        }
        if(key_down)
        {
            switch (key_down)
            {
            case KEY1DOWN:
                menu_index = menu_list[menu_index].up;
                if(operation == menu_list[21].operation)    dinosaur_jump_flag = 1;
                break;
            case KEY2DOWN:
                menu_index = menu_list[menu_index].down;
                break;
            case ENCODERDWON:
                menu_index = menu_list[menu_index].next;
                turn_flag = 0;
                break;
            case ENCODERROTATING:
                incerment_flag = 1;
                break;
            case ENCODERREVERSE:
                decerment_flag = 1;
                break;
            default:
                break;
            }
            if(turn_flag == 0)
            {
                Lcd_Clear(BLACK);
                turn_flag = 1;
            }
            operation = menu_list[menu_index].operation;
            (*operation)();
        }
        if(operation == menu_list[21].operation)(*operation)();
        else delay_ms(100);
    }
}
  • 菜单结构

FvIET-YiWYamStTsIa0JAuVGmFH-

3.主要功能展示:

(1).图片显示,将图片数据存储在了栈区,能存储的数据比较有限。

FlZX35fZOnmCdXoyddYf3wckXQIj

2.字体大小和颜色调整

使用旋转编码器的旋转可以调整字体的大小,颜色。

FqkfcmKmGoXZze00swAHdXyOAE7C

FgmPgHmIovPfE_1ocMyee0wxSFsW

3.谷歌小恐龙

按上键可以实现跳跃,但是当前没有加入游戏分数,结束判断等。

FjFWriAZlFpJdXh6uENQ1aOUkKcN

4.问题

这个项目的问题主要在于旋转编码器旋转的检测上,当金属触点卡在了中间是,会不断检测到旋转编码器的旋转,在旋转时,由于会有两次触点接触,会先后先后检测到两次不同方向的旋转,为了解决这个问题,应该要判断两次adc值,结合两次的adc值来判断旋转编码器的旋转状态。

当前的菜单不支持增加菜单选项。

 

  • 附件连接链接:

https://pan.baidu.com/s/1DYqOYtpBAvTm0-sx-8mxfA?pwd=6666 

提取码:6666

 

 

 

 

 

 

 

 

 

团队介绍
我是西安电子科技大学的大一学生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号