蓝桥杯十三届嵌入式题解

概述

在这里插入图片描述
不算客观题,4t网评测有85分(仅供参考)

1.cubemx配置

定时器2

在这里插入图片描述

  • 注意CCR初始为500,占空比50%,之后要调整为10%
  • 频率为1Khz

定时器6

在这里插入图片描述

  • 定时器6用来每隔10ms扫描按键

串口

在这里插入图片描述

  • 注意开启NVIC

2.代码

全局变量

/*------------------------杂区------------*/
extern struct keys Mkey[5];
uint8_t led_sta=0x00;
char str[40];
char rx_data [50];
char tx_data[50];

char  m_data[50];

uint8_t view;
uint8_t error;
uint8_t confirm;
uint8_t right;

uint8_t K_first;//实现显示@
uint8_t K_second;
uint8_t K_third;

uint32_t tim_5s;
uint32_t tim_5s_ledflag;

/*------------------------数据区------------*/

//confirm=0

int b1;//按键获得值
int b2;
int b3;

char password[4]="123";//现在代码

//confirm=1
uint16_t frq;
float duty;

初始化

  • 需要注意,这里的接收中断初始化最好使用(HAL_UARTEx_ReceiveToIdle_IT(&huart1,( uint8_t*)rx_data,50);)用来接收不定长的数据
void My_Init(void)
{
	
	HAL_TIM_Base_Start_IT(&htim6);
	
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
	
	HAL_UART_Init(&huart1);
	
	HAL_UARTEx_ReceiveToIdle_IT(&huart1,(  uint8_t*)rx_data,50);
	该函数用于在中断模式下接收数据,直到 UART 接收缓冲区空闲(即没有数据接收一段时间)。
	//HAL_UART_Receive_IT(&huart1,(uint8_t *)rx_data,sizeof(rx_data));
	//HAL_UART_Transmit_IT(&huart1,(uint8_t *)tx_data,sizeof(tx_data));
	

	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	
	LED_Disp(0x00);
	
	tim_5s_ledflag=uwTick;
 	
}

LED模块

void LED_Disp(uint8_t x )
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,x<<8,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);

	
}
void LED_sta(uint8_t num,uint8_t sta)
{
	uint8_t pos=0x01<<(num-1);
	led_sta=(led_sta&(~pos))|(pos*sta);
	LED_Disp(led_sta);

}

void LED_proc(void)
{
	if(tim_5s)
	{
		LED_sta(1,1);
	}
	else LED_sta(1,0);
	
	static uint16_t flag,count;
	if(error>=3)
	{
		if(uwTick-tim_5s_ledflag>100) 
		{
			count++;
			flag=!flag;
			LED_sta(2,flag);
			
			tim_5s_ledflag=uwTick;
			
			if(count>=50)	
			{
				LED_sta(2,0);
				count=0;
				error=0;
			}
		}
	}
	else LED_sta(2,0);
		
}

按键

struct keys 
{
	uint8_t press;
	uint8_t flag;
	uint32_t age;
	uint8_t Long_flag;
	
};


struct keys Mkey[5];

uint8_t key_read(void)
{
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0 ) return 1;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) return 2;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0) return 3;
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0) return 4;
	else return 0;
	
}
void key_serv(void)
{
	uint8_t key_v =key_read();
	if(key_v!=0)
	{
		Mkey[key_v].age++;
		if(Mkey[key_v].age>2)
		{
			Mkey[key_v].press=1;
		}
	}
	else 
	{
		for(int i=0;i<5;i++)
		{
			if(Mkey[i].press==1&&Mkey[i].Long_flag!=1) Mkey[i].flag=1;
			//if(Mkey[i].age>199&&Mkey[i].press==1) Mkey[i].Long_flag=1;
			//if(Mkey[i].press==1 ) Mkey[i].flag=1;
			
			Mkey[i].age=0;
			Mkey[i].press=0;
			
		}
	}

}
void key_proc(void)
{
	
	if((Mkey[1].flag==1)&&(view==0))//按键1 
	{
		
		if(K_first==1) b1++;
		b1%=10;
		
		
		K_first=1;
		
		Mkey[1].flag=0;
	}

	if(Mkey[2].flag==1&&(view==0))//按键2 
	{
		  
		
		if(K_second==1) b2++;
		b2%=10;
		K_second=1;
		
		 
		Mkey[2].flag=0;
	}

	if(Mkey[3].flag==1&&(view==0))//按键3加
	{
		
		if(K_third==1) b3++;
		b3%=10;
		K_third=1;
		
		Mkey[3].flag=0;
	}
	if(Mkey[4].flag==1)//按键4
	{
		
		confirm=1;
		if((password[0]-48) == b1 &&(password[1]-48) == b2&& (password[2]-48) == b3)//如果密码正确
		//if(password[0] == b1 &&password[1] == b2&& (password[2]) == b3)//如果密码正确
			
		{
			view=1;//切换sta界面
			right=1;
			
			
			error=0;//次数清零
			
			LCD_Clear(Black);
			
			TIM2->ARR=500-1;TIM2->CCR2=50;//设置PWM 2khz 10%
		}
		else//不相等
		{
			view=0;
			error++;
			
		}
		    K_first=0;//更换PSD显示@
			K_second=0;
			K_third=0;
		
		b1=b2=b3=0;
		
		
//		memset(rx_data,0,sizeof(rx_data));//确认按下,每一位都置0
		
 		Mkey[4].flag=0;
		
	}

}

LCD

void LCD_proc(void)
{
	
	
	if(view==0)
	{
		
		sprintf(str,"        PSD        ");
		LCD_DisplayStringLine(Line1,(u8 *)str);
	
		if(K_first==1)
		{
			sprintf(str,"     B1:%d         ",b1);
		LCD_DisplayStringLine(Line3,(u8 *)str);
		
		}
		else
		{
			sprintf(str,"     B1:@           ");
		LCD_DisplayStringLine(Line3,(u8 *)str);
		}
		
		
		if(K_second==1)
		{
		sprintf(str,"     B2:%d         ",b2);
		LCD_DisplayStringLine(Line4,(u8 *)str);
		}
		else
		{
			sprintf(str,"     B2:@           ");
		LCD_DisplayStringLine(Line4,(u8 *)str);
		}
		
		if(K_third)
		{
		sprintf(str,"     B3:%d         ",b3);
		LCD_DisplayStringLine(Line5,(u8 *)str);
		}
		else
		{
			sprintf(str,"     B3:@           ");
		LCD_DisplayStringLine(Line5,(u8 *)str);
		}
	
		
	}
	
	if(view==1)
	{
		frq=80000000/(TIM2->PSC+1)/(TIM2->ARR+1);
		duty=(TIM2->CCR2)*100.0f/(TIM2->ARR);
		
		sprintf(str,"        STA        ");
		LCD_DisplayStringLine(Line1,(u8 *)str);
		sprintf(str,"     F=%dHz           ",frq);
		LCD_DisplayStringLine(Line3,(u8 *)str);
		sprintf(str,"     D=%.0f%%           ",duty);
		LCD_DisplayStringLine(Line4,(u8 *)str);
	}
	
		 
}

中断函数

  • 需要注意char old_pswd[4]; char new_pswd[4];接收三位数据便需要4个字节后面有’\0’;
  • char password[4]=“123”;也是一样(否则会出现第一位置0)
uint16_t count;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM6)//按键10ms
	{
		
		key_serv( );
		
		if(right)tim_5s++;//STA界面
		if(tim_5s>500) 
		{
			view=0;
			tim_5s=0;
			right=0;
			TIM2->ARR=1000-1;TIM2->CCR2=500-1;
		}
		
		
		
 		
	}
}
static uint16_t count;
char old_pswd[4];
char new_pswd[4];
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	count++;//记录进入中断的次数
    if(huart->Instance==USART1)
    {	
		//如果 old_pswd 和 new_pswd 是全局变量,并且在中断服务例程(ISR)中被修改,
		//而在主程序中也被访问或修改,可能会导致数据竞争和未定义行为。
		//这种情况下,主程序和中断服务例程可能会同时访问和修改这些变量,导致 password 的第一位被意外清零
		
        // 确保数据格式为 old_pswd-new_pswd
        if (sscanf(rx_data, "%3s-%3s", old_pswd, new_pswd)==2 )  // 确保成功读取两个密码
        {
            // 判断旧密码是否正确
            if (strcmp(password,old_pswd) == 0)
            {
                // 密码正确,更新密码
                for (int i = 0; i < 3; i++)
                {
                    password[i] = new_pswd[i];  // 更新为新密码
                }
                // 返回成功信息
                sprintf(tx_data, "   success   ");
                HAL_UART_Transmit(&huart1, (const uint8_t*)tx_data, strlen(tx_data), HAL_MAX_DELAY);
            }
            else
            {
                // 旧密码不匹配
                sprintf(tx_data, "   fail   ");
                HAL_UART_Transmit(&huart1, (const uint8_t*)tx_data, strlen(tx_data), HAL_MAX_DELAY);
            }
        }
        else
        {
            // 数据格式不正确
            sprintf(tx_data, "   invalid format   ");
			
            HAL_UART_Transmit(&huart1, (const uint8_t*)tx_data, strlen(tx_data), HAL_MAX_DELAY);
			
        }
		
        // 重新启动接收中断
        HAL_UARTEx_ReceiveToIdle_IT(&huart1,(  uint8_t*)rx_data,50);
		
		
		
		
    }
}

感谢阅读,仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值