【物联网蓝桥杯嵌入式】第13届蓝桥杯嵌入式真题代码详解(超详细)
一、CubeMx配置
GPIO配置
定时器配置
USART串口通信配置
二、LED模块
三、LCD显示屏和脉冲模块
四、KEY模块
五、USART串口通信模块
在user.c里配置LED和KEY按键接口
user.c如下
#include "main.h"
void LED_disp(u8 led) //LED模块
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //把PD2引脚置高电平(不作用)
HAL_GPIO_WritePin(GPIOC,0xFF00,GPIO_PIN_SET); //PC8-PC15引脚置高电平
HAL_GPIO_WritePin(GPIOC,led<<8,GPIO_PIN_RESET); //RESET低电平有效
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //PD2置低,锁存器有效
}
u8 key_up;
u8 key_down;
u8 key_old=0;
u8 key_value;
void KEY_read() //按键模块
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0)
{ HAL_Delay(10); //延时10MS消抖
key_value=1;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0)
{ HAL_Delay(10); //延时10MS消抖
key_value=2;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0)
{ HAL_Delay(10); //延时10MS消抖
key_value=3;
}
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
{
HAL_Delay(10); //延时10MS消抖
key_value=4;
}
else key_value=0; //没有按键
key_up=~key_value&(key_value^key_old); //按键弹起
key_down=key_value&(key_value^key_old); //按键按下
key_old=key_value;
}
在main.c里实现比赛要求
main.c内容如下
#include "main.h"
#include "gpio.h"
#include "user.h"
#include "stdio.h" //sprintf头文件
#include "string.h" //strlen头文件
unsigned char ui=0; //LCD屏幕
unsigned char password[3]={'1','2','3'};
extern size_t strlen(const char *);
u8 error_num=0;//错误次数
u8 b1_value='@'; //按键B1的值
u8 b2_value='@';
u8 b3_value='@';
u32 lcd_tick=0;
u8 lcd_buf[30];
u8 pwm;
void LCD_proc()
{
if(uwTick-lcd_tick<100)
return;
lcd_tick=uwTick;
if(pwm==0) //1KHZ,50%占空比
{
__HAL_TIM_SET_AUTORELOAD(&htim2,999); //频率1000
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500); //因为1000分之x=0.5
}
else //2KHZ,10%占空比
{
__HAL_TIM_SET_AUTORELOAD(&htim2,499); //频率2000 ,499是counter的值
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50); //因为500分之x=0.1
}
if(ui==0){
sprintf((char *)lcd_buf," PSD");
LCD_DisplayStringLine(Line0,lcd_buf);
sprintf((char *)lcd_buf," B1:%c",b1_value);
LCD_DisplayStringLine(Line3,lcd_buf);
sprintf((char *)lcd_buf," B2:%c",b2_value);
LCD_DisplayStringLine(Line4,lcd_buf);
sprintf((char *)lcd_buf," B3:%c",b3_value);
LCD_DisplayStringLine(Line5,lcd_buf);
}
if(ui==1)
{
sprintf((char *)lcd_buf," STA");
LCD_DisplayStringLine(Line0,lcd_buf);
sprintf((char *)lcd_buf," F:2000HZ");
LCD_DisplayStringLine(Line3,lcd_buf);
sprintf((char *)lcd_buf," D:10%%");
LCD_DisplayStringLine(Line4,lcd_buf);
LCD_ClearLine(Line5);
pwm=0;
}
}
u32 key_tick;
int LD1 = 0; //记录LD1亮灭状态(在stm32g4xx_it.c 文件 SysTick_Handler 函数中使用)
int LD2_Flag = 0; //用来便捷LD2是否要闪烁(在stm32g4xx_it.c 文件 SysTick_Handler 函数中使用)
void KEY_proc()
{
if(uwTick-key_tick<20)
return;
key_tick=uwTick;
KEY_read();
if(ui==0){
if(key_down==1)
{
if(b1_value=='@')
b1_value=48; //0的ASCLL码是48,@是64,9是57,输出%c字符型
else
if(++b1_value>57)
b1_value=48;
}
if(key_down==2)
{
if(b2_value=='@')
b2_value=48;
else
if(++b2_value>57)
b2_value=48;
}
if(key_down==3)
{
if(b3_value=='@')
b3_value=48;
else
if(++b3_value>57)
b3_value=48;
}
if( key_down==4){
LCD_Clear(Black);
if((b1_value==password[0])&&(b2_value==password[1])&&(b3_value==password[2]))
{
error_num=0; //输错次数清零
sprintf((char *)lcd_buf," STA");
LCD_DisplayStringLine(Line0,lcd_buf);
sprintf((char *)lcd_buf," F:2000HZ");
LCD_DisplayStringLine(Line3,lcd_buf);
sprintf((char *)lcd_buf," D:10%%");
LCD_DisplayStringLine(Line4,lcd_buf);
LCD_ClearLine(Line5);
pwm=!0;
//LD1亮
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All , 1);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 , 0);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 0);
LD1= 1; //防止LD2闪烁时哪LD1关掉
HAL_Delay(5000); //延迟5s
LCD_Clear(Black);
//LD1 灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All , 1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 0);
LD1 = 0;
b1_value='@';
b2_value='@';
b3_value='@';
}
else
{
b1_value=b2_value=b3_value='@'; //这样密码错误就可以到@@@
error_num++;
if(error_num > 2) //密码错误三次及以上
{
//LED2 以0.1秒闪烁
LD2_Flag = 1;//在stm32g4xx_it.c 文件 SysTick_Handler 函数中使用执行闪烁
}
}
}
}
}
uint8_t str [40];
uint8_t rx_buffer; //字节接收处 ///存的是原本的
uint8_t counter=0;//等于3代表传进去的数字为3
uint8_t RX_buff[7];//存新装进去的
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
RX_buff[counter++]=rx_buffer;
if(counter==7)
{
if((RX_buff[0]==password[0])&&(RX_buff[1]==password[1])&&(RX_buff[2]==password[2]))
{
password[0]=(RX_buff[4]);
password[1]=(RX_buff[5]);
password[2]=(RX_buff[6]);
sprintf(str,"sucess\r\n");
}
else
{
sprintf(str,"error\r\n");
}
HAL_UART_Transmit(&huart1,(unsigned char *)str,strlen(str),50);
}
HAL_UART_Receive_IT(&huart1,(uint8_t *)(&rx_buffer),1);
}
int main(void)
{
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
//初始化
LED_disp(0);
LCD_Init();
UART_Start_Receive_IT(&huart1,(uint8_t *)(&rx_buffer),1); //开启串行端口 1次接一个字节
HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_2); //打开定时器2用于PWM脉冲输出
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
while (1)
{
//函数声明
LCD_proc();
KEY_proc();
}
stm32g4xx_it.c
实现LED2以0.1s闪烁
在stm32g4xx_it.c 文件 SysTick_Handler 函数内容如下
int time_ms = 0;
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
extern int LD2_Flag;
extern int LD1;
if(LD2_Flag == 1)
{
if(time_ms == 5000) //5秒钟到
{
time_ms = 0;
LD2_Flag = 0;
return;
}
if((time_ms % 200) == 0) //灯亮
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All , 1);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9 , 0);
if(LD1 == 1) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 , 0);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 0);
}
else if((time_ms % 100) == 0) //灭
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All , 1);
if(LD1 == 1) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 , 0);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 1);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2 , 0);
}
time_ms ++ ;
}
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
作者:芒着变好