蓝桥杯嵌入式第十二届省赛模拟题

第十二届-嵌入式设计与开发科目模拟试题

代码工程和题目PDF地址:
https://github.com/Lxiangrui/Simulation-of-the-12th-Blue-Bridge-Cup

1、题目内容

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

2、需求分析

1、硬件部分,先看需要哪些模块,仅仅有ADC、GPIO、USART!!所以配置部分应该没有什么问题。

2、通读全题,理解需求,划分先后,发现该题ADC是核心,按键和串口其次,最后才是LED,当然还有LCD。

3、逻辑部分,主要逻辑部分在于如何实现定时器的开始、停止、重新开始等操作、其次就是简单的按键和串口控制参数变化。

核心逻辑:

重点的,对于如何实现定时器的开始、停止、重新开始等操作,我就单独展开说一下吧,我首先想到的是利用数组存储历史电压值,来判断是否满足条件。比如定时器的(重新)开始的点,通过题目来看,就是电压值上升,并且经过Vmin的时刻,我就通过判断历史值小于Vmin,并且瞬时值大于Vmax,就能很好的,判断定时器的开始的时刻了。结束功能同理。

3、相关代码

主函数

负责模块初始化、界面的显示和切换,按键处理,串口处理,以及逻辑函数等的调用

int main(void)
{
	SysTick_Config(SystemCoreClock/1000);
	Delay_Ms(200);
	Init_adc();
	Init_usart();
	Init_key();
	Init_led();
	STM3210B_LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	Ctro_led(ledall,0);
    history_voltage[0] = volt_adc();//防止开机直接开始计时
	history_voltage[1] = volt_adc();
	while(1){
		if(flag_UI)	UI_PARA();
		else	UI_DATA();
		UART_handle();
		determine_tim();
		LED_handle();
	}
}

获取电压函数

更新电压瞬时值,并且保存历史值,为了使程序运行良好,采用了10ms一次的更新

void to_obtain_voltage(){
	if(time_ms%10 == 0){
	history_voltage[1] = history_voltage[0];
	history_voltage[0] = volt_adc();}
}

定时器模式函数

void determine_tim(){
	
	if((history_voltage[0] > Vmin)&&(history_voltage[1] < Vmin)){		
        //实时数据在上面,历史数据在下面,这样就保证了是上升沿触发计时
		Tim_flag = 1;
		time_s = 0;
	}
	
	if((history_voltage[0] > Vmax)&&(history_voltage[1] < Vmax)){
		Tim_flag = 0;
	}
}

UI界面函数

void UI_DATA(){
		LCD_DisplayStringLine(Line0,(unsigned char *)"      Data");
		sprintf(disbuff," V:%.2fV      ", volt_adc());
	if(time_ms%50 > 40)	LCD_DisplayStringLine(Line2,(unsigned char *)disbuff);
		sprintf(disbuff," T:%ds      ",time_s);
		LCD_DisplayStringLine(Line3,(unsigned char *)disbuff);
		to_obtain_voltage();
}
void UI_PARA(){
		LCD_DisplayStringLine(Line0,(unsigned char *)"      Para");
		sprintf(disbuff," Vmax:%.1fV  ", Vmax);
		LCD_DisplayStringLine(Line2,(unsigned char *)disbuff);
		sprintf(disbuff," Vmin:%.1fV  ", Vmin);
		LCD_DisplayStringLine(Line3,(unsigned char *)disbuff);
}

LED控制函数

没什么讲的,按照不同标志位,控制LED亮灭

void LED_handle(){
	if(Tim_flag == 1)	Ctro_led(led1,1);
	else								Ctro_led(led1,0);
	
	if(led2_flag == 1)	Ctro_led(led2,1);
	else								Ctro_led(led2,0);
	
	if(led3_flag == 1)	Ctro_led(led3,1);
	else								Ctro_led(led3,0);
	
}

串口处理函数

这里我使用的三个嵌套的if来判断串口设置的值是否满足条件,是因为但是我不想写括号,而且那样会使得if那一行很长。但总的来说三个if嵌套着写,代码还是变多了。。因为后面发现,题目要求如果不满足条件,LED3会常亮,所以加了三个else,如果一开始就使用一个if并行判断,只需要一个else就好了😂,所以还是缺少了大局观,没有考虑很仔细。

void UART_handle(){
	if(RXOVER){
		int i;
		LCD_DisplayStringLine(Line6,(unsigned char *)RxBuffer1);
		uvmax = (RxBuffer1[0]-'0') + (RxBuffer1[2]-'0')*0.1;
		uvmin = (RxBuffer1[4]-'0') + (RxBuffer1[6]-'0')*0.1;
		if(uvmax-uvmin-1>0){
		if((uvmax>0)&&(uvmax<3.3)){
		if((uvmin>0)&&(uvmin<3.3)){
			Vmax = uvmax;
			Vmin = uvmin;
			led3_flag = 0;
		}
		else led3_flag = 1;
		}
		else led3_flag = 1;
		}
		else led3_flag = 1;
		for(i=0;i<100;i++)	RxBuffer1[i] = 0;
		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	}
}

按键中断处理函数

按键中断处理函数,我把它们都放到了main.c中,这样就不用extern 很多变量传递了。其次是改题目并没有使用b4按键,我配了,虽然只是几行代码,但是还是浪费了时间。还有就是按键逻辑处理的时候,也是犯了和串口处理程序中一样的错,使得程序冗余。

tips:

题目要求如果按键设置的值不合理,就不会更新按键的值,我的思路是,每次进入按键设置界面时,就保存现在的电压上下限,然后按下按键时,是改的真实的电压上下限,然后在按下b1时,切换回数据界面时,判断现在的电压上下限是否满足条件,如果不满足就将开始保存的电压上下限赋值回去,并且控制LED点亮,反之满足条件就关闭LED,并保存电压上下限。

当然还有那种设置针对于按键模式内的电压上下限,那样的话需要在模式切换的时候来回赋值,代码比较多,我就没用那种了。


void EXTI0_IRQHandler(void)
{
	static char flag_panduan;
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
  {
		i= 0xffff;
		while(i--);
		if(flag_UI == 0){
			kvmax = Vmax;
			kvmin = Vmin;
		}
//		
		flag_UI=!flag_UI;
//    //LCD_Clear(Black);
		if(flag_UI == 0){			//需要在切换回数据界面时判断
			flag_panduan = 1;
		}
		if(flag_panduan == 1){
			if(Vmax-Vmin-1>0){
		if((Vmax>0)&&(Vmax<3.3)){
		if((Vmin>0)&&(Vmin<3.3)){
			led2_flag = 0;
//			Vmax = uvmax;
//			Vmin = uvmin;
		}
		else{
			  Vmax = kvmax;
			  Vmin = kvmin;
				led2_flag = 1;
		}	
		}
			else{
			  Vmax = kvmax;
			  Vmin = kvmin;
				led2_flag = 1;
		}	
			}
			else{
			  Vmax = kvmax;
			  Vmin = kvmin;
				led2_flag = 1;
		}	
			flag_panduan = 0;
		}
		
	  /* Clear the  EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line0);
  }
}

void EXTI9_5_IRQHandler(void)
{
	 if(EXTI_GetITStatus(EXTI_Line8) != RESET)
  {
		i= 0xffff;
		
		while(i--);
    
		if(flag_UI == 1) Vmax+=0.1;
		if(Vmax>3.3)	Vmax = 0;
    /* Clear the  EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line8);
  }
}
void EXTI1_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line1) != RESET)
  {
		i= 0xffff;
		while(i--);
    
		if(flag_UI == 1) Vmin+=0.1;
		if(Vmin>3.3)	Vmin = 0;
    /* Clear the  EXTI line 0 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line1);
  }
}

SYStick函数

这里使用systick来驱动定时,同时还用来控制adc采样时间,以及延时,还有LCD刷新率,对于蓝桥杯真的很方便,但是实际应用不知道好不好哦.

void SysTick_Handler(void)
{
	time_ms++;
	if(time_ms % 1000 == 0){
		if(Tim_flag) time_s++;
		 time_ms = 0;
	}
	TimingDelay--;
}

}
}


### SYStick函数

这里使用systick来驱动定时,同时还用来控制adc采样时间,以及延时,还有LCD刷新率,对于蓝桥杯真的很方便,但是实际应用不知道好不好哦.

```c
void SysTick_Handler(void)
{
	time_ms++;
	if(time_ms % 1000 == 0){
		if(Tim_flag) time_s++;
		 time_ms = 0;
	}
	TimingDelay--;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值