突击蓝桥杯嵌入式(七)——第十三届省赛第一场真题

突击蓝桥杯嵌入式(七)——第十三届省赛第一场真题

一、题目概览

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

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

二、思路梳理

我们直接在LCD例程的基础上,改需增加的外设如下:

LED灯(配置锁存器PD2),串口(波特率9600,带中断),按键4个,PWM输出。

题目较为简单,其逻辑部分如下:

上电之后,板子初始化,LCD显示为@@@,默认密码为123,PWM脉冲输出1KHZ的方波信号,然后开启串口接收中断(7个数据进入中断),然后中断里对于字符串进行处理,利用ssanf分离出输入的初始密码和新密码,然后对比密码是否正确,如果错误,则不改变原有密码值。

然后按键扫描部分:

按下B1B2B3分别对应密码的123位,其变化规律为0-9-0-9,然后B4确认,如果密码正确,LED1点亮五秒然后熄灭,LCD显示输出界面5s,且PWM输出2KHZ,占空比为百分之10的方波,之后显示三个@@@!!!如果错误,累计次数,超过两次,LED2以0.1s为间隔闪烁,持续五秒。

三、代码

uint8_t str[21];

uint8_t LCD_flag = 2;	
/******************
LCD分为三个界面,分别为
复位页面(三个@@@)2
密码界面(主页面)0
数据页面(显示频率和占空比)1
******************/
int passward[3];	//现在输入的密码
uint8_t real_passward[3];	//真正的密码
uint8_t rx_passward[3];		//串口接收到的密码
uint8_t count;				//
uint8_t right_flag;			//密码正确标志
uint8_t count_led=0;		//led计数器
uint8_t shock_flag=0;		//led闪烁标志位
uint8_t shock;				//闪烁种的led亮灭标志
uint8_t count_LCD;			//数据页面LCD只能持续5s,所以用一个count计数

uint8_t key_value;			//三行代码消抖,没啥好说的
uint8_t key_down;
uint8_t key_up;
uint8_t key_old;
uint8_t rx_buff[7];			//串口接收的消息

__IO uint32_t uwTickLCD_Speed;	//滴答定时器参量,没啥好说的
__IO uint32_t uwTickKey_Speed;
__IO uint32_t uwTickLED_Speed;

LED灯

void LED_Disp(uint8_t ucled)
{
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,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_PIN_SET);//灭灯
	HAL_GPIO_WritePin(GPIOC,ucled<<8,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	
}
void LED_Proc()
{
	if(uwTick - uwTickLED_Speed < 100) return;
	else uwTickLED_Speed = uwTick;
	if(count_led<=50&&count_led>0)		//如果触发了闪烁5s或亮5s的标志
	{
		if(shock_flag==1)	//若是闪烁标志
        {
			if(shock==1)	//led2闪烁5s
            {
				LED_Disp(0x02);
				shock^=1;
			}
			else if(shock==0)
            {
				LED_Disp(0x00);
				shock^=1;
			}
				count_led--;	//每100ms 标志位-1
            }
             else				//当不是闪烁标志
             {
                  LED_Disp(0x01);	
                  count_led--;
             }

	}
	else if(count_led == 0){	//当计数位为0,也就是过了五秒时候,关闭所有LED和标志位
		LED_Disp(0x00);
		shock_flag=0;
	}
}

LCD

void LCD_main_Dis()			//主页面,显示密码
{
	sprintf((char *)str,"        PSD          ");
	LCD_DisplayStringLine(Line1,(uint8_t *)str);
	if(passward[0] == -1)
	{
		sprintf((char *)str,"     B1:@            ");
		LCD_DisplayStringLine(Line3,(uint8_t *)str);
	}
	else
	{
		sprintf((char *)str,"     B1:%d            ",passward[0]);
		LCD_DisplayStringLine(Line3,(uint8_t *)str);
	}
	if(passward[1] == -1)
	{
		sprintf((char *)str,"     B2:@            ");
		LCD_DisplayStringLine(Line4,(uint8_t *)str);
	}
	else
	{
		sprintf((char *)str,"     B2:%d            ",passward[1]);
		LCD_DisplayStringLine(Line4,(uint8_t *)str);
	}
	if(passward[2] == -1)
	{
		sprintf((char *)str,"     B3:@            ");
		LCD_DisplayStringLine(Line5,(uint8_t *)str);
	}
	else
	{
		sprintf((char *)str,"     B3:%d            ",passward[2]);
		LCD_DisplayStringLine(Line5,(uint8_t *)str);
	}
}

void LCD_data_Dis()			//数据页面,密码正确时候显示
{
	sprintf((char *)str,"        STA          ");
	LCD_DisplayStringLine(Line2,(uint8_t *)str);
	sprintf((char *)str,"     F:2000HZ            ");
	LCD_DisplayStringLine(Line4,(uint8_t *)str);
	sprintf((char *)str,"     D:10%%            ");
	LCD_DisplayStringLine(Line5,(uint8_t *)str);
		sprintf((char *)str,"                      ");
	LCD_DisplayStringLine(Line6,(uint8_t *)str);
}

void LCD_Proc()
{
	if(uwTick - uwTickLCD_Speed < 100) return;
	else uwTickLCD_Speed = uwTick;

	if(LCD_flag == 0)
	{
		LCD_main_Dis();
	}
	if(LCD_flag == 1)	//如果密码正确,进入数据页面5s
	{
			LCD_data_Dis();
			count_LCD++;		//100ms +1
			TIM2->ARR = 500;	//改变频率和占空比
			TIM2->CCR2 = 50;
			if(count_LCD==50){	//当过了5s
			count_LCD =0;	//返回主页面,清除LCD计数
			LCD_flag = 2;
			TIM2->ARR = 1000;	//复原占空比
			TIM2->CCR2 = 500;
	}
	if(LCD_flag == 2)	
	{
		passward[0]=-1;
		passward[1]=-1;
		passward[2]=-1;
	}
}

Key按键

uint8_t Key_Scan()	//扫描哪个键让按下去
{
	static uint8_t value;
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == GPIO_PIN_RESET)
	{
		value = 1;
	}	
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET)
	{
		value = 2;
	}
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == GPIO_PIN_RESET)
	{
		value = 3;
	}
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)
	{
		value = 4;
	}
	else
	{
		value = 0;
	}
	return value;
}


void Key_Proc()
{
	if(uwTick - uwTickKey_Speed < 100) return;
	else uwTickKey_Speed = uwTick;
	key_value = Key_Scan();
	key_down = key_value&(key_value^key_old);
	key_up = ~key_value&(key_value^key_old);
	key_old = key_value;
	switch(key_down)
	{
		case 1:
			passward[0]++;
			if(passward[0]>9){
				passward[0] = 0;
			}
			LCD_flag = 0;
		break;			
		case 2:
			passward[1]++;
			if(passward[1]>9){
				passward[1] = 0;
			}
			LCD_flag = 0;
		break;
		case 3:
			passward[2]++;
			if(passward[2]>9){
				passward[2] = 0;
			}
			LCD_flag = 0;
		break;
		case 4:
				right_flag = check_passward();
				if(right_flag){
					count=0;
					count_led=50;
					LCD_flag = 1;
					passward[0]=-1;
					passward[1]=-1;
					passward[2]=-1;
				}
		break;
	}	
}

uint8_t check_passward()	//检查密码是否正确,正确就返回1,错误就计数,三次之后置1闪烁标志位
{
	if((passward[0] == real_passward[0])&&(passward[1] == real_passward[1])&&(passward[2] == real_passward[2]))
	{
		count=0;
		return 1;
	}
	else
	{
		count++;
		if(count>2){
			shock_flag=1;
			count_led=50;
		}
		return 0;
	}
}

串口

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	static uint8_t cofirm_passward[3];
	static uint8_t re_passward[3];	//sscanf从rx_buff读取密码,如果输入的旧密码正确,将修改的密码覆盖原来的密码
	sscanf((char *)rx_buff,"%1d%1d%1d-%1d%1d%1d",&cofirm_passward[0],&cofirm_passward[1],
           &cofirm_passward[2],&re_passward[0],&re_passward[1],&re_passward[2]);
	LCD_DisplayStringLine(Line8,(uint8_t *)str);
	if((cofirm_passward[0]==real_passward[0])&&(cofirm_passward[1]==real_passward[1])&&(cofirm_passward[2]==real_passward[2]))
	{
		for(int k=0;k<3;k++)
		{
			real_passward[k] = re_passward[k];
		}
	}
	HAL_UART_Receive_IT(&huart1,rx_buff,7);
}

主函数,主要是一些初始化

	HAL_TIM_PWM_Init(&htim2);				//一些初始化,没啥好说的
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	LED_Disp(0X00);
	real_passward[0] = 1;
	real_passward[1] = 2;
	real_passward[2] = 3;
	HAL_UART_Receive_IT(&huart1,rx_buff,7);
  while (1)
  {
		LCD_Proc();
		Key_Proc();
		LED_Proc();
  }
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路人甲YYH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值