蓝桥杯嵌入式第11届国赛题

比完省赛,写了几道国赛题,贴在这里和大家分享一下。

以上是第十一届的赛题,这届题目元素包括lcd,led,key,adc,ic,pwm,后面是我的解答思路

首先是cubemx的配置,必考的lcd, led,与key三大元素

打开高速时钟

给led命名

key

方法是通过定时器中断扫描按键状态,由于题目要求按键响应小于0.3秒,所以在配置psc与arr的时候需要计算一下定时器产生中断的时间。

 使用记得开启相关定时器中断

回调函数中写按键扫描,为防止抖动,多次判断key_state这个状态,如果真的按下,才会给key_flag置1,而case 3中的time是为了确定按键按下的时间,可以根据题目要求,为time赋值。

key_function这个函数是按键的具体作用,flag1是界面的切换标志,为0是数据界面,为1是参数界面,再按下按键,则跳转到数据界面,切换界面时需要使用清屏函数,并且每一次执行完按键操作时,需要清除按键的标志位。


题目要求按键B2与B3只能在参数界面起作用,所以我们设置一个前提flag1==1,此时,如果我们在数据界面按下时,按键的标志位置1,并且会在参数界面起作用,所以我们需要在flag1==0时,清除按键的标志位。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM16)
	{
		key[0].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		for(int i=0;i<4;i++)
		{
			switch(key[i].state)
			{
				case 0:
					if(key[i].key_state==0)
					{
						key[i].state=1;
					}
				case 1:
					if(key[i].key_state==0)
					{
						key[i].key_sflag=1;
						key[i].state=2;
					}
				case 2:
					if(key[i].key_state==1)
					{
						key[i].state=0;
					}
					if(key[i].key_state==0)
					{
						key[i].key_time++;
						if(key[i].key_time>500)
							key[i].key_lflag=1;
					}
			}
		}
	}
}
//在中断回调里写扫描
void key_function()
{
	if(key[0].key_sflag==1)
	{
		LCD_Clear(Black);
		flag1++;
		if(flag1>1)
			flag1=0;
		key[0].key_sflag=0;
	}
	if(flag1==0)
	{
		if(key[1].key_sflag==1)
		{
			key[1].key_sflag=0;
		}
		if(key[2].key_sflag==1)
		{
			key[2].key_sflag=0;
		}
	}
	if(flag1==1)
	{
		if(key[1].key_sflag==1)
		{
			led1_last=led1-1;
			led1++;
			if(led1==led2)
			{
				led1++;
			}
			if(led1>8)
			{
				if(led2==1)
					led1=2;
				else
					led1=1;
			}
			key[1].key_sflag=0;
		}
		if(key[2].key_sflag==1)
		{
			led2_last=led2-1;
			led2++;
			if(led1==led2)
			{
				led2++;
			}
			if(led2>8)
			{
				if(led1==1)
					led2=2;
				else
					led2=1;
			}
			key[2].key_sflag=0;
		}
	}
	if(key[3].key_sflag==1)
	{
		if(pwm_mode==0)
			pwm_mode=1;
		else
			pwm_mode=0;
		key[3].key_sflag=0;
	}
}
//此函数写按键的作用,例如切换显示屏幕,数字加减

led

蓝桥杯led与lcd共用8个io口,所以是通过锁存器将led的状态存起来,而pd2就是锁存器的关键,使能后,才会将数据存入。

uint16_t led_state[8]={1,1,1,1,1,1,1,1};
void control_led(uint16_t pin,uint8_t level)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
	HAL_GPIO_WritePin(GPIOC,led1_Pin|led2_Pin|led3_Pin|led4_Pin|led5_Pin|led6_Pin|led7_Pin|led8_Pin,1);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
	
	for(int i=0;i<8;i++)
	{
		if((pin&(led1_Pin<<i))==led1_Pin<<i)
		{
			led_state[i]=level;
		}
	}
	
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,1);
	for(int i=0;i<8;i++)
	{
		HAL_GPIO_WritePin(GPIOC,led1_Pin<<i,led_state[i]);
	}
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,0);
}
void led_light()
{
	if(data[0]>data[1])
	{
		if(led1-1!=led1_last)
			control_led(led[led1_last],1);
		control_led(led[led1-1],0);
	}
	else
	{
		control_led(led[led1-1],1);
	}
	if(f1>f2)
	{
		if(led2-1!=led2_last)
			control_led(led[led2_last],1);
		control_led(led[led2-1],0);
	}
	else
	{
		control_led(led[led2-1],1);
	}
}

adc采集与频率测量

adc采集

本届题目使用到一个adc的两个通道,所以需要使用扫描模式,转换次数设为两个,通道13与通道17。

data[0]与data[1]就是采集到的值,需要进行处理,data[0]*3.33/4096,我之前写模拟题时,只将数据乘了3.3,后面精度不够,改为了3.33。

void get_adc(uint16_t *data,uint8_t size)
{
	for(int i=0;i<size;i++)
	{
		HAL_ADC_Start(&hadc2);
		if(HAL_ADC_PollForConversion(&hadc2,100)==HAL_OK)
		{
			data[i]=HAL_ADC_GetValue(&hadc2);
		}
	}
	HAL_ADC_Stop(&hadc2);
}

频率测量

配置TIM2通道2

同样要勾选NVIC

输入捕获测量频率,只需要开启对应通道的输入捕获模式,设置为上升沿触发,用传入的时钟80M/psc/捕获到上升沿时存入寄存器的值,即CCR2,捕获完毕需将CNT清零,等待下一次捕获。

uint16_t f1;
uint16_t f2;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM2)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
		{
			f1=1000000/TIM2->CCR2;
			TIM2->CNT=0;
		}
	}
	if(htim->Instance==TIM15)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
		{
			f2=1000000/TIM15->CCR1;
			TIM15->CNT=0;
		}
	}
}

pwm输出

extern uint16_t pwm_mode;

//同频信号
void pwm_change(uint16_t f1,uint16_t f2)
{
	uint16_t psc;
	if(pwm_mode==0)
		psc=80000/f1;
	else
		psc=80000/f2;
	__HAL_TIM_PRESCALER(&htim17,psc);
}
//由于只是频率改变,所以只改变psc

 pwm有三个值可以更改,psc,arr,ccr,psc只与频率有关,arr与频率和占空比有关,ccr与占空比有关。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值