【蓝桥杯嵌入式】蓝桥杯嵌入式第十二届省赛题,考点:模拟电压,串口通信,计时器

简介: 【蓝桥杯嵌入式】蓝桥杯嵌入式第十二届省赛题,考点:模拟电压,串口通信,计时器

目录


题目

硬件框图

功能描述

赛题分析

代码实现

LCD模块

中断(按键与计时)模块

按键模块

串口模块


正文


题目


硬件框图



功能描述


基本功能


       1)测量竞赛板上电位器R37输出的模拟电压信号Vwa;,并通过LCD 实现数据的

实时显示。


       2)通过按键完成显示界面切换、参数设置等功能。


       3)支持通过串口进行参数设置的功能。


       4)通过LED指示灯完成状态指示功能。


       5)设计要求

               电压数据刷新时间:≤0.5秒。

               按键响应时间:≤0.1秒。

               根据试题要求设计合理的电压数据采样频率,并对ADC采样到的电压数据进行有效的数字滤波。


显示功能


       1)数据界面

               通过液晶屏显示三个数据项,包括:界面名称Data、电位器R37输出的电压值V和计时结果T,电压值保留小数点后2位有效数字。

       2)参数界面

               通过液晶屏显示三个数据项,包括界面名称Para、电压参数Vmax和Vmin。电压参数保留小数点后1位有效数字。


      显示说明·

               显示背景色(BackColor):黑色。


               显示前景色(TextColor):白色。


               请严格按照图示要求设计各个信息项的名称(区分字母大小写)和行列位置。


               计时结果以秒为单位,计时条件下数据实时刷新。


       计时说明

               1)当电位器R37的输出电压上升到Vmin时,开始计时,声到电压上升到Vmax结束计时。


               2)满足开始计时条件,计时时间重置为0秒,并以秒单位开始计时。

       如上图所示的电压变化曲线中,从t1时刻开始以秒为单位计时,直到t2时刻触发停止计时条件,停止计时;t3时刻重新触发计时(计时时间重置为0),直到t4时刻停止计时。

4321.png

        如上图所示的电压变化曲线中,从t1时刻开始以秒为单位计时,t2时刻再次触发计时条件,重置计时时间为0,直至t3时刻结束计时。

按键功能


       1) B1:界面切换按键.切换选择数据界面或参数界面。


       2) B2:每次按下B2按键,Vmax参数加0.1V,当参数加到3.3V,再次按下B2后返回0.0V。


       3) B3:每次按下B3按键,Vm参数加0.1V,当参数加到3.3V,再次按下B3后返回0.0V。


       4) 当设备从参数界面退出,返回数据界面时,自动判断当前设置的参数是否合理,如参数合理则使之生效,如不合理,则弃用本次设置的参数,使用进入参数界面前的原参数。


       备注:

               B2和B3按键仅在参数设置界面有效。

               要求Vmax ≥ Vmin + 1V.

               要求Vmax、Vmin可设置范围为0.0V-3.3V。


串口通信功能


       1)使用 STM32 USART2完成串口功能。


       2)通信波特率:9600bps。


       3)串口参数设置命令:“Vmax,Vmin”

               例如:“3.2,1.4”,将电压参数Vmax和Vmin分别设置为3.2V和1.4V。


               备注:示例中的双引号为字符串标识,非参数设置命令内容。


       4)如通过串口接收到的指令存在格式或逻辑错误,设备不执行该条命令。


LED指示灯功能


       1)LD1,若当前触发了计时功能,且计时尚未结束,LD1点亮,否则LD1熄灭。


       2)LD2,若通过按键设置的参数不合理,LD2点亮,直至下次设置了正确的参数后熄灭。


       3)LD3,若串口接收到格式错误指令或不满足参数合理性判断的要求时LD3点亮,直至下次接收到正确指令后熄灭。


初始状态说明

       1)上电后,默认处于数据界面。


       2)上电默认参数:


               Vmax: 3.0V


               Vmin: 1.0v


赛题分析


       实现看硬件框图,了解考点,本次赛题的考点除了老三样(LED,按键,LCD)以外,主要的考点就是模拟电压输入与串口通信了。


       再往下看,就能看到功能描述,就能知道本题大概方向了。主要是测量R37的模拟电压信号,然后串口有一些接收的功能要求。


       我们接着往下面看,来到LCD模块,其主要就是把每行每列的字母数值的位置确定。有需要实时显示的就要实时刷新。


       再往下的计时,就是本次考题比较核心的内容了,什么时候开始计时,什么时候结束,这两个是很好判断的,但是什么条件时是需要将计时重置为0,这个就需要注意一下了,有两种情况:第一,计时正常结束后,重新开始新一轮的计时;第二,计时开始后,未到计时结束,又重新开始计时。计时是实用中断来实现。


       按键与平常也有一些区别,就是在参数界面将参数调好之后,并不会立刻改变真实的参数值,而是需要先进性参数合理性判断,符合要求的参数变动才会保存,否则还是沿用未进行调整时的参数。


       串口模块也是用于参数设置,同样的,也需要对参数的合理性进行判断,不合理则不采用,合理则改变参数为串口接收到的数值。


       LED模块就是一些指示功能,穿插在其他模块中得以体现。


代码实现


LCD模块


   LCD模块就是将各个参数完全按照赛题上的规格来显示即可。

void disp_proc()
{
  if(view==0)
  {
    char text[30];
    sprintf(text,"      Data   ");
    LCD_DisplayStringLine(Line0, (uint8_t *)text);
    sprintf(text," V:%.2fV",R37_v);
    LCD_DisplayStringLine(Line2, (uint8_t *)text);
    sprintf(text," T:%ds",times);
    LCD_DisplayStringLine(Line3, (uint8_t *)text);    
  }
  else if(view==1)
  {
    char text[30];
    sprintf(text,"      Para    ");
    LCD_DisplayStringLine(Line0, (uint8_t *)text);
    sprintf(text," Vmax:%.1fV     ",max_v);
    LCD_DisplayStringLine(Line2, (uint8_t *)text);
    sprintf(text," Vmin:%.1fV     ",min_v);
    LCD_DisplayStringLine(Line3, (uint8_t *)text);
  }
}


中断(按键与计时)模块


       中断中,包含了本次赛题多个重点:R37模拟电压信号的获取,计时器计时,计时器何时开始计时,何时结束计时,何时重置计时器。外加一些LED的操作。


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(a++ >20)
  {
    R37_v = getADC(&hadc2);
    if(R37_f < min_v && R37_v >= min_v)
    {
      times = 0;
      flag_t = 1;
      TurnOn_LED(1);
    }
    else if(flag_t == 1 && R37_v < min_v)
    {
      flag_t = 0;
      TurnOff_LED(1);
    }
    else if(flag_t == 1 && R37_v >= max_v)
    {
      flag_t = 2;
      TurnOff_LED(1);
    }
    a = 0;
    R37_f = getADC(&hadc2);
  }
  if(flag_t == 1)
  {
    if(s++ == 100)
    {
      times++;
      s = 0;
    }
  }
  else if(flag_t == 2)
  {
    flag_t = 0;
  }
  if(htim->Instance==TIM3)
  {
    key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
    key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
    key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
    key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
    for(int i = 0;i < 4; i++ )
    {
      switch (key[i].judge_sta)
      {
        case 0:
        {
          if(key[i].key_sta==0) 
          {
            key[i].judge_sta = 1; //第一次判断是否按下
            key[i].key_time = 0;
          }
        }
        break;
        case 1:
        {
          if(key[i].key_sta==0) //进入下一次定时器扫描,按键还是按下状态,那么就确认为按下,以此来消抖
          {
            key[i].judge_sta = 2;
          }
          else
            key[i].judge_sta = 0;
        }
        break;
        case 2:
        {       
          if(key[i].key_sta==1)     //判断是否松手
          {
            if(key[i].key_time < 100)
            {
              key[i].key_flag = 1;
            }
            key[i].judge_sta = 0;   
          }
          else
          {
            key[i].key_time++;
            if(key[i].key_time > 100)       //一次扫描10毫秒,100次1000毫秒,就是判断是否长按超过1000毫秒//未松手时,就会执行相应反应
            {
              key[i].long_flag = 1;
            }
          }
        }
        break;
      }
    }
  }
}


按键模块


       按键模块包括判断按键界面上调整参数是否合理的判断,判断后参数的改动。

void key_proc()
{
  if(key[0].key_flag == 1)
  {
    if(view == 1)
    {
      if(max_v < min_v + 0.99)
      {
        max_v = max;
        min_v = min;
        TurnOn_LED(2);
      }
      else
      {
        TurnOff_LED(2);
      }
    }
    else if(view == 0)
    {
      max = max_v;
      min = min_v;
    }
    view = !view;
    LCD_Clear(Black);
    key[0].key_flag = 0;
  }
  if(key[1].key_flag == 1)
  {
    if(view == 1)
    {
      max_v += 0.1;
      if(max_v > 3.3)
      {
        max_v = 0;
      }
    }
    key[1].key_flag = 0;
  }
  if(key[2].key_flag == 1)
  {
    if(view == 1)
    {
      min_v += 0.1;
      if(max_v > 3.3)
      {
        min_v = 0;
      }
    }
    key[2].key_flag = 0;
  }
}


串口模块


       串口模块只用实现接收功能,接收并判断参数是否合理,合理就对参数进行改变,不合理参数就不做改变。

void uart_rx_proc()
{
  if(rx_pointer>0)
  {
    if(rx_pointer==7) //如果接收到的是7个字符
    {
      sscanf(rxdata,"%c.%c,%c.%c",&max_g,&max_x,&min_g,&min_x); //将字符串拆分
      max_g1 = atoi(&max_g);
      max_x1 = atoi(&max_x);
      min_g1 = atoi(&min_g);
      min_x1 = atoi(&min_x);
      if(max_g1 + max_x1/10 >= min_g1 +min_x1/10 +1)
      {
        max_v = max_g1 + max_x1/10;
        min_v = min_g1 +min_x1/10;
        TurnOff_LED(3);
      }
      else
      {
        TurnOn_LED(3);
      }
    }
    rx_pointer=0;
    memset(rxdata,0,30);
  }
}
相关文章
|
7月前
|
C语言
蓝桥杯嵌入式零基础如何准备
蓝桥杯嵌入式零基础如何准备
|
7月前
|
缓存 网络协议 算法
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
|
7月前
蓝桥杯嵌入式第十一届(第一场)省赛
蓝桥杯嵌入式第十一届(第一场)省赛
189 1
|
7月前
蓝桥杯嵌入式第十二届省赛
蓝桥杯嵌入式第十二届省赛
115 0
|
7月前
蓝桥杯嵌入式第十一届(第二场)省赛
蓝桥杯嵌入式第十一届(第二场)省赛
128 0
|
7月前
|
芯片
蓝桥杯嵌入式创建第一个工程(点亮led灯)
蓝桥杯嵌入式创建第一个工程(点亮led灯)
104 0
|
7月前
|
算法 测试技术 编译器
蓝桥杯-02-蓝桥杯C/C++组考点与14届真题
蓝桥杯-02-蓝桥杯C/C++组考点与14届真题
|
7月前
|
算法 Java 测试技术
蓝桥杯-02-蓝桥杯Java组考点与14届真题
蓝桥杯-02-蓝桥杯Java组考点与14届真题
|
7月前
|
算法 测试技术 编译器
蓝桥杯-02-python组考点与14届真题
蓝桥杯-02-python组考点与14届真题