精华内容
下载资源
问答
  • 2021-11-29 14:09:52

    蓝桥杯第九届省赛真题

    源码在这需要的可以自取

    1.题目

    1、LCD 显示

    ​ LCD 显示存储位置、定时时间和当前状态。系统预留 5 个存储位置用于存储常用的定时时间。当定时器停止时,当前状态为 Standby;当系统正在设置时间时,当前状态为 Setting;当定时器运行时,当前状态为 Running,定时器暂停时,当前状态为 Pause。
    在这里插入图片描述

    2、按键功能

    系统使用 4 个按键,B1、B2、B3 和 B4。

    按键 B1 为存储位置切换键。每按一次,存储位置依次以 1、2、3、4、5循环切换,切换后定时时间设定为当前位置存储的时间。
    按键 B2 为时间位置(时、分、秒)切换键和存储键。短按 B2 键进入时间设置状态。每次短按 B2 键,设置位置以时、分、秒循环切换,并突出显示(高亮)当前位置;设置完后,长按 B2 键(超过 0.8 秒)把设置的时间存储到当前的存储位置,并推出设置状态。如果是临时设置定时时间,则不需存储,直接按定时器启动按键。

    按键 B3 为时、分、秒(按键 B2 确定当前位置)数字增加键。每短按B3 一次,数字递增一次;按住 B3 超过 0.8 秒,则数字快速递增,直到松开B3 按键。数字递增时,超出范围则从头循环。

    按键 B4 为定时器启动键。短按 B4,定时器启动,开始运行;运行期间短按 B4,暂停定时器,再短按 B4,恢复定时器运行;长按 B4(超过 0.8 秒),则取消定时器运行,回到 Standby 状态。

    3、PWM 输出和 LED 显示

    定时器运行时,PA6 口输出 PWM 信号,同时 LED 灯(LD1)以 0.5 秒的频率闪烁。PWM 信号频率为 1KHz,占空比为 80%。
    定时器停止或暂停时,停止输入 PWM 信号,LED 灯灭。

    4、定时时间存储

    设定好的定时时间存储在 EEPROM 中。
    掉电重启后,显示存储位置 1 的定时时间。

    2.题目分析

    源码在结尾 完全免费开源!!!

    源码在结尾 完全免费开源!!!

    源码在结尾 完全免费开源!!!

    这道题我乍一看 ,欸 就这?这么简单? 但是其实实现起来的时候发现和想象中的不一样,题目里有很多小坑要去处理,不然程序到处会有奇奇怪怪的bug,虽然这些bug大部分情况下不会太影响你的程序正常运行,但我们尽量还是把程序做到完美一点点吧

    要注意几个小点

    • 设置时间时,时间的跳动规则不能使用我们平时正常倒计时的规则,会有小bug。也就是我们在正常倒计时的地方要加一句限定,限定只有不在设置的时候才是正常倒计时的时间规则。

    • 反正挺多地方都需要加上这个设置限定的,长短按的地方也有很多小细节要注意

    • 改变状态的显示可以利用我之前的文章有提到的,详情参考

      封装数组的方法去做,顺便再写一个控制所有状态的函数,可以方便很多,这里听起来好像有点抽象,后面看我代码就知道了

      总之这题 就是在制作一个简单的倒计时上,增加功能,注意细节减少bug就可以了。基础功能的实现是比较容易的

    3.项目结构

    3.1 函数结构与全局变量

    //时间
    int hour = 0;
    int minute = 1;
    int second = 5;
    //存储位置标志位
    int storage_flag=1;
    //状态数组和数组对应标志位以及当前状态
    //其实这四个状态也可以封装成数组,但是我不想弄了
    char *status[4] = {"Running","Pause","Standby","Setting"};
    int status_flag = 2;
    int is_standby = 1;
    int is_setting = 0;
    int is_start = 0;
    int is_pause = 0;
    
    //暂停和启动标志位(都是短按,所以标志位控制)
    int pause_start_flag = 1;
    //倒计时到了标志
    int alarm_flag;
    //led标志
    int led1_flag;
    //显示区
    char NO_Disp[26];
    char Time_Disp[26];
    char Status_Disp[26];
    //按键延时标志
    int button2_delay=0;
    int button3_delay=0;
    int button4_delay=0;
    //改变时还是分还是秒
    int set_time_mode=0;
    //显示函数
    void Countdown_Display();
    //倒计时控制
    void Countdown_Time_Control();
    //总按键控制
    void Key_Control();
    //KEY2:设置选择时分秒控制
    void Setting();
    //下划线
    void Draw_Under_line(int mode);
    //KEY3:设置时间
    void Time_Setting(int mode);
    //KEY4:定时器状态控制
    void Timer_State_Control();
    //LED控制
    void Led_Control();
    //状态控制(主要为了方便)
    void Status_Control(int status_flag);
    //读和存数据的东西
    uint8_t Read_Data(uint8_t address);
    void Write_Data(unsigned char address,unsigned char info);
    void Read_Time(int storage_flag);
    void Storage_Time(int storage_flag);
    

    3.2 倒计时基础实现

    这里就是之前说的 设置模式和正常时的两种情况要区分开,你肯定不希望设置倒计时的时候被进位什么的影响吧

    void Countdown_Time_Control()
    {
    	if(is_setting==1)
    	{
    		if(hour>24){hour=0;}
    		if(minute>60) {minute=0;}
    		if(second>60) {minute=0;}
    	}
    	if(is_setting==0)
    	{
    		if(second==0)
    		{
    			if(minute>0)
    			{
    				minute-=1;
    				second = 60;
    			}
                //总不能minute为0了还继续减少分钟吧哈哈
    			else
    			{
    				second=0;
    			}
    		}
    		if(minute==0)
    		{
    			if(hour>1)
    			{
    				hour-=1;
    				minute = 60;
    			}
    			else
    			{
    				minute=0;
    			}
    		}
    	}
        //时间到!!!
    	if(minute==0 && second == 0 && hour==0)
    	{
    		alarm_flag = 1;
    		if(is_setting==0)
    		{
                //2状态对应之前数组的第三个元素 Standby,在status_control里会处理
    			status_flag = 2;
    			Status_Control(status_flag);
    		}
    	}
    }
    

    systick中断,这些写完可以先试一下,看看最基础的倒计时能不能做到了

    void SysTick_Handler(void)
    {
    	TimingDelay--;
    	//一秒倒计时
    	if(++Time_Flag==1000)
    	{
    		//限定只有运行的时候倒计时能走
    		if(alarm_flag==0 && is_setting==0 && is_standby==0 && is_pause==0)
    		{
    			second--;
    		}
    		Time_Flag=0;
    	}
    	if(++Led_Delay==500)
    	{
    		led1_flag = !led1_flag;
    		Led_Delay = 0;
    	}
    }
    

    3.3 方便的状态控制函数

    因为我们每次切换状态的时候,都要把当前状态置1,其他置0,每次都写4行太麻烦了,这里直接封装

    而在我的LCD显示函数里,显示的那个状态也会由status的数组,传入status_flag达到同步显示的效果

    void Status_Control(int status_flag)
    {
    	if(status_flag==0)
    	{
    		is_standby = 0;
    		is_setting = 0;
    		is_start = 1;
    		is_pause = 0;
    	}
    	if(status_flag==1)
    	{
    		is_standby = 0;
    		is_setting = 0;
    		is_start = 0;
    		is_pause = 1;
    	}
    	if(status_flag==2)
    	{
    		is_standby = 1;
    		is_setting = 0;
    		is_start = 0;
    		is_pause = 0;
    	}
    	if(status_flag==3)
    	{
    		is_standby = 0;
    		is_setting = 1;
    		is_start = 0;
    		is_pause = 0;
    	}
    }
    

    3.4 按键总控结构

    void Key_Control()
    {
    	char key = KEY_Scan();
    	switch(key)
    	{
            //切换存储的时间
    		case '1':
                //切换存储位
    			storage_flag++;
    			if(storage_flag>5){  storage_flag=1;  }
                //改变状态
    			Status_Control(storage_flag);
                //读取该位置存储时间
    			Read_Time(storage_flag);
    			break;
            //设置选择的时分秒
    		case '2':
    			Setting();
    			break;
            //改变时分秒,set_time_mode在按键2里会改变
            //后续马上让大家看
    		case '3':
    			Time_Setting(set_time_mode);
    			break;
            //定时器的状态控制
    		case '4':
    			Timer_State_Control();
    			break;
    	}
    }
    

    3.5 KEY2的设置功能

    前面大家看到了Setting函数 那么我们看看他的实现体

    void Setting()
    {
    	char key = KEY_Scan();
        //去看对应数组的参量哈
        //更新定时器状态
    	status_flag=3;
    	Status_Control(status_flag);
    	//长短按的实现
    	if(KEY2==0)
    	{
    		button2_delay++;
    		//短按
    		if(button2_delay==1)
    		{
    			alarm_flag = 0;
                //三个模式 其实就是时分秒,后面该变量交付给KEY3控制
    			set_time_mode++;
    			if(set_time_mode>3)
    			{
    				set_time_mode=1;
    			}
                //靠下划线让我们方便识别设置的时分秒
    			Draw_Under_line(set_time_mode);
    		}	
            //长按
    		if(button2_delay>=4)
    		{
                //确认松手,这个很重要,不然可能退出了马上外面扫描到key2
                //然后又进入了设置函数,烦得很,大家想想
    			while(KEY2==0)
    			//存储当前数据位置 报警置0(因为有可能定时器时间到了然后我们设置时间)
    			alarm_flag = 0;
                //存储
    			Storage_Time(storage_flag);
                //清除所有下划线
    			LCD_SetTextColor(White);
    			LCD_DrawLine(120,280,250,Horizontal);
    			LCD_SetTextColor(Black);
                //更新状态
    			status_flag=2;
    			Status_Control(status_flag);
    			return;
    		}
    	}
    	else
    	{
    			button2_delay=0;
    	}
    
    }
    

    下划线的绘制函数没什么好说的,慢慢试坐标就是了,然后根据传入的参数分成三个if语句就可以了,这里就不展示了

    3.6 KEY3的设置时间功能

    void Time_Setting(int mode)
    {
        //注意到这里哈,这就是前面说的那些小细节
        //与上is_setting,保证只有设置时间的时候key3起作用
    	if(KEY3==0 && is_setting)
    	{
    		button3_delay++;
    		//短按
    		if(button3_delay==1)
    		{
    			if(mode==1){hour++;}
    			if(mode==2){minute++;}
    			if(mode==3){second++;}
    		}
    		//长按
    		if(button3_delay>=10)
    		{
    			if(mode==1){hour++;}
    			if(mode==2){minute++;}
    			if(mode==3){second++;}
    		}
    	}
    	else
    	{
    		button3_delay=0;
    	}
    	
    }
    

    3.7 KEY4的状态设置功能

    void Timer_State_Control()
    {
        //清除下划线(也是小细节处理)
    	LCD_SetTextColor(White);
    	LCD_DrawLine(120,280,250,Horizontal);
    	LCD_SetTextColor(Black);
        //报警先清0,不然会被之前状态影响
    	alarm_flag = 0;
    	if(KEY4==0)
    	{
    		button4_delay++;
            //短按
    		if(button4_delay==1)
    		{
                //暂停和开始的转化
    			if(pause_start_flag==1)
    			{
                    //一如既往调用这两行更新状态
    				status_flag=0;
    				Status_Control(status_flag);
    				pause_start_flag=!pause_start_flag;
    			}
    			else if(pause_start_flag==0)
    			{
    				status_flag=1;
    				Status_Control(status_flag);
    				pause_start_flag=!pause_start_flag;
    			}
    		}
            //长按
    		if(button4_delay==10)
    		{
    			status_flag=2;
    			Status_Control(status_flag);
    		}
    	}
    	else
    	{
    		button4_delay=0;
    	}
    }
    

    LED和Pwm的控制就太简单拉, is_start这个变量为1的时候才能使用就行了。其他时候就关闭 easy~。这里也不放了

    3.8 存储部分

    其实也很简单,分五个存储时间的地方就行了,注意地址不要重复

    void Storage_Time(int storage_flag)
    {
    	if(storage_flag==1)
    	{
    		Write_Data(0x10,hour);    Delay_Ms(2);
    		Write_Data(0x11,minute);  Delay_Ms(2);
    		Write_Data(0x12,second);  Delay_Ms(2);
    	}
    	if(storage_flag==2)
    	{
    		Write_Data(0x20,hour);    Delay_Ms(2);
    		Write_Data(0x21,minute);  Delay_Ms(2);
    		Write_Data(0x22,second);  Delay_Ms(2);
    	}
    	if(storage_flag==3)
    	{
    		Write_Data(0x30,hour);    Delay_Ms(2);
    		Write_Data(0x31,minute);  Delay_Ms(2);    
    		Write_Data(0x32,second);  Delay_Ms(2);
    	}
    	if(storage_flag==4)
    	{
    		Write_Data(0x40,hour);    Delay_Ms(2);
    		Write_Data(0x41,minute);  Delay_Ms(2);
    		Write_Data(0x42,second);  Delay_Ms(2);
    	}
    	if(storage_flag==5)
    	{
    		Write_Data(0x50,hour);    Delay_Ms(2);
    		Write_Data(0x51,minute);  Delay_Ms(2);
    		Write_Data(0x52,second);  Delay_Ms(2);
    	}
    }
    

    存值的地方很简单,取值的地方倒是要注意,因为可能存在不是你的板子取到垃圾值的情况,所以我们可以这么做

    当 取到的值 不在规定范围内的时候,我们先往里面写入一次值就好了

    void Read_Time(int storage_flag)
    {
    	if(storage_flag==1)
    	{
    		hour = Read_Data(0x10);    Delay_Ms(2);
    		minute = Read_Data(0x11);  Delay_Ms(2);
    		second = Read_Data(0x12);  Delay_Ms(2);
    		if(hour>24 || hour<0){ hour=0; }
    		if(minute>60 || minute<0){ minute=1; }
    		if(second>60 || second<0){ second=10; }
            Storage_Time(1);
    	}
    	if(storage_flag==2)
    	{
    		hour = Read_Data(0x20);    Delay_Ms(2);
    		minute = Read_Data(0x21);  Delay_Ms(2);
    		second = Read_Data(0x22);  Delay_Ms(2);
    		if(hour>24 || hour<0){ hour=0; }
    		if(minute>60 || minute<0){ minute=0; }
    		if(second>60 || second<0){ second=30; }
             Storage_Time(2);
    	}
    	if(storage_flag==3)
    	{
    		hour = Read_Data(0x30);    Delay_Ms(2);
    		minute = Read_Data(0x31);  Delay_Ms(2);
    		second = Read_Data(0x32);  Delay_Ms(2);
    		if(hour>24 || hour<0){ hour=0; }
    		if(minute>60 || minute<0){ minute=1; }
    		if(second>60 || second<0){ second=10; }
             Storage_Time(3);
    	}
    	if(storage_flag==4)
    	{
    		hour = Read_Data(0x40);    Delay_Ms(2);
    		minute = Read_Data(0x41);  Delay_Ms(2);
    		second = Read_Data(0x42);  Delay_Ms(2);
    		if(hour>24 || hour<0){ hour=1; }
    		if(minute>60 || minute<0){ minute=2; }
    		if(second>60 || second<0){ second=30; }
            Storage_Time(4);
    	}
    	if(storage_flag==5)
    	{
    		hour = Read_Data(0x50);    Delay_Ms(2);
    		minute = Read_Data(0x51);  Delay_Ms(2);
    		second = Read_Data(0x52);  Delay_Ms(2);
    		if(hour>24 || hour<0){ hour=0; }
    		if(minute>60 || minute<0){ minute=5; }
    		if(second>60 || second<0){ second=20; }
            Storage_Time(5);
    	}
    }
    
    

    3.9 主函数

    	//省略初始化
    	//读取值,默认storage_flag==1
    	Read_Time(storage_flag);
    	while(1)
    	{
            //LED
    		Led_Control();
            //按键控制
    		Key_Control();
            //显示
    		Countdown_Display();
           	//时间逻辑校验
    		Countdown_Time_Control();
    	}
    

    细节的坑真的多,可能代码还是有小bug,但是我感觉应该大部分都还ok了。希望我和大家代码能力越来越优秀呀!!!

    下题见。
    以下是源码,欢迎大家反馈bug 源码

    更多相关内容
  • 蓝桥杯嵌入式第九届省赛_电子定时器_工程代码,已实现题目所有要求,打开直接运行即可,压缩包内是完整的工程文件,希望能够帮助到大家。
  • 蓝桥杯开发板的基本模块已经玩的差不多了,接下来就拿第九届题练一下手。 算是解决了长短按键,解决了高亮显示 先看一下第九届试题的题目和硬件框图。题目就是“电子定时器”。 硬件框图如下 作者:little_...
  • 内含题目以及本人的解题程序,内容较好理解,如有疑问可以联系我,本资源适用于蓝桥杯嵌入式备考的人,也适用于初学stm32的人
  • 一部分 客观试题(15分) 1)在STM32系列微控制器中,可以作为主时钟MCO输出的时钟源是( )。 A. HSI B. HSE C. SYSCLK D. HSE/2 2)三态门的输出状态包括( )。 A.高电平 B.低电平 C.模拟输出 D.高阻态 ...
  • 蓝桥杯嵌入式真题第九届省赛-客观题-答案解析,详情可参考我的博客https://blog.csdn.net/demon_xi/article/details/109254453
  • 蓝桥杯嵌入式第九届省赛-电子定时器
  • 内含题目以及本人的解题程序,内容较好理解,如有疑问可以联系我,本资源适用于蓝桥杯嵌入式备考的人,也适用于初学stm32的人
  • 蓝桥杯嵌入式国赛第九届 源码 电子秤
  • 蓝桥杯嵌入式——第九届蓝桥杯嵌入式国赛 目录蓝桥杯嵌入式——第九届蓝桥杯嵌入式国赛一、赛题二、CubeMX模块配置三、部分模块代码四、完整代码下载 一、赛题 话不多说,这一的赛题题量适中,考察的东西中规中规...

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

    一、赛题

    话不多说,这一届的赛题题量适中,考察的东西中规中规,没有什么需要特别注意的,比十一届的难一些,但是比第十届的要简单一点。考察的内容如下:

    LED,闪烁
    LCD,LCD的高亮显示
    ADC按键
    双通道ADC转换(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. 串口的配置
      在这里插入图片描述

    三、部分模块代码

    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(((select == 0 && Line == Line2) || (select == 1 && Line == Line4) || (select == 2 && Line == Line6)) && i == 2)
    			LCD_SetBackColor(Green);
    		else if(((select == 0 && Line == Line2) || (select == 1 && Line == Line4) || (select == 2 && Line == Line6)) && i == 18)
    			LCD_SetBackColor(Black);
    		
    		LCD_DisplayChar(Line, refcolumn, *ptr);
    		refcolumn -= 16;
    		ptr++;
    		i++;
    	}
    }
    
    1. ADC按键
      这里我使用的是三行按键的检测方法,不清楚三行按键检测可以看我的另一篇博客,https://blog.csdn.net/qq_43715171/article/details/113004685
      由于开启了ADC的DMA,每一次ADC转换完成数据都会存放到存储器adc_value中,其中电位器对应通道的数据存放在adc_value[0]中,ADC按键存放在adc_value[1]中。
      key_refresh()就是按键检测,检测当前的按键状态。每10ms调用一次key_scan()函数,在key_scan()里面调用了key_refresh()来获取当前的按键状态,key_scan的最后一部分代码是有关按键的长按的实现,不清楚的也可以去看我的上一篇博客,第十一届蓝桥杯嵌入式的那一章,里面有讲。
    
    uint8_t key_falling = 0;
    uint8_t key_state = 0;
    
    extern uint16_t adc_value[];
    	
    void key_refresh(void)
    {
    	uint8_t key_temp = 0xFF;
    	if(adc_value[1] < 100)
    		key_temp &= (~0x01);
    	else if(adc_value[1] < 800)
    		key_temp &= (~0x02);
    	else if(adc_value[1] < 1300)
    		key_temp &= (~0x04);
    	else if(adc_value[1] < 2000)
    		key_temp &= (~0x08);
    	else if(adc_value[1] < 2500)
    		key_temp &= (~0x10);
    	else if(adc_value[1] < 3200)
    		key_temp &= (~0x20);
    	else if(adc_value[1] < 3600)
    		key_temp &= (~0x40);
    	else if(adc_value[1] < 4000)
    		key_temp &= (~0x80);
    	key_temp ^= 0xFF;
    	key_falling = (key_temp) & (key_temp ^ key_state);
    	key_state = key_temp;
    }
    
    void key_scan(void)
    {
    	static uint8_t key_scan_cnt = 0;
    	
    //	if(key_flag)
    //	{
    		key_flag = 0;
    		key_refresh();
    		if(key_falling == 0x01)
    		{
    			if(interface == DATA)
    			{
    				interface = PARA;
    				select = 0;
    			}
    			else
    			{
    				interface = DATA;
    				if(items_temp[0] != items_temp_pre[0] || items_temp[1] != items_temp_pre[1] || items_temp[2] != items_temp_pre[2])
    				{
    					items_temp_pre[0] = items_temp[0];
    					items_temp_pre[1] = items_temp[1];
    					items_temp_pre[2] = items_temp[2];
    					items[0].unit_price = items_temp[0] * 0.01;
    					items[1].unit_price = items_temp[1] * 0.01;
    					items[2].unit_price = items_temp[2] * 0.01;
    					setting_times++;
    					eeprom_write_flag = 1;
    				}
    				printf("U.W.1 : %.2f\r\n",items[0].unit_price);
    				printf("U.W.2 : %.2f\r\n",items[1].unit_price);
    				printf("U.W.3 : %.2f\r\n",items[2].unit_price);
    			}
    		}
    		else if(key_falling == 0x02 && interface == PARA)
    		{
    			if(select == 0)
    			{
    				if(items_temp[0] < 1000)
    					items_temp[0]++;
    			}
    			else if(select == 1)
    			{
    				if(items_temp[1] < 1000)
    					items_temp[1]++;
    			}
    			else if(select == 2)
    			{
    				if(items_temp[2] < 1000)
    					items_temp[2]++;
    			}
    		}
    		else if(key_falling == 0x04 && interface == PARA)
    		{
    			if(select == 0)
    			{
    				if(items_temp[0] > 0)
    					items_temp[0]--;
    			}
    			else if(select == 1)
    			{
    				if(items_temp[1] > 0)
    					items_temp[1]--;
    			}
    			else if(select == 2)
    			{
    				if(items_temp[2] > 0)
    					items_temp[2]--;
    			}
    		}
    		else if(key_falling == 0x08 && interface == PARA)
    		{
    			select = (select + 1) % 3;
    		}
    		else if(key_falling == 0x10)
    		{
    			number = 0;
    		}
    		else if(key_falling == 0x20)
    		{
    			number = 1;
    		}
    		else if(key_falling == 0x40)
    		{
    			number = 2;
    		}
    		else if(key_falling == 0x80)
    		{
    			printf("U.W.%d:%.2f\r\n",select,items[number].unit_price);
    			printf("G.W:%.2f\r\n",items[number].weight);
    			printf("Total:%.2f\r\n",items[number].weight * items[number].unit_price);
    		}
    //	}
    		if(key_state == 0x02 && interface == PARA && ++key_scan_cnt == 80)
    		{
    			key_scan_cnt = 75;
    			if(select == 0)
    			{
    				if(items_temp[0] < 1000)
    					items_temp[0]++;
    			}
    			else if(select == 1)
    			{
    				if(items_temp[1] < 1000)
    					items_temp[1]++;
    			}
    			else if(select == 2)
    			{
    				if(items_temp[2] < 1000)
    					items_temp[2]++;
    			}
    		}
    		else if(key_state == 0x04 && interface == PARA && ++key_scan_cnt == 80)
    		{
    			key_scan_cnt = 75;
    			if(select == 0)
    			{
    				if(items_temp[0] > 0)
    					items_temp[0]--;
    			}
    			else if(select == 1)
    			{
    				if(items_temp[1] > 0)
    					items_temp[1]--;
    			}
    			else if(select == 2)
    			{
    				if(items_temp[2] > 0)
    					items_temp[2]--;
    			}
    		}
    		if(key_state == 0)
    		{
    			key_scan_cnt = 0;
    		}
    }
    
    
    1. printf的重定向
    int fputc(int ch,FILE *l)
    {
    	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFF);
    	return ch;
    }
    

    四、完整代码下载

    代码使用说明,一定要看

    完整代码下载点我

    展开全文
  • 蓝桥杯嵌入式第九届省赛-客观题之答案解析 致谢 学习蓝桥杯嵌入式 推荐一个up主,电子设计工坊,讲解很细,小编也是通过他的视频学习。 同时感谢我的小伙伴乐观的LISHAN提供技术支持,大佬链接具体讲解了如何编程...

    蓝桥杯嵌入式第九届省赛-客观题之答案解析

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

    致谢

    学习蓝桥杯嵌入式 推荐一个up主,电子设计工坊,讲解很细,小编也是通过他的视频学习。 同时感谢我的小伙伴乐观的LISHAN提供技术支持,大佬链接具体讲解了如何编程的细节问题!!!如果觉得图片模糊的小伙伴可私聊小编!

    展开全文
  • 蓝桥杯嵌入式比赛-经验分享视频(第九届
  • 蓝桥杯第九届嵌入式省赛试题“电子定时器”带客观题程序题。
  • 蓝桥杯第九届 省赛 嵌入式试题资料。 包含试题、模板和各类工具软件。
  • 蓝桥杯省赛第九届真题(程序题答案),功能已全部实现,都是用比较简单的方法编写的,适合初学者,最关键的莫过于i2c的存储和时钟,都已经写全,欢迎大家提出自己的看法。
  • 本压缩包包含第九届嵌入式蓝桥杯决赛试卷及答案,程序为本人参考资料所写,基本上是原创;不喜勿喷;仅供参考。
  • 届蓝桥杯嵌入式 这一的蓝桥杯省题他的用到的外设相对于来说还是比较多的,有用到ADC、EEPROM、USART、led、key这些外设,可以说除了没用到PWM、蜂鸣器之外,蓝桥杯嵌入式的考点涉及的外设大多都包含在里面了。...

    第七届蓝桥杯嵌入式

    这一届的蓝桥杯省题他的用到的外设相对于来说还是比较多的,有用到ADC、EEPROM、USART、led、key这些外设,可以说除了没用到PWM、蜂鸣器之外,蓝桥杯嵌入式的考点涉及的外设大多都包含在里面了。可以说也是比较齐全了,不过我们也不要给自己太大的压力,把基本的配置学会了,main函数编写起来难度也不是很大的。
    在这里插入图片描述

    第七届题目要求是模拟液位警报系统,要求通过模拟电压信号(ADC)计算他液位高度,并在液位等级发生变化的时候通过串口发送到PC机上。

    下面我们看看具体的要求。
    1.液位高度、ADC的分析
    在这里插入图片描述
    这里说明了液位的高度是由H=Vr37*K公式得出,并且当我们模拟电压为3.3时,高度为100.然后我们可以发现这个图片ADC=1.65V时,高度=50,即可推导出K约等于30.3。知道了这些参数就可以计算他的高度了。

    2.液位等级的判定
    在这里插入图片描述
    3.按键的设定
    在这里插入图片描述
    这里四个按键说明:
    B1:是参数界面和设定界面的切换
    B2:是在设定界面上切换阈值并凸显位置(即为高亮)
    B3:是在相对应的阈值中,进行阈值的加运算,按下一次+5,直至95为止
    B4:是在相对应的阈值中,进行阈值的减运算,按下一次-5,直至5为止

    4.串口的设置
    在这里插入图片描述
    串口要求主要为查询和输出:
    查询:
    当我们串口从PC机上接受到字符“C“时,串口打印当前的液位高度和液位等级。
    当我们串口从PC机上接受到字符“S“时,串口打印当前三个阈值的大小参数。
    输出:
    当我们检测到我们液位等级发生变化(上升或下降)的时候串口打印当前的液位高度和液位等级,并告知是上升或下降。

    5、led设置
    在这里插入图片描述
    led没啥好说的,赛题分析完了,还是看代码部分吧

    代码

    1.main

    
    #include "stm32f10x.h"
    #include "stdio.h"
    #include "led.h"
    #include "i2c.h"
    #include "key.h"
    #include "adc.h"
    #include "usart.h"
    #include "string.h"
    #include "lcd.h"
    
    u32 TimingDelay = 0;
    u32 LD2_delay=0;
    	u32 LD3_delay=0;
    	unsigned char i=0;
    u8 RXBUF[20];   //串口数组
    u8 RXCUNT=0;   //计数位
    u8 RXOVER=0;     //标志位
    
    unsigned char key_val;   //按键存储值
    unsigned int adc_val;    //adc存储值
    unsigned char i2c_val;   //i2c存储值
    unsigned char chun_chu[20];   
    unsigned char H;               //等级比较         
    unsigned char B1=0;           //界面切换
    unsigned char B2=0;          //高亮切换
    unsigned char level;          //液位等级
    float hight=30.3;        //K值
    unsigned char Threshold1=30;   //阈值1
    unsigned char Threshold2=50;
    unsigned char Threshold3=70;
    unsigned char LD2_l;       //下降标志
    unsigned char LD2_h;        //上升标志
    unsigned char usart_LD3;   //串口发送标志
    
    
    void lcd_caozuo()
    {
      if(B1==0)     //参数界面
    	{
    		
    		adc_val=adc_scanf(); //读取adc的值
    	  LCD_DisplayStringLine(Line1,"      Liquid Level   ");
    		if((float)adc_val*3.3/4095!=3.3)  
    		{
    		  sprintf((char *)chun_chu,"     Height:%2ucm      ",(int)(((float)adc_val*3.3/4095)*hight));   //液位高度的计算公式
    		  LCD_DisplayStringLine(Line3,chun_chu);
    		}
    		else if((float)adc_val*3.3/4095==3.3)
    		{
    		  LCD_DisplayStringLine(Line3,"     Height:100cm      ");
    		}
    		
    		sprintf((char *)chun_chu,"     ADC:%4.2fV        ",(float)adc_val*3.3/4095);   //ADC的值
    		LCD_DisplayStringLine(Line5,chun_chu);
    		
    		if((int)(((float)adc_val*3.3/4095)*hight)<=Threshold1)   //当液位等级为0
    		{
    		  level=0;
    			sprintf((char *)chun_chu,"     Level:%1u       ",level);
    			LCD_DisplayStringLine(Line7,chun_chu);
    			if(H>level)  //下降
    			{
    			 LD2_l=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+D\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);   //打印液位高度、等级和变化趋势
    				USART_SendString(USART2,RXBUF);
    			}
    			H=0;     //重新赋值
    			
    		}
    		if(Threshold1<(int)(((float)adc_val*3.3/4095)*hight)&&(int)(((float)adc_val*3.3/4095)*hight)<=Threshold2)//等级1
    		{
    		   level=1;
    			sprintf((char *)chun_chu,"     Level:%1u       ",level);
    			LCD_DisplayStringLine(Line7,chun_chu);
    			if(H>level)//下降
    			{
    			  LD2_l=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+D\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			if(H<level)  //上升
    			{
    			  LD2_h=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+U\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			H=1;
    		}
    		if(Threshold2<(int)(((float)adc_val*3.3/4095)*hight)&&(int)(((float)adc_val*3.3/4095)*hight)<=Threshold3)  //等级2
    		{
    		   level=2;
    			sprintf((char *)chun_chu,"     Level:%1u       ",level);
    			LCD_DisplayStringLine(Line7,chun_chu);
    			if(H>level)
    			{
    			  LD2_l=1;  //下降
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+D\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			if(H<level)  //上升
    			{
    			  LD2_h=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+U\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			H=2;
    		}
    		if((int)(((float)adc_val*3.3/4095)*hight)>Threshold3)
    		{
    		  level=3;
    			sprintf((char *)chun_chu,"     Level:%1u       ",level);
    			LCD_DisplayStringLine(Line7,chun_chu);
    			if(H>level)
    			{
    			  LD2_l=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+D\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			if(H<level)  
    			{
    			  LD2_h=1;
    				sprintf((char *)RXBUF,"A:H%2u+L%1u+U\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);
    			}
    			H=3;
    		}
    	}
    	if(B1==1)   //阈值设定切面
    	{
    	  LCD_DisplayStringLine(Line1,"    Parameter Setup   ");
    		
    		i2c_write(0x01,Threshold3+Threshold2+Threshold1); //eeprom保存
    		Delay_LCD(30);
    		i2c_val=i2c_read(0x01);
    		if(B2==0)//不高亮
    		{
    		  i2c_val=Threshold1;
    		  sprintf((char *)chun_chu,"   Threshold1:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line3,chun_chu);
    			
    			i2c_val=Threshold2;
    		  sprintf((char *)chun_chu,"   Threshold2:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line5,chun_chu);
    			
    			i2c_val=Threshold3;
    		  sprintf((char *)chun_chu,"   Threshold3:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line7,chun_chu);
    			
    			LCD_DisplayStringLine(Line9,"            ");
    		}
    		if(B2==3)//第三行高亮
    		{
    			LCD_SetBackColor(Yellow);
    		  i2c_val=Threshold1;
    		  sprintf((char *)chun_chu,"   Threshold1:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line3,chun_chu);
    			LCD_SetBackColor(Blue);
    			
    			i2c_val=Threshold2;
    		  sprintf((char *)chun_chu,"   Threshold2:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line5,chun_chu);
    			
    			i2c_val=Threshold3;
    		  sprintf((char *)chun_chu,"   Threshold3:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line7,chun_chu);
    			
    			LCD_DisplayStringLine(Line9,"            ");
    		}
    		if(B2==5)  //第五行高亮
    		{
    
    		  i2c_val=Threshold1;
    		  sprintf((char *)chun_chu,"   Threshold1:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line3,chun_chu);
    		
    			LCD_SetBackColor(Yellow);
    			i2c_val=Threshold2;
    		  sprintf((char *)chun_chu,"   Threshold2:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line5,chun_chu);
    			LCD_SetBackColor(Blue);
    			
    			i2c_val=Threshold3;
    		  sprintf((char *)chun_chu,"   Threshold3:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line7,chun_chu);
    			
    			LCD_DisplayStringLine(Line9,"            ");
    		}
    		if(B2==7)  //第七行高亮
    		{
    
    		  i2c_val=Threshold1;
    		  sprintf((char *)chun_chu,"   Threshold1:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line3,chun_chu);
    		
    			
    			i2c_val=Threshold2;
    		  sprintf((char *)chun_chu,"   Threshold2:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line5,chun_chu);
    			
    			LCD_SetBackColor(Yellow);
    			i2c_val=Threshold3;
    		  sprintf((char *)chun_chu,"   Threshold3:%2ucm        ",i2c_val);
    		  LCD_DisplayStringLine(Line7,chun_chu);
    			LCD_SetBackColor(Blue);
    			
    			LCD_DisplayStringLine(Line9,"            ");
    		}
    			
    	}
    }
    
    void key_caozuo(void)
    {
      key_val=key_scanf();  //读取按键值
    	if(key_val==1)   //B1按下
    	{
    	  switch(B1)  //界面切换
    		{
    		  case 0:B1=1;break;
    			case 1:B1=0;break;
    		}
    	}
    	if(key_val==2)  //B2按下
    	{
    		if(B1==1)  //在阈值界面下有效
    		{
    		  switch(B2)  //高亮切换
    		 {
    		   case 0:B2=3;break;
    			 case 3:B2=5;break;
    			 case 5:B2=7;break;
    			 case 7:B2=0;break;
    		 }
    		}
    	if(key_val==3)  //B3按下
    	{
    	  if(B1==1)  //在阈值界面下有效
    		{
    		  if(B2==3)  //第三行高亮
    			{
    			  if(Threshold1!=95)  //+5
    					Threshold1=Threshold1+5;
    			}
    			if(B2==5)//第5行高亮
    			{
    			  if(Threshold2!=95)
    					Threshold2=Threshold2+5;
    			}
    			if(B2==7)//第7行高亮
    			{
    			  if(Threshold3!=95)
    					Threshold3=Threshold3+5;
    				
    			}
    		}
    	}
    	if(key_val==4)  //B4按下
    	{
    	  if(B1==1)   //在阈值界面下有效
    		{
    		  if(B2==3)
    			{
    			  if(Threshold1!=5)
    					Threshold1=Threshold1-5;
    				
    			}
    			if(B2==5)
    			{
    			  if(Threshold2!=5)
    					Threshold2=Threshold2-5;
    				
    			}
    			if(B2==7)
    			{
    			  if(Threshold3!=5)
    					Threshold3=Threshold3-5;
    			
    			}
    		}
    	}
    }
    //Main Body
    int main(void)
    {
    	SysTick_Config(72000);
    
    	
    	STM3210B_LCD_Init();
    	LCD_Clear(Blue);
    	LCD_SetBackColor(Blue);
    	LCD_SetTextColor(White);
    	
    	i2c_init();
    	led_init();
    	key_init();
    	adc_init();
    	USART2_Init(9600);
    	
    	
    	while(1)
    	{
    		lcd_caozuo();
    		key_caozuo();
    		
    	 if(RXOVER==1)    //串口接收处理
    		{
    			RXOVER=0;   //标志位清零
    			usart_LD3=0;  //标志位
    			USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);
    		 if(RXBUF[0]=='C')  //接收到“C”打印,并串口LD3=1;
    			{
    				usart_LD3=1;
    			  sprintf((char *)RXBUF,"C:H%2u+L%1u\r\n",(int)(((float)adc_val*3.3/4095)*hight),level);
    				USART_SendString(USART2,RXBUF);	
    			}
    			if(RXBUF[0]=='S')
    			{
    				usart_LD3=1;
    			  sprintf((char *)RXBUF,"S:TL%2u+TM%2u+TH%2u\r\n",Threshold1,Threshold2,Threshold3);
    				USART_SendString(USART2,RXBUF);	
    			
    			}
          memset(RXBUF,'\0',sizeof(RXBUF));   //清空数组
    			
    		}
    	}
    }
    
    //
    
    void SysTick_Handler(void)
    {
    	
    	led_init();
    	TimingDelay++;
    	if(TimingDelay<900)
    		led_scanf(0,led0);
    	if(TimingDelay==1000)
    		TimingDelay=0;
    	if(TimingDelay>900)
    		led_scanf(1,led0);
    	
    	if(LD2_l==1||LD2_h==1)
    	{
    		LD2_delay++;
    		for(i=0;i<5;i++)
    		{
    		 
    		if(LD2_delay<100)
    			led_scanf(0,led1);
    		if(LD2_delay==200)
    			LD2_delay=0;
    		if(LD2_delay>100)
    			led_scanf(1,led1);
    		}
    	  
    	}
    	if(usart_LD3==1)
    	{
    		 LD3_delay++;
    	  for(i=0;i<5;i++)
    		{
    		
    		if(LD3_delay<100)
    			led_scanf(0,led2);
    		if(LD3_delay==200)
    			LD3_delay=0;
    		if(LD3_delay>100)
    			led_scanf(1,led2);
    		}
    	}
    }
    
    
    

    2.usart

    #include "usart.h"
    
    extern u8 RXBUF[20];
    extern u8 RXCUNT;   //½ÓÊܼÆÊý
    extern u8 RXOVER;     //±ê־λ
    
    
    void USART2_Init(unsigned long ulBaud)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
      USART_InitTypeDef USART_InitStruct;
      NVIC_InitTypeDef NVIC_InitStruct;
      
    
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
      
    
      GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_Init(GPIOA, &GPIO_InitStruct);
      
    
      GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
      GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStruct); 
      
    
      USART_InitStruct.USART_BaudRate = ulBaud;
      USART_InitStruct.USART_WordLength = USART_WordLength_8b;
      USART_InitStruct.USART_StopBits = USART_StopBits_1;
      USART_InitStruct.USART_Parity = USART_Parity_No;
      USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_InitStruct.USART_HardwareFlowControl= USART_HardwareFlowControl_None;//Ó²¼þ¿ØÖÆÁ÷£¬Ò»°ãÑ¡ÔñNone
      USART_Init(USART2, &USART_InitStruct);
      
    	// ÔÊÐíUSART2
      USART_Cmd(USART2, ENABLE);
      
    	// ÔÊÐíUSART2½ÓÊÕÖжÏ
      USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);	
      
    	// ÔÊÐíNVIC USART2ÖжÏ
      NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;//ÖжÏͨµÀΪUSART2
      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//ÏÈÕ¼ÓÅÏȼ¶
      NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//´ÓÓÅÏȼ¶
      NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//ÖжÏʹÄÜ
      NVIC_Init(&NVIC_InitStruct);//³õʼ»¯
    }
    
    unsigned char USART_SendChar(USART_TypeDef* USARTx, unsigned char ucChar)
    {
      while(!USART_GetFlagStatus(USARTx, USART_FLAG_TXE));//²»¶Ï¼ì²é±ê־λ
      USART_SendData(USARTx, ucChar);//·¢ËÍ×Ö·ûÊý¾Ý
      return ucChar;//·µ»Ø·¢Ë͵Ä×Ö·û
    }
    
    
    void USART_SendString(USART_TypeDef* USARTx, unsigned char* pucStr)
    {
      while(*pucStr != '\0')
        USART_SendChar(USARTx, *pucStr++);
    }
    
    
    void USART2_IRQHandler(void)
    {	
    		u8 temp;
    		if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
    		{
    				USART_ClearITPendingBit(USART2,USART_IT_RXNE);
    				temp =  USART_ReceiveData(USART2);
    				if(temp == '\n')
    				{
    						RXCUNT = 0;
    						RXOVER = 1;
    						USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
    				}else
    				{
    						RXBUF[RXCUNT] = temp;
    						RXCUNT++;
    				}
    		}
    }
    
    
    
    

    3.adc

    #include "adc.h"
    
    void adc_init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct;
    	ADC_InitTypeDef ADC_InitStruct;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1,ENABLE);
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);
    	
    	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
    	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
    	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
    	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
    	ADC_InitStruct.ADC_NbrOfChannel=1;
    	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
      ADC_Init(ADC1,&ADC_InitStruct);
    	
    	ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_1Cycles5);
    	
    	ADC_Cmd(ADC1,ENABLE);
    	
    	ADC_StartCalibration(ADC1);
    	
    	while(ADC_GetCalibrationStatus(ADC1));
    }
    
    unsigned int adc_scanf(void)
    {
      ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    	
    	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
    	
    	return ADC_GetConversionValue(ADC1);
    }
    
    
    

    4.key

    #include "key.h"
    #include "lcd.h"
    
    void key_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruct);
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);	
      
      
    }
    
    unsigned char key_scanf(void)
    {
      unsigned char key_but=0;
    	if(key0==0||key1==0||key2==0||key3==0)
    	{
    		Delay_LCD(100);
    	  if(key0==0) key_but=1;
    		if(key1==0) key_but=2;
    		if(key2==0) key_but=3;
    		if(key3==0) key_but=4;
    	}
    	return key_but;
    }
    
    

    5.led

    #include "led.h"
    
    void led_init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    	GPIO_InitStruct.GPIO_Pin=led0|led1|led2|led3|led4|led5|led6|led7;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOC,&GPIO_InitStruct);
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOD,&GPIO_InitStruct);	
    	
    	GPIO_SetBits(GPIOD,GPIO_Pin_2);
    	GPIO_SetBits(GPIOC,ledall);	
    	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
    }
    
    void led_scanf(unsigned char mode,unsigned int led)
    {
    	if(mode==0)//Èç¹ûstate==0
    	{
    		GPIO_SetBits(GPIOD,GPIO_Pin_2);//PD2Êä³ö¸ßµçƽ
    		GPIO_ResetBits(GPIOC,led);//ledÊä³öµÍµçƽ
    		GPIO_ResetBits(GPIOD,GPIO_Pin_2);//PDÊä³öµÍµçƽ	
    	}
    	else if(mode==1)//Èç¹ûstate==1
    	{
    		GPIO_SetBits(GPIOD,GPIO_Pin_2);//PD2Êä³ö¸ßµçƽ
    		GPIO_SetBits(GPIOC,led);//ledÊä³ö¸ßµçƽ
    		GPIO_ResetBits(GPIOD,GPIO_Pin_2);//PDÊä³öµÍµçƽ			
    
    	}
    }
    
    
    1. i 2c 这个我就放读和写的程序吧,官方也会给i2c的程序,就只要编写读写就行了。
    unsigned char i2c_read(unsigned char add)
    {
    	unsigned char data;
    	
      I2CStart(); 
    	
      I2CSendByte(0xa0);
      I2CWaitAck(); 
    
      I2CSendByte(add);
      I2CWaitAck(); 
    	
      I2CStart();
      I2CSendByte(0xa1); 
      I2CWaitAck();
    	
    	data=I2CReceiveByte();
    	I2CSendAck();
    	
      I2CStop();
    	
    	return data;
    }
    
    // AT24C02д
    //Èë¿Ú²ÎÊý£ºaddÊǵØÖ·£¬±ÈÈç0x01,0x02µÈµÈ£»dataÊÇдÈëµÄÊý¾Ý£¬ÊÇunsigned charÐÍ
    void i2c_write(unsigned char add,unsigned char data)
    {
      I2CStart(); 
    	
      I2CSendByte(0xa0); 
      I2CWaitAck(); 
    
      I2CSendByte(add);	
      I2CWaitAck();
      
    	I2CSendByte(data);	
      I2CWaitAck();
    	
      I2CStop();
    }
    
    

    在这里插入图片描述

    在这里插入图片描述

    注意:

    在串口接收的时候必须要加一个 memset(RXBUF,’\0’,sizeof(RXBUF));进行对数组的清空操作。另外这个memset函数必须要加上头文件#include "string.h"才有用。

    参加这种动手能力的比赛,大家还是多动手,多去理解才是王道,这样理解更加的深刻。

    祝大家都能得奖。

    展开全文
  • 蓝桥杯嵌入式第省题

    千次阅读 2022-03-23 17:57:38
    这一的省题用到的外设比较多一点,有用到i2c、key、led、usart、rtc、adc。并且考点相对比较全一点,但我们只要会了上述的外设配置,总体的main函数的逻辑代码编写,难度不大。 题目分析 我们接下来看看任务要求:...
  • 蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛

    千次阅读 多人点赞 2021-05-22 13:18:35
    蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛 目录蓝桥杯嵌入式——第十届蓝桥杯嵌入式国赛一、赛题二、CubeMX模块配置三、部分模块代码四、完整代码下载 一、赛题 上一次做了十一的国赛赛题,感觉很容易。然后这两...
  • 这次第九届蓝桥杯的省赛的题比第八省赛的题简单了,但是我在做的时候也有很多小问题导致卡壳,也是将之前学习过的东西在做了一次小复习,同时这次省赛的长短按键也是比第一次接触到,很有收获。本次仍然是基于CT...
  • 内含题目以及本人的解题程序,内容较好理解,如有疑问可以联系我,本资源适用于蓝桥杯嵌入式备考的人,也适用于初学stm32的人
  • 蓝桥杯嵌入式——第十二届蓝桥杯嵌入式第一场省赛 目录蓝桥杯嵌入式——第十二届蓝桥杯嵌入式第一场省赛一、赛题分析二、问题总结三、代码(完整代码,功能全部实现,附有注释) 一、赛题分析 这是刚刚过去的第十二...
  • 蓝桥杯嵌入式——十一届蓝桥杯嵌入式国赛

    千次阅读 多人点赞 2021-05-19 12:35:30
    蓝桥杯嵌入式——十一届蓝桥杯嵌入式国赛 之前准备省赛的时候用的是旧版的STM32F103,从准备国赛开始就用新版STM32G431平台了,主要是想经过新版的准备学习一下HAL库以及CubeMX的使用。用了几天的新版,感觉新版...
  • 蓝桥杯嵌入式——第九届省赛-电子定时器 目录蓝桥杯嵌入式——第九届省赛-电子定时器一、赛题分析二、问题总结三、代码 一、赛题分析 这一的赛题,系统框图如下,用到了LCD、LED、按键、EEPROM、PWM输出等模块。 ...
  • 程序说明: 蓝桥杯大赛第九届省赛-电子定时器 软件环境: Keil uVision 4.11 硬件环境: CT117E嵌入式竞赛板(代码兼容ILI932X系列、uc8230液晶控制器) 日 期: 2020年10月13日 作 者: lishan */ #include "stm32...
  • 文件包括蓝桥杯电子大类中的嵌入式设计比赛历年真题以及部分模拟题,其中也包括考察基础知识的客观题(第八第九届)。
  • if(b1>9){b1=0;} } if(flag=='2'){ b2++; if(b2>9){b2=0;} } if(flag=='3'){ b3++; if(b3>9){b3=0;} } } void Commit_Password() { //如果密码正确 if(b1 == password1 && b2 == password2 && b3 ...
  • 蓝桥杯嵌入式真题
  • 蓝桥杯嵌入式第省赛“里程仪

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 942
精华内容 376
关键字:

蓝桥杯嵌入式第九届