寒假在家一起练- 通过IO扩展板上的按键和旋转编码器控制并实现菜单功能
通过MSP430核心板的ADC监测IO板模拟输出管脚的变化,判断哪一个按键或编码器的旋转发生了变化,进而控制1.44寸LCD屏幕的菜单显示,实现二级菜单。
标签
嵌入式系统
ADC
2023寒假在家练
zyt6
更新2023-03-27
南昌大学
846

一、项目需求

  • IO扩展板上的2个按键和旋转编码器的3个输入端口是通过R-2R电阻网络的方式连接在一起,生成一个模拟电压量。按下任何一个按键都会改变这个模拟电压量的值。
  • IO扩展板上的LCD屏幕为128*128分辨率的1.44寸彩色屏幕,通过SPI总线进行访问。

要求:本任务需要通过MSP430核心板的ADC监测IO板模拟输出管脚的变化,判断哪一个按键或编码器的旋转发生了变化,进而控制1.44寸LCD屏幕的菜单显示,要求实现主菜单和至少二级菜单。

二、完成的功能及达到的性能

1.项目介绍

上电后,出现”屏保“,按下确定键进入主菜单。

9k=

主菜单如图所示,主题为“我的实验室”,通过旋转编码器中的旋钮选择进入该主题的三个部分。

iaBFXQAAAABJRU5ErkJggg==

第一部分为团队,团队数量范围为0~5;可通过旋转编码器调整数值大小,按压旋转编码器为保存。

2Q==

第二部分为新成员,数量范围为0~10;可通过旋转编码器调整数值大小,按压旋转编码器为保存。

9k=

第三部分为所获荣誉,数量范围为0~10。可通过旋转编码器调整数值大小,按压旋转编码器为保存。

2Q==

2.操作功能

第一界面:可通过确定键进入第二界面。

第二界面:可通过退出键来到第一界面。用“->”代表选择的菜单,通过旋钮控制其在哪个菜单停留,确定键进入对应的界面。

第三界面:可通过退出键来到第二界面。通过旋转编码器调整数值大小,按压旋转编码器中央键可保存数值,未保存的数值再次进入时会丢失。

三、设计思路

  • ADC对模拟输入进行采样,由定时器采样,软件触发;
  • 将采样得到的ADC量化值显示在LCD上;
  • 按下按键观察量化值,通过试验得出三个按键及旋钮的电压变化规律;
  • 通过观察得到的规律,确定范围,实现各按键及旋钮的功能

四、实现思路

1.流程图

cvo5vt1t3VtbV1wZl0DMR2E+AO3W5zQ4rGie4c3Qvh+bpvBC9GiIgAiLgS0BCxBeLIkVABERABERABDJBQLtmMkFZdYiACIiACIiACPgSkBDxxaJIERABERABERCBTBCQEMkEZdUhAiIgAiIgAiLgS0BCxBeLIkVABERABERABDJBQEIkE5RVhwiIgAiIgAiIgC8BCRFfLIoUAREQAREQARHIBAEJkUxQVh0iIAIiIAIiIAK+BCREfLEoUgREQAREQAREIBMEJEQyQVl1iIAIiIAIiIAI+BKQEPHFokgREAEREAEREIFMEJAQyQRl1SECIiACIiACIuBLQELEF4siRUAEREAEREAEMkFAQiQTlFWHCIiACIiACIiALwEJEV8sihQBERABERABEcgEAQmRTFBWHSIgAiIgAiIgAr4EJER8sShSBERABERABEQgEwQkRDJBWXWIgAiIgAiIgAj4EpAQ8cWiSBEQAREQAREQgUwQkBDJBGXVIQIiIAIiIAIi4EtAQsQXiyJFQAREQAREQAQyQUBCJBOUVYcIiIAIiIAIiIAvAQkRXyyKFAEREAEREAERyAQBCZFMUFYdIiACIiACIiACvgQkRHyxKFIEREAEREAERCATBCREMkFZdYiACIiACIiACPgSkBDxxaJIERABERABERCBTBCQEMkEZdUhAiIgAiIgAiLgS0BCxBeLIkVABERABERABDJBQEIkE5RVhwiIgAiIgAiIgC8BCRFfLIoUAREQAREQARHIBAEJkUxQVh0iIAIiIAIiIAK+BCREfLEoUgREQAREQAREIBMEJEQyQVl1iIAIiIAIiIAI+BKQEPHFokgREAEREAEREIFMEJAQyQRl1SECIiACIiACIuBLQELEF4siRUAEREAEREAEMkFAQiQTlFWHCIiACIiACIiALwEJEV8sihQBERABERABEcgEgf8fJXCkCRTA3FIAAAAASUVORK5CYII=

2.硬件介绍

如图所示,IO扩展板上的2个按键和旋转编码器的3个输入端口是通过R-2R电阻网络的方式连接在一起的,可以生成一个模拟电压量。按下任何一个按键都会改变这个模拟电压量的值,通过模拟电压量的变化使用其功能。

通过仿真及电路计算可知,当K2按下时,模拟电压量会变化1/2;K1按下时会变化1/4;旋钮上方按键按下时会改变1/8;旋钮BC处按压时会改变1/16;旋钮AC处按压时会改变1/32。从而判断按键状态。

w+zr9rxc0ed+AAAAABJRU5ErkJggg==

IO扩展板上的LCD屏幕为128*128分辨率的1.44寸彩色屏幕,可以通过SPI总线进行访问。

xrRns2baysoeYZxbrfdOnKilrMwEe6ajo3tYWEFxMZMJOjErS0lOblynTiw+SRIE6gYBzoyRfCgEmunpYZiNTkpCsrGCAhMWNUXF3x0cFl24QDEx5D5NSHiWmOgTHW2iqUlNvJnyhCYI1A0C5BipAmdHa+u8oqKI+HhMnns3a9bDygp5HUxMVBQVFeXk2hoZ6amq2ujr4xgJ36sREdkFBQNatlw+eHBFFYQiCNQtAsQSq27xJq0RBESKAFkDixROUhlBoG4RIApct3iT1ggCIkWAKLBI4SSVEQTqFgGiwHWLN2mNICBSBIgCixROUhlBoG4RIApct3iT1ggCIkWAKLBI4SSVEQTqFgGiwHWLN2mNICBSBIgCixROUhlBoG4R+D9wlBEgKRBNuQAAAABJRU5ErkJggg==

五、实现过程

1.修改主频为25Mhz

430 默认情况下XT2是关闭的,系统的核心电压是一个比较低的值,在设置高频率,并且使用外部高速时钟之前我们需要打开时钟,并且在这之前我们需要把系统的核心电压升到最高。

430为了省电默认状态下核心电压默认设置为1.8V来节省功耗。 在用户手册的2.2.4节提到了升核心电压的方法.第一步是解锁  向PMMCTL0 寄存器高8位写入 0xA5 然后设置核心电压等级是三级(官方手册有提到频率和核心电压的关系)

然后令 SR寄存器里面的 SCG0=1,关闭锁相环,同时 关闭了这个时钟以后系统时钟应该会自动切换到备用时钟。再i选择 XTAL2 的时钟信号作为参考信号 并且分频到1MHz,逐步配置。

clock_init(25);//25Mhz
void clock_init(unsigned char Fre)//修改主频程序
{
    P5SEL |= BIT2|BIT3|BIT4|BIT5;//开启外部两个时钟

    UCSCTL6 |= XCAP_3|XT1OFF;          // XT1 相关 配置
    UCSCTL6 |= XT2DRIVE_0 |XT2OFF;     // XT2 相关 配置
//以下是提升核心电压部分的代码
    PMMCTL0_H = 0xA5;                                         //开PMM电源管理
    SVSMLCTL |= SVSMLRRL_1 + SVMLE;                            //配置SVML电压
    PMMCTL0 =  PMMPW + PMMCOREV_3;                             //配置内核电压
    while((PMMIFG & SVSMLDLYIFG ) == 0);                       //等待设置完成
    PMMIFG &= ~(SVMLVLRIFG + SVMLIFG + SVSMLDLYIFG);
    if((PMMIFG & SVMLIFG) == 1)                                //判断内核电压是否上升到VSVML
         while((PMMIFG & SVMLVLRIFG) == 0);                    //如果没有等待
    SVSMLCTL &= ~SVMLE;                                        //关掉SVML模块
    PMMCTL0_H = 0X00;

    __bis_SR_register(SCG0);                 //该语法为固定格式,意为将括号内的变量置位,SCG0与系统工作模式有关,此时 MCLK 暂停工作
    UCSCTL0 = 0;                             //先清零,FLL 运行时,该寄存器系统会自动配置,不用管
    UCSCTL6 = (UCSCTL6&(~(XT2OFF|XT1OFF))|XCAP_3|XT2DRIVE_0);
    UCSCTL3 = (5<<4)|(2<<0);                 // 选择 XTAL2 的时钟信号作为参考信号 并且分频到1MHz
    UCSCTL4|= SELA_5;
    if(Fre < 5)
        UCSCTL1 = DCORSEL_2;
    else if(Fre<15)
        UCSCTL1 = DCORSEL_4;
    else
        UCSCTL1 = DCORSEL_7;
   UCSCTL2 = (Fre-1);
    __bic_SR_register(SCG0);
    __delay_cycles(782000);
    while (SFRIFG1 & OFIFG) {                               // Check OFIFG fault flag
      UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);           // Clear OSC flaut Flags
      SFRIFG1 &= ~OFIFG;                                    // Clear OFIFG fault flag
    }
    UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_3|SELM_3;
}

2.准备事项

开启LCD,关闭加热,看原理图可知,给低电平可关闭。

LCD_Init();
LCD_Fill(0,0,LCD_W,LCD_H,WHITE);//指定区域填充颜色,清屏 防止出现重叠
GPIO_setAsOutputPin(GPIO_PORT_P1,GPIO_PIN4);
GPIO_setOutputLowOnPin(GPIO_PORT_P1,GPIO_PIN4);

3.ADC采集程序

ADC12模块中是由以下部分组成:输入的16路模拟开关,ADC内部电压参考源,ADC12内核,ADC时钟源部分,采集与保持/触发源部分,ADC数据输出部分,ADC控制寄存器等组成。

ADC 输入范围由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。我们在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到 ADC 的输入电压范围为:0~3.3V。

void setupADC(void)
{

    #define ADCpin         GPIO_PORT_P6,GPIO_PIN0

    GPIO_setAsPeripheralModuleFunctionOutputPin(ADCpin);     // 复位P6.0

    ADC12_A_init(ADC12_A_BASE,ADC12_A_SAMPLEHOLDSOURCE_SC, ADC12_A_CLOCKSOURCE_ADC12OSC, ADC12_A_CLOCKDIVIDER_1);  //软件触发, 一分频,内部振荡器MODCLK 5MHZ数字振荡器作为时钟源

    ADC12_A_enable(ADC12_A_BASE);   //启用ADC12_A模块
    //设置并启用采样定时器脉冲,这里是使用的软件触发的形式,所以选择失能
    ADC12_A_setupSamplingTimer(ADC12_A_BASE,ADC12_A_CYCLEHOLD_16_CYCLES,ADC12_A_CYCLEHOLD_16_CYCLES,ADC12_A_MULTIPLESAMPLESDISABLE);

    ADC12_A_configureMemoryParam param = {0};
    param.memoryBufferControlIndex = ADC12_A_MEMORY_0;           //将内存缓冲配置为MEMORY_0
    param.inputSourceSelect = ADC12_A_INPUT_A0;                  //将输入A0映射到内存缓冲区0,因为P6.0引脚对应A0
    param.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC; //正电压为AVcc
    param.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS; //负电压为AVss
    param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;              //单通道转换

    ADC12_A_configureMemory(ADC12_A_BASE,&param);   //
}

由ADC转换的电压变化太小,不能准确体现按键变化,因而在此不做换算。

unsigned long readADC(void){

    //开始从MEMORY_0中进行单通道连续转换
    ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_0,ADC12_A_SINGLECHANNEL);

    while(ADC12_A_isBusy(ADC12_A_BASE) == ADC12_A_BUSY){
        // 等待转换完成
    }
    //读取ADC转换之后寄存器的值
    long result = ADC12_A_getResults(ADC12_A_BASE, ADC12_A_MEMORY_0);
    return  result;//直接返回
}

由于采集速率过快导致获得的数据不稳定,在此进行简单的处理,直接用延迟1毫秒取5次得平均值。

    a1=readADC();
    delay_ms(1);
    a2=readADC();
    delay_ms(1);
    a3=readADC();
    delay_ms(1);
    a4=readADC();
    delay_ms(1);
    a5=readADC();
    delay_ms(1);
    a=(a1+a2+a3+a4+a5)/5;

4.逻辑设计

代码中的范围是通过多次试验得出,界定好范围,进行按键旋钮功能分配。

    if( (a<3500)&&(a>3400) )            //换菜单,调大小
    {
      if( view==1 )
      {
          Flag_Page_1++;
          if( Flag_Page_1==4 )
          {
              Flag_Page_1=1;
          }
      }
      else if( view==2 )
      {
          switch(Flag_Page_1)
          {
              case 1:
                  X0++;
                  if( X0==6 )   X0=0;
                  break;
              case 2:
                  Y0++;
                  if( Y0==11 )   Y0=0;
                  break;
              case 3:
                  T0++;
                  if( T0==11 ) T0=1;
                  break;
          }
      }
    }
    else if( (a<2900)&&(a>2700) )        //进入
    {
        if( view==0 )
        {
            view=1;
        }
        else if( view==1 ) view=2;
        Flag_Sure=1;
        X0=X;Y0=Y;T0=T;
        LCD_Fill(0,0,LCD_W,LCD_H,WHITE);//指定区域填充颜色,清屏 防止出现重叠
    }
    else if( (a<2100)&&(a>1800) )        //退出
    {
        Flag_Sure=0;
        if( view==2 )
        {
            view=1;
        }
        else if( view==1 ) view=0;
    }
    if( view==2 )
    {
        if( (a<3300)&&(a>3100) )       //保存
        {
           Flag_Save=1;
        }
    }

在每个界面中都逐一进行配置,在此不一一列举。

if( view==0 )                     //图片

else if( view==1 )               //主页面

else if( view==2 )       //调节数值

六、过程感受

1.主程序频率的设置

刚开始设置发现程序执行的太慢,还以为是程序代码写的不好,上网查了才发现是430的本身配置频率太慢了,在网上下载、学习了各种资料才学会配置修改,进而改了主频。

2.旋钮的模拟变化量

旋钮只有在转动卡在凸起时,电压才会变化,因此转动过程中电压变化规律并不是很清晰。而且该电路并不是太稳定,仅仅是摇晃就会改变电压模拟量,感觉这部分还有待改进。然后我使用了一点点休整,使ADC采样5次取平均,减小误差。

附件下载
work.zip
所有代码
MSP-EXP430F5529LP数据手册.pdf
核心板数据手册
IOBV3-MSP430.pdf
扩展板
团队介绍
南昌大学
团队成员
郑宇婷
南昌大学,测控技术与仪器,郑宇婷
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号