精华内容
下载资源
问答
  • 本压缩包包含第十届嵌入式蓝桥杯试卷及答案,程序为本人参考资料所写,基本上是原创;不喜勿喷;仅供参考。
  • 内含题目以及本人的解题程序,内容较好理解,如有疑问可以联系我,本资源适用于蓝桥杯嵌入式备考的人,也适用于初学stm32的人
  • 本压缩包包含第十届嵌入式蓝桥杯决赛试卷及答案,程序为本人参考资料所写,基本上是原创;不喜勿喷;仅供参考。
  • 蓝桥杯嵌入式第十届省赛-客观题之答案解析,详情可参考我的博客https://blog.csdn.net/demon_xi/article/details/109254787
  • 第十届决赛题目考察的知识点较多,题目较为综合,主要考察两路adc,pwm输入捕获,ds18b20,数码管等。两路ADC,本程序采用注入通道。 工程结构 init.c #include stm32f10x.h #include lcd.h #include init.h #...
  • 内含题目以及本人的解题程序,内容较好理解,如有疑问可以联系我,本资源适用于蓝桥杯嵌入式备考的人,也适用于初学stm32的人
  • 蓝桥杯嵌入式第十届省赛真题 文章目录 蓝桥杯嵌入式第十届省赛真题 1.题目分析 2.项目结构 2.1数组思路 2.2Key_Flag控制对应逻辑 2.3KEY控制操作 1.题目分析 总的来说这题考点特别的少,逻辑也比我之前发的12届的...

    蓝桥杯嵌入式第十届省赛真题

    1.题目分析

    总的来说这题考点特别的少,逻辑也比我之前发的12届的停车计费简单得多,还是一样 代码结尾自取。完全免费

    相对来说能从这题学到的。对我来说我觉得是 封装一些“状态”数组。可以让代码的可读性和复用性高很多。

    思路其实很简单,就是切换界面和获取adc的值,并和上下限比较进行对应操作。

    IvVBp4.md.jpg](https://imgtu.com/i/IvVBp4)
    IvVakT.md.jpg
    IvVdtU.md.jpg

    IvVwhF.md.jpg

    2.项目结构

    变量设计:

    u32 TimingDelay = 0;
    
    //切换设置函数
    void setting();
    void Delay_Ms(u32 nTime);
    //更新
    void Upate_Data();
    //渲染主界面
    void Fflush_Main();
    //渲染设置界面
    void Fflush_Setting();
    //Key_4,3的对应控制这里的flag我觉得用的挺好的
    //后面大家会看到 
    void Key4_Control(int flag);
    void Key3_Control(int flag);
    //高光展示
    void DymaicShow(int flag);
    //控制状态
    void Status_Control()
    
    //展示数组(个人习惯)
    char MaxVolDisplay[24];
    char MinVolDisplay[24];
    char UpperDisplay[24];
    char LowerDisplay[24];
    char StatusDisplay[24];
    char VolDisplay[24];
    //状态数组
    char *Status[8]={"Normal","Upper  ","Lower  "};
    //LED灯数组 这里也非常有用,可以和后面的led灯编号对照
    uint16_t LED_Arr[9]={0,LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};
    //电压
    double Vol = 3.22;
    double MaxVol = 2.4;
    double MinVOl = 1.2;
    //LED编号
    int UpperLED = 1;
    int LowerLED = 2;
    //状态值 和状态数组比较
    int Status_Flag = 0;
    

    2.1数组思路

    首先先来聊聊为什么这里的LED要利用编号 而不是规定死字符串 “LD1”,“LD2”这样的。因为如果规定死字符串的话,到时候报警灯点亮的时候,还需要解析字符串取出最后一位的数字,麻烦

    我们不如换一种思路 规定字符串为“LD”而我们在后面动态的拼接LED的编号。也就是这样

    sprintf(UpperDisplay," Upper:LD%d",UpperLED);
    

    就做到了利用UpperDisplay动态展示对应的数据。并且UpperLED可以用来后面点亮灯。

    这也是为什么我要把LED封装成数组。

    我们可以轻易的做到 利用UpperLED作为LED数组的下标,点亮对应的LED 这样点亮就非常方便了,而不需要if判断。如下

    (这里的flag是用来交替闪烁的,200ms的时候 flag会自己取反,做到亮灭交替)

    LED_Control(LED_Arr[UpperLED],Led_Flag);
    

    那么前面的Status_Flag和char *Status[8]也是同理了;

    这里我们就可以引出我的第一个函数

    Status_Control.c

    void Status_Control()
    {
    	if(Vol>MaxVol)
    	{
            //这里的标志位是到时中断里200ms取反一次的 做到间断闪烁
            LED_Control(LED_Arr[UpperLED],Led_Flag);
    		Status_Flag=1;
    		return;
    	}
    	if(Vol<MinVOl)
    	{
            LED_Control(LED_Arr[LowerLED],Led_Flag);
    		Status_Flag=2;
    		return;
    	}
    	Status_Flag=0;
    }
    

    可以很清晰的通过代码看出。不同的Status_Flag 到时就会动态的控制char *Status[8]展示他对应的该有的变量

    sprintf(StatusDisplay,"  Status:%s",Status[Status_Flag]);
    LCD_DisplayStringLine(Line5,StatusDisplay);
    

    2.2Key_Flag控制对应逻辑

    重点就在这四个函数

    void Key4_Control(int flag);
    void Key3_Control(int flag);
    void DymaicShow(int flag);
    

    分析题目我们可以读出,在Setting界面修改的时候,需要在最大电压值,最小电压值,最大电压LED编号和最小电压LED编号。这

    四个地方切换,并通过KEY3,KEY4控制他们的加减。

    他们的共性就是 4 个位置 对应四个不同的操作模式和操作逻辑。

    (高光+KEY4+KEY3)*4个位置 那么有12种情况,为此写12个函数未免太过麻烦了。

    我们抽象的来想,可以是 3个操作,各自对应4个模式把三个操作抽象成函数

    三个操作里面对应的四种情况其实是平行关系的。

    这个平行关系我们就用Flag替代。例如flag为1,执行三个函数里各自的情况1,flag2执行三个函数里各自的情况2。

    而按键2 就是我们用来触发Flag改变的,逻辑如下(14-30行)

    如此我们的代码耦合性就会降低 ,函数各司其职。

    //切屏函数
    void setting()
    {
    	char key;
    	int flag=0;
    	LCD_Clear(White);
    	Fflush_Setting();
    	
    	while(1)
    	{
    		key = KEY_Scan();
    		Vol=Get_Adc();
    		Status_Control();
    		DymaicShow(flag);
    		switch(key)
    		{
                //返回主界面
    			case '1':
    				LCD_Clear(White);
    				LCD_SetBackColor(White);
    				return;
    			case '2':
    				flag++;
    				if(flag>=4){  flag=0;   }
    				break;
    			case '3':
    				Key3_Control(flag);
    				break;
    			case '4':
    				Key4_Control(flag);
    				break;
    		}
    	}
    }
    

    2.3KEY控制操作

    利用前面的操作,这里我们就可以做按键在不同高亮位置时不同对应的情况了,其实我觉得应该用switch case会更加好一点,结构更加清晰,但是当时写完懒得改了。

    void Key3_Control(int flag)
    {
        //最大电压值
    	if(flag==0)
    	{
    		//浮点数计算精度问题
    		if(MaxVol+0.3<3.300000000000001)
    		{
    			MaxVol+=0.3;
    			return;
    		}
    		MaxVol=3.3;
    	}
        //最小电压值
    	else if(flag==1)
    	{
    		if(MinVOl+0.3<3.300000000000001)
    		{
    			MinVOl+=0.3;
    			return;
    		}
    		MinVOl=3.3;
    	}
        //最大电压值LED编号
    	else if(flag==2)
    	{
            //这里要先关灯,不然警告闪灯的时候,假设LED1亮还没熄灭的时候,
            //我们按下Key3切换,那么LED2闪烁,LED1还在亮
    		LED_Control(LEDALL,0);
            //最大编号
    		if(UpperLED==8)
    		{
    			UpperLED=8;
    			return;
    		}
            //如果往上+1的时候,和最小电压编号的LED编号相等的时候
            //那么我们需要过这个编号,让两个编号不相等
    		if(UpperLED+1==LowerLED)
    		{
                //但是如果跨过LowerLED的编号后会超过8,那么也不行的哦
    			if(UpperLED+1==8)
    			{
    				return;
    			}
                //逻辑完成,直接跨越
    			UpperLED+=2;
    			return;
    		}
            //其他情况正常+1,后续最小电压那些也是同理,我就不写那么多注释了
    		UpperLED++;
    	}
        //最小电压值LED编号
    	else if(flag==3)
    	{
    		LED_Control(LEDALL,0);
    		if(LowerLED==8)
    		{
    			LowerLED=8;
    			return;
    		}
    		if(LowerLED+1==UpperLED)
    		{
    			if(LowerLED+1==8)
    			{
    				return;
    			}
    			LowerLED+=2;
    			return;
    		}
    		LowerLED++;
    	}
    }
    

    KEY4_Control也是这个道理。这里就不复制展示了,代码文章结尾自取

    高亮部分我来求解一下,大家有没有更好的解法,我只会这种最笨的方式

    void DymaicShow(int flag)
    {
    	LCD_SetBackColor(White);
    	if(flag==0)
    	{
    		LCD_DisplayStringLine(Line1, "      Setting");
    		LCD_DisplayStringLine(Line4,MinVolDisplay);
    		LCD_DisplayStringLine(Line5,UpperDisplay);
    		LCD_DisplayStringLine(Line6,LowerDisplay);
            //单独某一行刷新改色
    		LCD_SetBackColor(Yellow);
    		sprintf(MaxVolDisplay," Max Volt:%.2f    ",MaxVol);
    		LCD_DisplayStringLine(Line3,MaxVolDisplay);
    		return;
    	}
    	if(flag==1)
    	{
    		LCD_DisplayStringLine(Line1, "      Setting");
    		LCD_DisplayStringLine(Line3,MaxVolDisplay);
    		LCD_DisplayStringLine(Line5,UpperDisplay);
    		LCD_DisplayStringLine(Line6,LowerDisplay);
    		LCD_SetBackColor(Yellow);
    		sprintf(MinVolDisplay," Min Volt:%.2f    ",MinVOl);
    		LCD_DisplayStringLine(Line4,MinVolDisplay);
    		return;
    	}
    	if(flag==2)
    	{
    		LCD_DisplayStringLine(Line1, "      Setting");
    		LCD_DisplayStringLine(Line3,MaxVolDisplay);
    		LCD_DisplayStringLine(Line4,MinVolDisplay);
    		LCD_DisplayStringLine(Line6,LowerDisplay);
    		LCD_SetBackColor(Yellow);
    		sprintf(UpperDisplay," Upper:LD%d        ",UpperLED);
    		LCD_DisplayStringLine(Line5,UpperDisplay);
    		return;
    	}
    	if(flag==3)
    	{
    		LCD_DisplayStringLine(Line1, "      Setting");
    		LCD_DisplayStringLine(Line3,MaxVolDisplay);
    		LCD_DisplayStringLine(Line4,MinVolDisplay);
    		LCD_DisplayStringLine(Line5,UpperDisplay);
    		LCD_SetBackColor(Yellow);
    		sprintf(LowerDisplay," Lower:LD%d        ",LowerLED);
    		LCD_DisplayStringLine(Line6,LowerDisplay);
    		return;
    	}
    }
    

    最后就是这个中断里取反的操作 很简单的

    void SysTick_Handler(void)
    {
    	TimingDelay--;
    	//低于下限电压
    	if(Status_Flag==2)
    	{
    		if(++Led_Dealy==200)
    		{
    			Led_Flag= !Led_Flag;
    			Led_Dealy=0;
    		}
    	}
    	//高于上限电压
    	else if(Status_Flag==1)
    	{
    		if(++Led_Dealy==200)
    		{
    			Led_Flag= !Led_Flag;
    			Led_Dealy=0;
    		}
    	}
    }
    

    整体和逻辑有关的代码大概就是这样了

    我个人认为最好的地方就是我用了数组和对应的Flag标识,来和数组组成映射关系,在代码里的很多地方都因此受益。还是个小萌新哈,如果大家有更好的方式也欢迎大家提出
    下载资源链接 链接:源码
    提取码:noyh

    展开全文
  • 第十届赛题程序部分较为简单,客观题相对较难。主要会用adc+led即可ok,本科组甚至没有用到EEPROM(本代码加入此功能将led灯信息,上下阈值存入EEPROM,reset后数据不丢失) 先看目录 初始化函数 头文件: 初始化...
  • 第十届蓝桥杯嵌入式省赛题代码,功能全能实现,亲测有效。第十届蓝桥杯自我感觉不论是在单片机组还是嵌入式组都是十分简单的。但是如果不会ADC那就凉凉了。
  • 代码加试题
  • 蓝桥杯嵌入式第十届省赛试题

    千次阅读 多人点赞 2020-04-17 23:38:35
    蓝桥杯嵌入式第十届省赛试题 这一届的试题总的来说比较简单,没有用到太多外设。考察的也是简单的逻辑。 试题部分 程序部分 我是在液晶驱动例程直接进行程序编写的,要加入stm32f10x_adc.c文件其余的用不到(也...

    蓝桥杯嵌入式第十届省赛试题

    这一届的试题总的来说比较简单,没有用到太多外设。考察的也是简单的逻辑。
    试题部分
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    程序部分
    我是在液晶驱动例程直接进行程序编写的,要加入stm32f10x_adc.c文件其余的用不到(也可以全部加进去但是编译速度较慢)。也可以自己建立工程文件进行代码编写。
    相关驱动。

    #include "mysource.h"
    /*********************key&&led&&lcd--init*********/
    void system_init(void)
    {
      GPIO_InitTypeDef GPIO_InitStructure;
        /* GPIOD Periph clock enable */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
    
      /* Configure PD0 and PD2 in output pushpull mode */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9|GPIO_Pin_10 | GPIO_Pin_11|GPIO_Pin_12 | GPIO_Pin_13|GPIO_Pin_14 | GPIO_Pin_15;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(GPIOC, &GPIO_InitStructure);
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
      GPIO_Init(GPIOD, &GPIO_InitStructure);	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_0;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
      GPIO_Init(GPIOA, &GPIO_InitStructure);	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;	
      GPIO_Init(GPIOB, &GPIO_InitStructure);	
    	STM3210B_LCD_Init();
    	LCD_Clear(Blue);
    	LCD_SetBackColor(Blue);
    	LCD_SetTextColor(White);
    	LCD_DisplayStringLine(Line2,(unsigned char *)"        Main        ");
    	LCD_DisplayStringLine(Line4,(unsigned char *)"  Volt:             ");		
    	LCD_DisplayStringLine(Line6,(unsigned char *)"  Status:           ");			
    }
    /***********led_show****************/
    void led_control(u8 date)
    {
      GPIOD->ODR|=GPIO_Pin_2;
    	GPIOC->ODR=~(date<<8);
    	GPIOD->ODR&=~GPIO_Pin_2;
    }
    void adc_init(void)
    {
      ADC_InitTypeDef ADC_InitStructure;
      GPIO_InitTypeDef GPIO_InitStructure; 
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB, ENABLE);	
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      /* ADC1 configuration ------------------------------------------------------*/
      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
      ADC_InitStructure.ADC_ScanConvMode = DISABLE;
      ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
      ADC_InitStructure.ADC_NbrOfChannel = 1;
      ADC_Init(ADC1, &ADC_InitStructure);
    
      /* ADC1 regular channel14 configuration */ 
      ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5);
    	  /* Enable ADC1 */
      ADC_Cmd(ADC1, ENABLE);
    
      /* Enable ADC1 reset calibration register */   
      ADC_ResetCalibration(ADC1);
      /* Check the end of ADC1 reset calibration register */
      while(ADC_GetResetCalibrationStatus(ADC1));
    
      /* Start ADC1 calibration */
      ADC_StartCalibration(ADC1);
      /* Check the end of ADC1 calibration */
      while(ADC_GetCalibrationStatus(ADC1));
    }
    u16 read_adc(void)
    {
      u16 ad_value=0;
    	  /* ADC1 regular channel14 configuration */ 
      ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5);
    	  /* Start ADC1 Software Conversion */ 
      ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
    	ad_value=ADC_GetConversionValue(ADC1);
    	ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
      ADC_SoftwareStartConvCmd(ADC1, DISABLE);	
      return ad_value;
    }
    
    
    #ifndef __MYSOURCE_H
    #define __MYSOURCE_H
    #include "stm32f10x.h"
    #include "stdio.h"
    #include "lcd.h"
    #define b1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
    #define b2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
    #define b3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
    #define b4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
    void system_init(void);
    void led_control(u8 date);
    void adc_init(void);
    u16 read_adc(void);
    #endif
    

    主函数

    #include "stm32f10x.h"
    #include "lcd.h"
    #include "mysource.h"
    #include "math.h"
    u8 led_buff[9]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    u32 TimingDelay = 0;
    u8 str[20];
    void Delay_Ms(u32 nTime);
    void key_scan(void);
    void lcd_show(void);
    void error_choose(void);
    u8 set=0;//设置状态选择
    float max_ad=2.40;//电压上限
    float min_ad=1.20;//电压下限
    u8 led_choose;//led选择
    u8 i=1;//设置模式下高亮选择
    u8 j=1;//upper led选择
    u8 k=2;//lower led选择
    u8 led_choose1=0x01;//upper led初始状态
    u8 led_choose2=0x02;//lower led初始状态
    u16 led_delay=0;//滴答定时器里led0.2s延时
    u8 runled=0x00;//led的运行状态
    u8 error=0;//错误警告标志
    //Main Body
    int main(void)
    {
      SysTick_Config(SystemCoreClock/1000);
      system_init();
      led_control(0x00);//全部关闭led
      adc_init();	
    	while(1)
    	{
        error_choose();//判断是否设置下上下限电压选择错误
        key_scan();
        lcd_show();	
        led_control(runled);
    	}
    }
    
    //
    void Delay_Ms(u32 nTime)
    {
    	TimingDelay = nTime;
    	while(TimingDelay != 0);	
    }
    void key_scan(void)//按键扫描
    {
      if(b1==0)
    	{
    	  Delay_Ms(30);
    		if(b1==0)
    		{
    			if(error==0)//错误设置下不能返回主界面
    			{
    					LCD_Clear(Blue);
    					set=!set;
    					error=0;
    			}
    		
    		}
    	 while(!b1);
    	}
      else if(b2==0)
    	{
    	  Delay_Ms(30);
    	  if(b2==0)
    		{
    			if(set==1)//高亮切换
    			{
    		  i++;
    			if(i==5)
    			{
    			  i=1;
    			}
    		}
    		}
    	  while(!b2);
    	}
      else if(b3==0)
    	{
    	  Delay_Ms(30);
        if(b3==0)
    		{
    			if(set==1)
    			{
    			if(i==1)
    			{
    			  max_ad+=0.3;
    				if(max_ad>3.3)
    				{
    				  max_ad=3.3;
    				}
    			}
    			else if(i==2)
    			{
    			  min_ad+=0.3;
    				if(min_ad>3.3)
    				{
    				  min_ad=3.3;
    				}
    			}
    			else if(i==3)
    			{
    				j++;
    				if(j==9)
    				{
    				  j=8;
    				}
    			  led_choose1=led_buff[j];
    			}
    			else if(i==4)
    			{
    				k++;
            if(k==9)
    				{
    				  k=8;
    				}		
    			  led_choose1=led_buff[k];
    			} 
    		}
    		
    		}			
    	 while(!b3);
    	}
    	else if(b4==0)
    	{
    	  Delay_Ms(30);
    		if(b4==0)
    		{
    			if(set==1)
    			{
    			if(i==1)
    			{
    			  max_ad-=0.3;
    				if(max_ad<0)
    				{
    				  max_ad=0;
    				}
    			}
    			else if(i==2)
    			{
    			  min_ad-=0.3;
    				if(min_ad<0)
    				{
    				  min_ad=0;
    				}
    			}
    			else if(i==3)
    			{
    				j--;
    				if(j==0)
    				{
    				  j=1;
    				}
    			  led_choose1=led_buff[j];//选择upper led
    			}
    			else if(i==4)
    			{
    				k--;
            if(k==0)
    				{
    				  k=1;
    				}		
    			  led_choose1=led_buff[k];//选择lower led
    			} 
    		}
    		
    		}
    	while(!b4);
    	}
    }
    void lcd_show(void)//lcd界面展示
    {
      if(set==0)
    	{
    			LCD_DisplayStringLine(Line2,(unsigned char *)"        Main        ");
    		  sprintf((char*)str,"  Volt:%1.2fV             ",read_adc()*3.3/0XFFF);
    	    LCD_DisplayStringLine(Line4,str);
          if((read_adc()*3.3/0XFFF)>max_ad)	
    			{
    				 led_choose=3;
    				 LCD_DisplayStringLine(Line6,(unsigned char *)"  Status:Upper           ");
    			}
          else if((read_adc()*3.3/0XFFF)<min_ad)	
    			{
    				 led_choose=1;
    				 LCD_DisplayStringLine(Line6,(unsigned char *)"  Status:Lower           ");			  
    			}	
          else
    			{
    				 led_choose=2;			  
    				 LCD_DisplayStringLine(Line6,(unsigned char *)"  Status:Normal           ");				
    			}		
          			
    	}
    	else
    	{
    	  LCD_DisplayStringLine(Line0,(unsigned char *)"       Setting     ");
    		if(i==1)
    		{
    			LCD_SetBackColor(White);
    	    LCD_SetTextColor(Blue);
    		}
    		sprintf((char*)str,"  Max Volt:%1.1f         ",max_ad);
    	  LCD_DisplayStringLine(Line2,str);
    	  LCD_SetBackColor(Blue);
    	  LCD_SetTextColor(White);
    
    		if(i==2)
    		{
    			LCD_SetBackColor(White);
    	    LCD_SetTextColor(Blue);
    		}    		
    		sprintf((char*)str,"  Min Volt:%1.1f         ",min_ad);    		
    	  LCD_DisplayStringLine(Line4,str);
    	  LCD_SetBackColor(Blue);
    	  LCD_SetTextColor(White);		
    		
    		if(i==3)
    		{
    			LCD_SetBackColor(White);
    	    LCD_SetTextColor(Blue);
    		}    		
        sprintf((char*)str,"  Upper:LD%d           ",j);
    		LCD_DisplayStringLine(Line6,str);
    	  LCD_SetBackColor(Blue);
    	  LCD_SetTextColor(White);
    
    		if(i==4)
    		{
    			LCD_SetBackColor(White);
    	    LCD_SetTextColor(Blue);
    		}   		
        sprintf((char*)str,"  Lower:LD%d           ",k);
    		LCD_DisplayStringLine(Line8,str);
    	  LCD_SetBackColor(Blue);
    	  LCD_SetTextColor(White);		
    	}
    	 if(error==1)
    	 {
    	   LCD_SetTextColor(Red);
    	   LCD_DisplayStringLine(Line9,(unsigned char*)"             Error!  ");
    		 LCD_SetTextColor(White);
    	 }
    	 else
    	 {
    	   LCD_ClearLine(Line9);
    	   
    	 }
    	 led_choose=0;
    }
    void error_choose(void)
    {
    	if(set==1)
    	{
      if(((max_ad>min_ad)&&fabs(max_ad-min_ad)>1e-6)&&(j!=k))
    	{
    	  error=0;
    
    	}
    	else
    	{
    	  error=1;	  
    	}
    
    }
    
    }
    void SysTick_Handler(void)//滴答定时器初始化
    {
    	TimingDelay--;
    	if(led_choose==1)
    	{
    	  if(++led_delay==200)
    		{
    		  led_delay=0;
    			runled&=~led_buff[j];			
    			runled^=led_buff[k];
    		
    		}
    	
    	}
    	else if(led_choose==2)
    	{
    	
    	  runled&=~0xff;
    	
    	}
    	else if(led_choose==3)
    	{
    	
    	  if(++led_delay==200)
    		{
    		  led_delay=0;
    			runled&=~led_buff[k];
    			runled^=led_buff[j];
    		
    		}	  
    	
    	}
    	else 
    	{
    	  runled=0x00;//关所有led
    	}
    }
    
    
    展开全文
  • 代码下载(内含试题)  https://gitee.com/litte_enigner/lqb_emb_10th.git 第十届蓝桥杯自我感觉不论是在单片机组还是嵌入式组都是十分简单的。但是如果不会ADC那就凉凉了。 作者:little_engineer
  • 第十届蓝桥杯嵌入式省赛(适用STM32G431 CUBEMX HAL库)
  • 蓝桥杯嵌入式第十届省赛-电压检测仪
  • 蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛

    千次阅读 多人点赞 2021-05-22 13:18:35
    蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛 目录蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛一、赛题二、CubeMX模块配置三、部分模块代码四、完整代码下载 一、赛题 上一次做了第十一届的国赛赛题,感觉很容易。然后这两...

    蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛

    一、赛题

    上一次做了第十一届的国赛赛题,感觉很容易。然后这两天做了第十届的赛题,感觉第十届的赛题是十一届难度的两倍。这一届的赛题考察的内容特别多,并且逻辑方面相比十一届也是难度大一些的,所以正式比赛的时候,如果不是特别熟悉,还有可能不能把全部的功能都实现。这一届考察的内容大致如下:

    LED
    LCD,LCD的高亮显示
    独立按键,长按
    双通道ADC转换
    定时器的输入捕获,检测占空比
    EEPROM数据的读写,使用EEPEOM存放16位数据
    DS18B20,精确到两位小数
    USAR串口的收发
    数码管显示

    这一届的题目还是挺有意义的,难度有一丢丢大,拿来赛前练手挺好的。

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    二、CubeMX模块配置

    1. DMA的配置
      用到一个DMA,用于ADC2的双通道转换
      在这里插入图片描述

    2. GPIO的配置
      在这里插入图片描述

    3. 中断的配置
      打开相应的中断,注意图上标红的地方,要关闭ADC的DMA中断,否则会不断的进入中断,打断CPU的执行。在这里插入图片描述

    4. ADC2的配置
      主要注意一下,我们用到了ADC2的两个通道,所以这里我们使用了DMA,每个通道转换完成的数据就会由DMA直接将对应的数据存放到相应的存储器中,所以我们后面只需要读取对应的存储器的值即可。如果不使用DMA也是可以的, 要麻烦一点,网上有很多资料,这里就不多说。
      ADC配置需要注意的是,要先添加DMA,然后才能在ADC的参数设置中使能ADC DMA转换,除此之外还要使能扫描转换,以及连续转换模式,否则只能自动转换一次ADC的数据,后面的每一次都要重新使能。
      在这里插入图片描述

    5. 定时器输入捕获
      其中81 - 1 分频是将定时器的时钟配置为1MHz。因为在系统时钟为80MHz。重转载计数器一定要设置为最大,对于16位的寄存器最大值也就是65535。
      在这里插入图片描述

    6. 串口的配置
      在这里插入图片描述

    三、部分模块代码

    1. 数码管
    #define			SEG_H			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
    #define			SEG_L			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)
    #define			RCK_H			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET)
    #define			RCK_L			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET)
    #define			SCK_H			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET)
    #define			SCK_L			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET)
    uint
    8_t seg_buf[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x39,0x77,0x00};
    
    void seg_set(uint8_t seg1,uint8_t seg2,uint8_t seg3)
    {
    	uint32_t seg = (seg_buf[seg3] << 16) | (seg_buf[seg2] << 8) | seg_buf[seg1];
    	uint8_t i;
    	for(i = 0; i < 24; i++)
    	{
    		if(seg & 0x800000)
    			SEG_H;
    		else
    			SEG_L;
    		seg <<= 1;
    		SCK_H;
    		SCK_L;
    	}
    	RCK_H;
    	RCK_L;
    }
    
    1. LCD高亮显示
      关于高亮显示的具体原理可以参考我的另一篇博客https://blog.csdn.net/qq_43715171/article/details/115238360
    void highlight(u8 Line, u8 *ptr)
    {
    	u32 i = 0;
    	u16 refcolumn = 319;//319;
    
    	while ((*ptr != 0) && (i < 20))	 //	20
    	{
    		if(((Line == Line3 && select == 0) || (Line == Line4 && select == 1)) && (i > 0 && i < 18))
    			LCD_SetBackColor(Yellow);
    		else
    			LCD_SetBackColor(Black);
    		LCD_DisplayChar(Line, refcolumn, *ptr);
    		refcolumn -= 16;
    		ptr++;
    		i++;
    	}
    }
    
    1. 按键的长按检测
      这里要解释一下,下面这一段程序是放在key_scan()里面,10ms扫描一次。
      以B3为例,假设此前是松开状态,如果B3按下,key_cnt就加1,加到90的时候,就触发长按,也就是90*10 = 900ms。然后将key_cnt设置为80,等到下一次到达90的时候,经过了(90-80)*10 = 100ms,也就是长按触发之后,没100ms将temp_upper_temp加1。如果没有按键按下要将key_cnt清零,以等待下一次的检测。
    if(key_state == B3 && interface == PARA && select == 0 && ++key_cnt == 90)
    	{
    		key_cnt = 80;
    		if(temp_upper_temp < 40)
    			temp_upper_temp++;
    	}
    	if(key_state == B4 && interface == PARA && select == 0 && ++key_cnt == 90)
    	{
    		key_cnt = 80;
    		if(temp_upper_temp > 20)
    			temp_upper_temp--;
    	}
    	if(key_state == 0)
    	{
    		key_cnt = 0;
    	}
    
    1. 占空比检测的代码
      核心程序就在这里回调函数中了。
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	if(htim -> Instance == TIM3)
    	{
    		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
    		{
    			if(CaptureNumber == 0)
    			{
    				/* Get the Input Capture value */
    				IC3ReadValue1 = TIM3->CCR2;
    				CaptureNumber = 1;
    				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
    			}
    			else if(CaptureNumber == 1)
    			{
    				/* Get the Input Capture value */
    				IC3ReadValue2 = TIM3->CCR2;
    				CaptureNumber = 2;
    				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
    				if (IC3ReadValue2 > IC3ReadValue1)
    				{
    					Capture_High = (IC3ReadValue2 - IC3ReadValue1); 
    				}
    				else
    				{
    					Capture_High = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
    				}
    				IC3ReadValue1 = IC3ReadValue2;
    			}
    			else if(CaptureNumber == 2)
    			{
    				/* Get the Input Capture value */
    				IC3ReadValue2 = TIM3->CCR2;
    				CaptureNumber = 0;
    				if (IC3ReadValue2 > IC3ReadValue1)
    				{
    					Capture_Low = (IC3ReadValue2 - IC3ReadValue1); 
    				}
    				else
    				{
    					Capture_Low = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
    				}
    				/* Frequency computation */ 
    				TIM3Freq = (uint32_t) 1000000 / (Capture_Low + Capture_High);
    				TIM3Duty = Capture_High * 1.0 / (Capture_Low + Capture_High);
    				pwm2 = TIM3Duty;
    			}
    		}
    	}
    }
    
    1. 串口的不定长数据接收以及数据的处理
      在我最近的一篇博客中,比较详细的讲解了使用IDLE+RXNE实现的串口的不定长数据接收 ,这里就不展开讲解啦。
      https://blog.csdn.net/qq_43715171/article/details/117132151

    数据的处理代码如下:

    
    void usart_proc(void)
    {
    	if(channel_x == A01 && a01 > pwm2 * 3.3 && usart_flag)
    	{
    		usart_flag = 0;
    		printf("$%.2f\r\n",temperature);
    	}
    	else if(channel_x == A02 && a02 > pwm2 * 3.3 && usart_flag)
    	{
    		usart_flag = 0;
    		printf("$%.2f\r\n",temperature);
    	}
    	
    	if((channel_x == A01 && a01 <= pwm2 * 3.3) || (channel_x == A02 && a02 <= pwm2 * 3.3))
    	{
    		usart_flag = 0;
    		usart_tick = 0;
    	}
    	
    	if(UART1_IDLE_Flag)
    	{
    		UART1_IDLE_Flag = 0;
    		
    //		memset(lcd_str,0,sizeof(lcd_str));
    //		snprintf((char*)lcd_str,20,"%s",RxBuffer);
    //		LCD_DisplayStringLine(Line9, lcd_str);
    		
    		if(strcmp((const char *)RxBuffer,"ST\r\n") == 0)
    		{
    			printf("$%.2f\r\n",temperature);
    		}
    		else if(strcmp((const char *)RxBuffer,"PARA\r\n") == 0)
    		{
    			printf("#%d,AO%d\r\n",temp_upper,channel_x + 1);
    		}
    		
    		memset(RxBuffer,0,sizeof(RxBuffer));
    		RxCounter = 0;
    	}
    }
    
    

    四、完整代码下载

    代码使用说明,一定要看

    完整代码下载点我

    展开全文
  • 蓝桥杯单片机第十届国赛题程序,里面有hex代码可提供下载调试,需要源码和赛题请解压里面的一个压缩包,里面包含源码和hex文件的源代码。非常的银杏,非常的好用。
  • 原题请戳这里第十届省赛真题 功能分析: 本题需要使四个模块: LED模块,实现提示灯功能(200ms闪烁) LCD模块,显示数据界面和设置界面 按键模块,用于在切换显示界面和在设置界面调节参数 ADC模块,用于采集转换...

    题目分析

    原题:

    原题请戳这里第十届省赛真题

    功能分析:

    本题需要使四个模块:

    1. LED模块,实现提示灯功能(200ms闪烁)
    2. LCD模块,显示数据界面和设置界面
    3. 按键模块,用于在切换显示界面和在设置界面调节参数
    4. ADC模块,用于采集转换电压值

    工具

    1. 软件:MDK ARM V5、STM32CubeMX v6.1.1
    2. 硬件:STM32G431RBTx 开发板

    程序设计

    CubeMX配置
    1. 本题CubeMX配置与我上一篇博客做的十一届真题相差不大,只少去了PWM的配置,可以参照上篇博文链接请戳这里蓝桥杯第十一届省赛真题练习
    代码实现

    本题需要自行添加官方例程中的lcd.c、lcd.h、fonts.h文件

    main.c中

    /* USER CODE BEGIN Includes */
    #include"lcd.h"
    #include"stdio.h" //speintf函数需要用到
    /* USER CODE END Includes */
    
    /* USER CODE BEGIN PV */
    char Buf[20];//用于存放格式化后的电压值字符串
    extern uint8_t LED_Flag;//外部变量声明,LED 200ms延时的标志变量
    uint8_t Key_Val=0; //键值
    uint8_t B1_Val=0; //B1按键标志
    uint8_t B2_Val=0;//B2按键标志
    uint8_t B3_Val=0;//B3按键标志
    uint8_t B4_Val=0;//B4按键标志
    char Upper_LimitValData[20];//用于存放格式化后的上限电压字符串
    char Lower_LimitValData[20];//用于存放格式化后的下限电压字符串
    float Upper_LimitVal =2.4;// 电压上限值
    float Lower_LimitVal =1.2;// 电压下限值
    char LDModeBuf[20];//用于存放格式化后的指示灯标号字符串
    uint8_t UpLDMode=1;//上限指示灯标号
    uint8_t LoLDMode=2;//下限指示灯标号
    uint8_t Status=0;//状态 0为主界面,1为设置界面
    char StatusBuf[20]; //用于存放格式化后的状态字符串
    char Status_Upper[20]="Upper"; //超过上限
    char Status_Lower[20]="Lower"; //低于下限
    char Status_Normal[20]="Normal";//正常
    /* USER CODE END PV */
    /* USER CODE BEGIN PFP */
    uint8_t Key_Scan()  //按键检测
    {
    	if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET) //B4
    	{
    		HAL_Delay(10);
    		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
    		{
    			
    			Key_Val=4; //返回按键值
    			B4_Val++;
    			if(B4_Val>1)
    			{
    				B4_Val=0;
    			}			
    		}
    			
    	}
    	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET)//B3
    	{
    		HAL_Delay(10);
    		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET)
    		{
    			
    			Key_Val=3;//返回按键值
    			B3_Val++;
    			if(B3_Val>1)
    			{
    				B3_Val=0;
    			}
    		}
    	}
    	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)//B2
    	{
    		HAL_Delay(10);
    		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)
    		{
    			
    			Key_Val=2;//返回按键值
    
    				B2_Val++;
    				if(B2_Val>4)
    				{
    					B2_Val=1;
    				}
    		}
    	}
    	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)//B1
    	{
    		HAL_Delay(10);
    		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
    		{	
    			Key_Val=1;//返回按键值
    			B1_Val++;
    			if(B1_Val>1)
    			{
    				B1_Val=0;
    			}
    		}
    	}
    	
    	return Key_Val;//返回按键值
    }
    
    uint16_t getADC(void) //ADC转换,返回电压值
    {
    	
    	uint16_t ADC_val = 0;
    	HAL_ADC_Start(&hadc2);
    	ADC_val = HAL_ADC_GetValue(&hadc2);
    	
    	return ADC_val ;//返回电压值
    }
    
    void LCD_HighLight() //高亮
    {
    			LCD_SetBackColor(White);
    			LCD_SetTextColor(Black);
    }
    void DeLCD_HighLight()//清除高亮
    {
    			LCD_SetBackColor(Black);
    			LCD_SetTextColor(White);
    }
    void LCD_SET() //设置界面
    {
    		
    			LCD_DisplayStringLine(Line2,(u8*)"       Setting      ");
    			sprintf(Upper_LimitValData, "   Max Volt:%.1fV     ", Upper_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line3, (uint8_t *)Upper_LimitValData);
    			sprintf(Lower_LimitValData, "   Min Volt:%.1fV     ", Lower_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line4, (uint8_t *)Lower_LimitValData);
    			sprintf(LDModeBuf, "   Upper:LD%d        ", UpLDMode );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line5, (uint8_t *)LDModeBuf);
    			sprintf(LDModeBuf, "   Lower:LD%d        ", LoLDMode);
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line6,(u8*)LDModeBuf);
    
    }
    void LCD_Mian()//主界面(默认界面)
    {
    	LCD_DisplayStringLine(Line2,(u8*)"        Main        ");
    	LCD_ClearLine(Line3);
    	LCD_ClearLine(Line4);
      	sprintf(Buf, "      Volt:%.2fV    ", getADC()*3.3/4096);
    	HAL_Delay(50);
    	LCD_DisplayStringLine(Line5, (uint8_t *)Buf);
    }
    
    void LED_Reset(uint8_t led_bit)//熄灭灯
    {
        uint32_t pin = GPIOC->IDR;
        GPIOC->BSRR = (uint16_t)led_bit << 8; //置GPIOC->BSRR高16位的某位为’1’,则对应的I/O端口管脚置’0’;
        // 更新锁存器
        GPIOD->BSRR |= GPIO_PIN_2; //开锁存
        __NOP();
        __NOP();
        __NOP();
        GPIOD->BRR |= GPIO_PIN_2;//关锁存
        __NOP();
        __NOP();
        __NOP();
        // 还原原始值
        GPIOC->BSRR = pin;
    }
     void LED_Set(uint8_t led_bit)//点亮灯
    {
        uint32_t pin = GPIOC->IDR;
        // 熄灭所有LED
        LED_Reset(0xff);
        GPIOC->BRR = (uint32_t)led_bit << 8;
        // 更新锁存器
        GPIOD->BSRR |= GPIO_PIN_2;
        __NOP();
        __NOP();
        __NOP();
        GPIOD->BRR |= GPIO_PIN_2;
        __NOP();
        __NOP();
        __NOP();
        // 还原原始值
        GPIOC->BSRR = pin;
    }
    
    void LED_Flash(uint8_t led_bit) //LED闪烁
    {
    	if(LED_Flag==0)//没到时间
    	{
    		LED_Set(0x00);//熄灭所有灯 	
    	}	 
    	else
    	{
    		LED_Set(led_bit);//点亮对应的指示灯
    	}
    	
    }
    
    void B1_Callback() //B1按键回调函数
    {
    	switch(B1_Val)
    	{
    		case 0:
    			LCD_Mian(); 
    			Status=0;//状态为0,显示主界面
    			break;
    		case 1:
    			Status=1;//状态置1,进入设置界面
    				break;
    	}
    }
    void B2_Callback() //按键B2的回调函数,用于参数界面实现高亮
    {
    	switch(B2_Val)
    		{
    
    			case 1:	 //显示的第一行高亮				
    				LCD_HighLight();
    				sprintf(Upper_LimitValData, "   Max Volt:%.1fV     ", Upper_LimitVal );
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line3, (uint8_t *)Upper_LimitValData);
    				DeLCD_HighLight();
    				break;
    			case 2: //显示的第二行高亮		
    
    				LCD_HighLight();
    				sprintf(Lower_LimitValData, "   Min Volt:%.1fV     ", Lower_LimitVal );
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line4, (uint8_t *)Lower_LimitValData);
    				DeLCD_HighLight();	
    				break;
    			case 3:	//显示的第三行高亮						
    				LCD_HighLight();
    				sprintf(LDModeBuf, "   Upper:LD%d        ", UpLDMode );
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line5, (uint8_t *)LDModeBuf);
    				DeLCD_HighLight();
    				break;
    			case 4: //显示的第四行高亮		
    			    LCD_HighLight();
    			    sprintf(LDModeBuf, "   Lower:LD%d        ", LoLDMode);
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line6,(u8*)LDModeBuf);
    				DeLCD_HighLight();
    				break;
    				}		
    }
    
    void B3_Callback() //按键B3的回调函数,用于实现按键“加”功能
    {
    	if(B3_Val==1&&B2_Val==1)//设置界面显示的第一行时,按键B3按下上限电压值加0.3,最大3.3
    	{
    		if(Upper_LimitVal>=0&&Upper_LimitVal+0.3f<=3.3f)//控制范围
    		{
    			Upper_LimitVal+=0.3f;
    			LCD_HighLight();
    			sprintf(Upper_LimitValData, "   Max Volt:%.1fV     ", Upper_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line3, (uint8_t *)Upper_LimitValData);
    			DeLCD_HighLight();	
    			B3_Val=0;//确保按下一次数值只加一次	
    		}	
    	}
    	else if(B3_Val==1&&B2_Val==2)//设置界面显示的第二行时,按键B3按下下限电压值加0.3,最大3.3
    	{
    		if(Lower_LimitVal>0&&Lower_LimitVal+0.3f<=3.3f)//控制范围
    		{
    			Lower_LimitVal+=0.3f;
    			LCD_HighLight();
    			sprintf(Lower_LimitValData, "   Min Volt:%.1fV     ", Lower_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line4, (uint8_t *)Lower_LimitValData);
    			DeLCD_HighLight();
    			B3_Val=0;
    		}
    	}
    	else if(B3_Val==1&&B2_Val==3)//设置界面显示的第三行时,按键B3按下上限指示灯序号加一,范围LED1~LED8
    	{
    		UpLDMode+=1;
    		if(UpLDMode>8)//控制范围
    		{
    			UpLDMode=1;
    		}
    		LCD_HighLight();
    		sprintf(LDModeBuf, "   Upper:LD%d        ", UpLDMode );
    		HAL_Delay(50);
    		LCD_DisplayStringLine(Line5, (uint8_t *)LDModeBuf);
    		DeLCD_HighLight();
    		B3_Val=0;
    	}
    	else if(B3_Val==1&&B2_Val==4)//设置界面显示的第四行时,按键B3按下下限指示灯序号加一,范围LED1~LED8
    	{
    		LoLDMode+=1;
    		if(LoLDMode>8)//控制范围
    		{
    			LoLDMode=1;
    		}
    		LCD_HighLight();
    		sprintf(LDModeBuf, "   Lower:LD%d        ", LoLDMode);
    		HAL_Delay(50);
    		LCD_DisplayStringLine(Line6,(u8*)LDModeBuf);
    		DeLCD_HighLight();
    		B3_Val=0;
    	}
    }
    void B4_Callback() //按键B4的回调函数,用于实现按键“减”功能
    {
    	if(B4_Val==1&&B2_Val==1)//设置界面显示的第一行时,按键B3按下上限电压值减0.3,最小0
    	{
    		if(Upper_LimitVal-0.3f>=0&&Upper_LimitVal<=3.3f) //控制范围0~3.3
    		{
    			Upper_LimitVal-=0.3f;
    			LCD_HighLight();
    			sprintf(Upper_LimitValData, "   Max Volt:%.1fV     ", Upper_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line3, (uint8_t *)Upper_LimitValData);
    			DeLCD_HighLight();		
    		}
    		B4_Val=0;//确保按键按下一次,值只加一次
    
    	}
    	else if(B4_Val==1&&B2_Val==2)//设置界面显示的第二行时,按键B3按下下限电压值减0.3,最小0
    	{
    		if(Lower_LimitVal-0.3f>=0&&Lower_LimitVal<=3.3f)//控制范围0~3.3
    		{
    			Lower_LimitVal-=0.3f;
    			LCD_HighLight();
    			sprintf(Lower_LimitValData, "   Min Volt:%.1fV     ", Lower_LimitVal );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line4, (uint8_t *)Lower_LimitValData);
    			DeLCD_HighLight();
    			
    		}
    		B4_Val=0;
    	}
    	else if(B4_Val==1&&B2_Val==3)//设置界面显示的第三行时,按键B3按下上限指示灯序号减一,范围LED1~LED8
    	{
    			UpLDMode-=1;
    			B4_Val=0;
    			if(UpLDMode<1)
    			{
    				UpLDMode=8;
    			}
    			LCD_HighLight();
    			sprintf(LDModeBuf, "   Upper:LD%d        ", UpLDMode );
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line5, (uint8_t *)LDModeBuf);
    			DeLCD_HighLight();
    			
    	}
    	else if(B4_Val==1&&B2_Val==4)//设置界面显示的第四行时,按键B3按下上限指示灯序号减一,范围LED1~LE
    	{		
    			B4_Val=0;
    			LoLDMode-=1;
    			if(LoLDMode<1)
    			{
    				LoLDMode=8;
    			}
    			LCD_HighLight();
    			sprintf(LDModeBuf, "   Lower:LD%d        ", LoLDMode);
    			HAL_Delay(50);
    			LCD_DisplayStringLine(Line6,(u8*)LDModeBuf);
    			DeLCD_HighLight();
    			
    	}
    }
    /* USER CODE END PFP */
    
      /* USER CODE BEGIN 2 */
      LCD_Init();//LCD初始化
      LCD_Clear(Black);//清屏
      LCD_SetBackColor(Black);//设置背景色
      LCD_SetTextColor(White);//设置前景色
      LCD_Mian();//显示主界面
      /* USER CODE END 2 */
    /* USER CODE END WHILE */
    	  if(getADC()*3.3f/4096>Upper_LimitVal)//电压超出上限值
    	  {
    			if(B1_Val==0)
    			{
    				sprintf(StatusBuf, "     Status:%s   ", Status_Upper );
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line6, (uint8_t *)StatusBuf);
    			}
    
    			switch(UpLDMode)//选择闪烁指示灯
    			{
    				case 1:
    					LED_Flash(0x01);
    					break;
    				case 2:
    					LED_Flash(0x02);
    					break;
    				case 3:
    					LED_Flash(0x04);
    					break;
    				case 4:
    					LED_Flash(0x08);
    					break;
    				case 5:
    					LED_Flash(0x10);
    					break;
    				case 6:
    					LED_Flash(0x20);
    					break;
    				case 7:
    					LED_Flash(0x40);
    					break;
    				case 8:
    					LED_Flash(0x80);
    					break;
    			}
    	  }
    	  else if(getADC()*3.3f/4096<Lower_LimitVal)//电压低于下限值
    	  {
    			if(B1_Val==0)
    			{
    				sprintf(StatusBuf, "     Status:%s   ", Status_Lower );
    				HAL_Delay(50);
    				LCD_DisplayStringLine(Line6, (uint8_t *)StatusBuf);
    			}			
    			switch(LoLDMode) //选择闪烁指示灯
    			{
    				case 1:
    					LED_Flash(0x01);
    					break;
    				case 2:
    					LED_Flash(0x02);
    					break;
    				case 3:
    					LED_Flash(0x04);
    					break;
    				case 4:
    					LED_Flash(0x08);
    					break;
    				case 5:
    					LED_Flash(0x10);
    					break;
    				case 6:
    					LED_Flash(0x20);
    					break;
    				case 7:
    					LED_Flash(0x40);
    					break;
    				case 8:
    					LED_Flash(0x80);
    					break;
    			}
    	  }
    	  else //电压在正常范围
    	  {
    			LED_Set(0x00);
    			if(B1_Val==0)
    			{
    					sprintf(StatusBuf, "     Status:%s   ", Status_Normal );
    					HAL_Delay(50);
    					LCD_DisplayStringLine(Line6, (uint8_t *)StatusBuf);
    			}
    			else
    			{
    				LCD_ClearLine(6);
    			}
    	  }
    		Key_Scan(); //按键扫描
    		B1_Callback();
    		switch(Status) //界面显示
    		{
    			case 0:
    				
    			break;
    			case 1:
    					LCD_SET();
    					switch(Key_Val)
    					{
    							case 2:
    								B2_Callback();
    							break;
    							case 3:
    								B3_Callback();
    								break;
    							case 4:
    								B4_Callback();
    								break;
    					}
    			break;
    
    		}
    
    

    stm32g4xx_it.c中

    /* USER CODE BEGIN PV */
    uint8_t LED_Ms=0; //计数标志
    uint8_t LED_Flag=0;//达到200ms 标志
    /* USER CODE END PV */
    
    void SysTick_Handler(void) //默认1ms进入一次中断
    {
      /* USER CODE BEGIN SysTick_IRQn 0 */
      if( LED_Ms++==200)
      {
    	  LED_Ms=0;
    	  LED_Flag=~LED_Flag;
      }
      /* USER CODE END SysTick_IRQn 0 */
      HAL_IncTick();
      /* USER CODE BEGIN SysTick_IRQn 1 */
    
      /* USER CODE END SysTick_IRQn 1 */
    }
    
    

    总结

    本题需要考虑到B2,B3,B4按键只在设置界面显示时才生效,所以需要考虑状态问题。其余功能就是调用函数,主要是框架需要设计好,本文程序写的比较“乱”,程序设计方面还很不足,在此方面还需要加强。题目功能以大致实现,性能方面还待加强

    展开全文
  • 蓝桥杯嵌入式 -第十届经验

    千次阅读 多人点赞 2019-06-01 11:23:42
      蓝桥杯嵌入式比赛主要分为两个部分: 选择题 和 程序题 。    选择题 主要考察的有 数电 、 模电 的知识,还有一些 ARM体系结构 的东西。由于机械专业的,数电模电没有学过所以全程蒙,ARM体系结构相关的在...
  • 根据第九届蓝桥杯国赛赛题自己写的答案,完成全部任务要求,设计内容有:LED提示、PWM信号采集、模拟信号、温度等。
  • 蓝桥杯嵌入式第十届省赛题+程序。 系统功能描述如下: 1)基本功能 (1)测量实训平台上电位器R37输出的模拟电压Rs,并通过液晶屏实现数据展示。 (2)通过LED指示灯实现超出上限、低于下限的提醒功能。 (3)...
  • 第十届蓝桥杯嵌入式比赛经历

    千次阅读 多人点赞 2019-03-25 11:05:53
    第十届蓝桥杯嵌入式比赛经历 题外话 作为一个第一次写CSDN博客的新人,就写一下关于对这次蓝桥杯嵌入式比赛的感想!先说点题外话,其实在本科的时候,就一直想自己写博客,写下自己的一些自己认为是技术的东西, ...
  • **本程序设计是基于嵌入式开发板CT117E,stm32f103RBT6。 如果对哪个模块的代码不理解可以点开我的博客查看各个模块的编写思路。 一、试题 二、需要用到的模块 1.LED 代码如下:led.c: #include "led.h" void...
  • 第十届蓝桥杯自我感觉不论是在单片机组还是嵌入式组都是十分简单的。但是如果不会ADC那就凉凉了。 先看一下功能要求大致意思是说设计一个电压检测装置,在电压值达到上限或者限制的时候有相应的指示。同时还可以...
  • 标题在这里插入代码片
  • 蓝桥杯单片机第十届程序设计.rar
  • 2019年第十届蓝桥杯客观题资源,里面有十道2019年3月24号考试的蓝桥杯客观题,内容真实有效,可以下载下来用来备考下一年蓝桥杯

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 186
精华内容 74
关键字:

蓝桥杯嵌入式第十届