第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)开发板 CT117E M4 STM32G431RBT 开发环境 CubeMX Keil5 涉及题目 第十三届蓝桥杯嵌入式省赛第一场真题 第十三届蓝桥杯第一场嵌入式设计与开发项目省赛

文章目录


前言

相关说明:

开发板:CT117E-M4(STM32G431RBT6)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式省赛第一场真题
在这里插入图片描述


CubeMX配置、主要函数代码及说明:

一、CubeMX配置(第十三届省赛第一场真题)

1.使能外部高速时钟:
在这里插入图片描述
2.配置时钟树:
在这里插入图片描述
3.GPIO:
在这里插入图片描述
4.TIM2(通道2 PA1输出方波、脉冲信号):
在这里插入图片描述5.UART:
在这里插入图片描述
6.NVIC优先级配置在这里插入图片描述


二、代码相关定义、声明

1.变量声明

unsigned char psd[3]={ 
   0x40,0x40,0x40};//定义输入密码数组 并初始化为@@@ unsigned char psd_now[3]={ 
   0x31,0x32,0x33};//定义正确密码数组 并初始化为1,2,3的ASCII码值 unsigned char jiemian;//显示界面 0为输入密码界面 1为状态输入界面 unsigned char uled;//LED显示参数 unsigned char flag;//报警灯标志位 0为LED2熄灭 1为LED2闪烁 unsigned char error_num;//存储错误输入密码次数 unsigned char rx,rx_buf[7],dex;//串口相关变量 unsigned char pwm;//初始为0 默认输出方波 1为输出脉冲 __IO uint32_t PWM_Tick;//计时脉冲输出时间 __IO uint32_t LED_Tick;//计时LED显示时间 

2.函数声明

void Key_Proc(); void Lcd_Proc(); void Uart_Proc(); void Led_Proc(); 

三、主要函数

1.main函数

int main(void) { 
    /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ LCD_Init(); LCD_Clear(Black); LCD_SetBackColor(Black); LCD_SetTextColor(White); __HAL_TIM_SET_AUTORELOAD(&htim2,999); __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); HAL_UART_Receive_IT(&huart1,&rx,1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { 
    /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ Key_Proc(); Lcd_Proc(); Uart_Proc(); Led_Proc(); } /* USER CODE END 3 */ } 

2.按键扫描

void Key_Proc() { 
    static __IO uint32_t Key_Tick;//减速变量 static unsigned char key_old; unsigned char key_down,key_value; if(uwTick-Key_Tick<50) return; Key_Tick=uwTick; key_value=Key_Scan(); key_down=key_value&(key_value^key_old); key_old=key_value; switch(key_down) { 
    case 1: if(jiemian==0)//密码输入界面时有效 { 
    if(++psd[0]>=0x3A)//初始为@时(0x40>0x3A) 按下B1变为0的ASCII值 psd[0]=0x30;//限定为0~9循环 } break; case 2: if(jiemian==0)//密码输入界面时有效 { 
    if(++psd[1]>=0x3A)//初始为@时(0x40>0x3A) 按下B2变为0的ASCII值 psd[1]=0x30;//限定为0~9循环 } break; case 3: if(jiemian==0)//密码输入界面时有效 { 
    if(++psd[2]>=0x3A)//初始为@时(0x40>0x3A) 按下B3变为0的ASCII值 psd[2]=0x30;//限定为0~9循环 } break; case 4://密码确认键 if((psd[0]==psd_now[0])&&(psd[1]==psd_now[1])&&(psd[2]==psd_now[2]))//密码输入正确 { 
    jiemian=1;//进入状态输出界面 uled|=0x01;//指示灯LED1点亮 LED_Tick=uwTick;//LED显示计时开始 pwm=1;//输出脉冲 PWM_Tick=uwTick;//输出脉冲计时开始 error_num=0;//错误次数清零 LCD_Clear(Black);//切换屏幕时清屏 } else//密码输入错误 停留在密码输入界面 { 
    if(++error_num>=3)//错误次数+1 大于等于3时 { 
    LED_Tick=uwTick;//开始报警计时 flag=1;//报警灯标志位置1 } psd[0]=psd[1]=psd[2]=0x40;//三位密码值重置为@ } break; } } 

3.屏幕显示和脉冲方波转换

void Lcd_Proc() { 
    static __IO uint32_t Lcd_Tick;减速变量 unsigned char lcd_string[21]; if(uwTick-Lcd_Tick<100) return; Lcd_Tick=uwTick; if(pwm==0)//密码输入界面时 输出方波 { 
    __HAL_TIM_SET_AUTORELOAD(&htim2,999);//设置频率1000Hz __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);//设置占空比50% } else//状态输出界面时 输出脉冲 { 
    __HAL_TIM_SET_AUTORELOAD(&htim2,499);//设置频率2000Hz __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50);//设置占空比10% } if(jiemian)//处于状态输出界面 { 
    if(uwTick-PWM_Tick>5000)//脉冲输出时间达到5秒 { 
    pwm=0;//输出5秒后转换为方波 jiemian=0;//进入密码输入界面 psd[0]=psd[1]=psd[2]=0x40;//三位密码值重置为@ LCD_Clear(Black);//切换屏幕时清屏 } } if(jiemian==0)//密码输入界面时 { 
    sprintf((char*)lcd_string," PSD"); LCD_DisplayStringLine(Line1,lcd_string); sprintf((char*)lcd_string," B1:%c",psd[0]);//密码第一位按字符输出 LCD_DisplayStringLine(Line3,lcd_string); sprintf((char*)lcd_string," B2:%c",psd[1]);//密码第二位按字符输出 LCD_DisplayStringLine(Line4,lcd_string); sprintf((char*)lcd_string," B3:%c",psd[2]);//密码第三位按字符输出 LCD_DisplayStringLine(Line5,lcd_string); } else//状态输出界面时 { 
    sprintf((char*)lcd_string," STA"); LCD_DisplayStringLine(Line1,lcd_string); if(pwm==0)//输出方波时 { 
    sprintf((char*)lcd_string," F:1000Hz"); LCD_DisplayStringLine(Line3,lcd_string); sprintf((char*)lcd_string," D:50%%"); LCD_DisplayStringLine(Line4,lcd_string); } else//输出脉冲时 { 
    sprintf((char*)lcd_string," F:2000Hz"); LCD_DisplayStringLine(Line3,lcd_string); sprintf((char*)lcd_string," D:10%%"); LCD_DisplayStringLine(Line4,lcd_string); } } } 

4.判断串口接收数据是否合法

unsigned char isRxCplt()//接收数据合法时返回值为1 { 
    unsigned char i; if(dex==0)//未接收到数据 return 0; if(dex!=7)//接收数据不为7个ASCII时不合法 return 2; if(rx_buf[3]==0x2D)//接收数据第四个为'-'时 { 
    for(i=0;i<3;i++) { 
    if((rx_buf[i]<'0')||(rx_buf[i]>'9'))//接收数据不为阿拉伯数字时不合法 return 2; } for(i=4;i<7;i++) { 
    if((rx_buf[i]<'0')||(rx_buf[i]>'9'))//接收数据不为阿拉伯数字时不合法 return 2; } return 1; } else//接收数据第四个不为'-'时不合法 return 2; } 

5.修改密码

void Uart_Proc() { 
    static __IO uint32_t Uart_Tick;//减速变量 unsigned char tx[21]; if(uwTick-Uart_Tick<100) return; Uart_Tick=uwTick; if(isRxCplt()==1)//接收数据合法 { 
    if((rx_buf[0]==psd_now[0])&&(rx_buf[1]==psd_now[1])&&(rx_buf[2]==psd_now[2]))//当前密码正确 { 
    psd_now[0]=rx_buf[4];//修改密码 psd_now[1]=rx_buf[5];//修改密码 psd_now[2]=rx_buf[6];//修改密码 sprintf((char*)tx,"Ok\n"); HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送OK表示修改成功 } else//当前密码不正确 { 
    sprintf((char*)tx,"Error\n"); HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送Error表示修改失败 } } else if(isRxCplt()==2)//接收数据不合法 { 
    sprintf((char*)tx,"Error\n"); HAL_UART_Transmit(&huart1,tx,strlen(tx),50);//向上位机发送Error表示修改失败 } dex=0;//清除串口接收数组索引 } 

6.串口中断

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { 
    rx_buf[dex++]=rx;//一位一位存入缓存数组 索引+1 HAL_UART_Receive_IT(&huart1,&rx,1);//重新开启接收中断 } 

7.LED闪烁

void Led_Proc() { 
    static __IO uint32_t Led_Tick;//减速变量  if(uwTick-Led_Tick<100)//0.1秒间隔闪烁 return; Led_Tick=uwTick; if(uwTick-LED_Tick>=5000)//LED1、LED2显示时间达到5秒 { 
    uled&=~0x01;//指示灯LED1熄灭 uled&=~0x02;//报警灯LED2熄灭 flag=0;//报警灯标志位清零,LED2停止闪烁 } if(flag)//报警灯标志位为1 uled^=0x02;//LED2以0.1秒间隔闪烁 Led_Disp(uled);//LED显示函数 } 

四、比赛感受

   本次比赛一波三折,赛前我去赛点测试,赛点CubeMx软件不支持64位,也没有32位java环境,也没有CubeMx G4安装包,Keil软件编译有问题,我刚好我的U盘里有安装包,解决了这些问题。
   比赛当天问题又出现了,我的电脑识别不了板子驱动,我检查驱动和更换电脑花费了1个半多小时,但是新电脑的Keil用调试器下载不进去,我就卸载了Keil进行重装,并安装Pack包和激活成功教程Keil,由于电脑有点卡,安装时间挺长的,安好已经两个多小时过去了,我代码只写好了底层的LED和按键,我心态挺好的,用了40分钟将程序写完,10分钟做完了选择题。
   当距离考试结束还有10分钟的时候我发现我的hex文件命名错误,我命名的是.hex,官方要求G.hex,否则零分,我赶紧把命名修改重新生成代码并提交。
   虽然有惊无险,但还是挺考验人心态的。


五、链接

1.第十三届蓝桥杯嵌入式省赛第一场真题PDF

2.第十三届蓝桥杯嵌入式国赛真题(基于HAL库的巨简代码+超级详解)

3.第十三届蓝桥杯嵌入式省赛第二场真题(基于HAL库的巨简代码+超级详解)

4.第十二届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)

今天的文章 第十三届蓝桥杯嵌入式省赛第一场真题(基于HAL库的巨简代码+超级详解)分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-01-06 14:46
下一篇 2025-01-06 14:40

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/103354.html