基于MSP430f5529IO扩展板上的按键和旋转编码器控制并实现菜单功能
本次寒假一起练平台,我选择的是基于MSP430备战电赛控制类题目的训练平台,并完成了项目1——通过IO扩展板上的按键和旋转编码器控制并实现菜单功能。
标签
嵌入式系统
MSP430
2023寒假在家练
Alkaid
更新2023-03-28
南昌大学
934
  1. 项目需求
  2. IO扩展板上的2个按键和旋转编码器的3个输入端口是通过R-2R电阻网络的方式连接在一起,生成一个模拟电压量。按下任何一个按键都会改变这个模拟电压量的值。
  3. IO扩展板上的LCD屏幕为128*128分辨率的1.44寸彩色屏幕,通过SPI总线进行访问
  4. 通过MSP430核心板的ADC监测IO板模拟输出管脚的变化,判断哪一个按键或编码器的旋转发生了变化,进而控制1.44寸LCD屏幕的菜单显示。
  5. 要求实现主菜单和至少二级菜单。
  6. 功能实现

2.1、LCD显示

MSP430的扩展板上搭载了1.44寸的SPI串口TFT彩屏st7735,控制LCD显示图片或者想要的文字。

lixcKWxubmcHeHsntdKffCOwdBShAAQpQIGMLMCjM2OPP3lOAAhSgAAUoQIFYgf8DMFME3uH6BxcAAAAASUVORK5CYII=

通过对LCD与MSP430的八个引脚进行控制,从而显示图片以及字符。

2.2、ADC采集

MSP430上的ADC模块支持12位模数转换,具有12位逐次逼近的时序控制电路和16个转换结果缓冲及控制寄存器。

mmmwNRqkm24AAAAASUVORK5CYII=

2.3、按键检测

扩展板上有两个独立按键和一个旋转编码器,通过ADC采集A_OUT(P6.0)的电压,检测它的变化,从而来判断哪个按键被按下以及编码器是否发生了旋转。

D6BwYS1htrdrAAAAAElFTkSuQmCC

2.4、二级菜单与光标

MSP430上电之后,显示主菜单,分别有三个选项,进入任何一个选项就进入了二级菜单,光标的上下移动通过旋转编码器来控制。

Z

  1. 实现思路
  • LCD和ADC进行初始化,LCD显示图片和字符,ADC对模拟量进行采集,在ADC中断获取数字量。
  • 对获取的ADC进行判断,从而确定哪个按键按下以及编码器的旋转。
  • 两个按键分别对应进入和退出,旋转编码器控制光标的移动。
  • 按下旋转编码器具有保存的功能,能够保存数字的大小。
  • 二级菜单的三个界面分别对应着不同的功能。

4.实现过程

4.1、思路流程图

 

HzPn0ip+vDp7AAAAAElFTkSuQmCC

4.2、ADC检测

测量引脚开启复用输入,将P6.0复用输入,配置ADC模块,ADC模块时钟源选为MODCLK时钟,不分频。内部模块振荡器(MODOSC)能够产生以约4.8Mhz的MODCLK时钟。Flash控制器模块、ADC_12模块等片内外设都可使用MODCLK作为内部参考时钟

a.ADC初始化

//Initialize the ADC12_A Module

/*

* Base address of ADC12_A Module

* Use internal ADC12_A bit as sample/hold signal to start conversion

* USE MODOSC 5MHZ Digital Oscillator as clock source

* Use default clock divider of 1

*/

ADC12_A_init(ADC12_A_BASE,

ADC12_A_SAMPLEHOLDSOURCE_SC,

ADC12_A_CLOCKSOURCE_ADC12OSC,

ADC12_A_CLOCKDIVIDER_1);




ADC12_A_enable(ADC12_A_BASE);

b.配置采样定时器

/*

* Base address of ADC12_A Module

* For memory buffers 0-7 sample/hold for 64 clock cycles

* For memory buffers 8-15 sample/hold for 4 clock cycles (default)

* Disable Multiple Sampling

*/

ADC12_A_setupSamplingTimer(ADC12_A_BASE,

ADC12_A_CYCLEHOLD_64_CYCLES,

ADC12_A_CYCLEHOLD_4_CYCLES,

ADC12_A_MULTIPLESAMPLESDISABLE);

配置采样结果缓冲寄存器,选择输入信号为A0,正参考电压源选为+3.3V,负参考电压源选为0V。

//Configure Memory Buffer

/*

* Base address of the ADC12_A Module

* Configure memory buffer 0

* Map input A5 to memory buffer 0

* Vref+ = AVcc(+3.3V)

* Vr- = AVss(0V)

* Memory buffer 0 is not the end of a sequence

*/

ADC12_A_configureMemoryParam param = {0};

param.memoryBufferControlIndex = ADC12_A_MEMORY_0;

param.inputSourceSelect = ADC12_A_INPUT_A0;

param.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;

param.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;

param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;

ADC12_A_configureMemory(ADC12_A_BASE ,&param);

c.配置ADC中断

因为使用的是ADC12_A_MEMORY_0,故使能为Enable memory buffer 0 interrupt

//Enable memory buffer 0 interrupt

ADC12_A_clearInterrupt(ADC12_A_BASE,

ADC12IFG0);

ADC12_A_enableInterrupt(ADC12_A_BASE,

ADC12IE0);

d.启动ADC转换

while(1)

{

//Enable/Start sampling and conversion

/*

* Base address of ADC12_A Module

* Start the conversion into memory buffer 0

* Use the single-channel, single-conversion mode

*/

ADC12_A_startConversion(ADC12_A_BASE, ADC12_A_MEMORY_0, ADC12_A_SINGLECHANNEL);

//LPM0, ADC12_A_ISR will force exit

__bis_SR_register(LPM0_bits + GIE);

//for Debugger

__no_operation();

}

4.3、按键检测

a.界面选择

设置flag_page_1为界面标志位,当标志位分别为1、11、12、13时,分别对应主界面、二级界面一、二级界面二、二级界面三。

switch(flag_page_1) //选择界面

{

case 1:

LCD_Page_1();

break;

case 11:

LCD_Page_11();

break;

case 12:

LCD_Page_12();

break;

case 13 :

LCD_Page_13();

break;

default: break;

}

b、按键检测

通过判断P6.0引脚的ADC模拟量变化来确定是哪个按键被按下。

void key_scan(void)

{

if(keyvalue)

keyvalue=0;

if ( Measured>3500&& Measured<3700)

{

if((float)Measured/0xfff*3.3>2.85&&(float)Measured/0xfff*3.3<3.1)

keyvalue = 1;

}

else if ( Measured>2900&& Measured<3000)

{

keyvalue = 2;

LCD_Fill(0,0,LCD_W,LCD_H,WHITE);

}

else if ( Measured>1900&& Measured<2000)

{

keyvalue = 3;

LCD_Fill(0,0,LCD_W,LCD_H,WHITE);

}

else if( Measured>3400&& Measured<3500)

{

keyvalue = 4;

LCD_Fill(0,0,LCD_W,LCD_H,WHITE);

}

}

c.按键服务函数

不同的按键有不同的功能,当对应的按键被按下,就会进入到按键相应的功能区域。

void key_service(void)

{

switch(keyvalue)

{

case 0:

break;

case 1:

{

flag_page_1_++;

if(flag_page_1_==4)

flag_page_1_=1;

}

break;

case 2:

{

switch(flag_page_1_)

{

case 1:

flag_page_1=11;

break;

case 2:

flag_page_1=12;

break;

case 3:

flag_page_1=13;

break;

}

break;

}

case 3:

flag_page_1=1;

break;

case 4:

if(flag_page_1==11)

p=num;

break;

default: break;

}

}

d.光标移动

设置光标标志位,当检测到编码器旋转后,标志位加一,以三为一个循环。

switch(flag_page_1_)

{

case 1:

LCD_ShowString(0,24," ->",BLUE, WHITE,16,0);

break;

case 2:

LCD_ShowString(0,48," ->",BLUE, WHITE,16,0);

break;

case 3:

LCD_ShowString(0,72," ->",BLUE, WHITE,16,0);

break;

}

5.遇到的主要问题

5.1、ADC滤波

在使用ADC时,不断地对P6.0引脚的电压进行采集,但是在采集的过程中,由于采用的是单通道的ADDC进行采集,得到的数据并不稳定,精度也并不高。因此在对编码器进行旋转判断时不是很准确,也就是检测并没有很灵敏。虽然能判断独立按键按下,但对旋转编码器的带电压变化捕捉不够理想。并且当编码器旋转到正好将两个小按键按下时,光标会不断上下移动,当编码器离开那个位置后,又恢复正常。

若对ADC检测到的信号进行滤波,首先能滤除杂波,使得信号更加平稳,所得到的误差也会减小。

5.2、LCD刷新

每进入一个新界面就刷新一次会造成界面重复刷新,因此,将LCD清屏函数放在按键扫描之后,每次检测到按键被按下之后,就将LCD清屏一次,这样就解决了重复刷新清屏问题。

6、未来规划与收获

本次项目成功基本实现了简易的二级菜单功能,但还是有很多的不足和可以改进的地方:

  • ADC的检测还可以进一步升级和完善,使之检测更加灵敏。
  • 还可以设置3级或者更多级的菜单,不同的菜单功能也可以更加多样化。
  • 旋转编码器能够判断出顺、逆时针方向的旋转。
  • 设置图案化的菜单界面,按键具有双击、长短按的功能。

经过这次寒假一起练平台,学到了很多东西:

  • 了解并初步学习了MSP430单片机的一些相关内容,对单片机的认识有了进一步的了解。
  • 尝试用ADC来检测按键按下和编码器的旋转,与以往对按键的检测通过I/O口不同。
  • 使用MSP430驱动LCD屏来显示图片和字符。
  • 和志同道合的小伙伴一起相互学习,解决问题。
附件下载
学习代码.zip
学习MSP430过程中写的一些代码
ADC.zip
项目源代码
团队介绍
南昌大学
团队成员
曾祥杰
南昌大学21级本科生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号