题目

    十三届省赛是要制作一个可由串口设置密码的密码锁。在本场比赛中,我们将用到LED模块按键模块串口模块定时器的PWM模块以及官方会提供源码的LCD模块。下面就请看原题:

题解

    在正式题解前,大家需要注意以下几点:

  • 由于LCD与LED有部分引脚是共用的,因此初始化完成LCD后最好手动关闭LED;
  • 由于每次LCD显示的长度可能不同,因此在本次显示前,要不先清屏,要不跟上次显示一样长;
  • 使用CubeMX配置完成串口USART1后需要更改默认引脚为PA9PA10

LED模块

    通过查询产品手册知,LED的引脚为PC8~PC15,外加锁存器74HC573需要用到的引脚PD2。(由于题目要求除LED1、LED2外的其他LED都处于熄灭状态,此处特意将所有的LED都初始化)
CubeMX配置:

代码样例
    由于G431的所有LED都跟锁存器74HC573连接,因此每次更改LED状态时都需要先打开锁存器,写入数据后再关闭锁存器。

/*****************************************************
* 函数功能:改变所有LED的状态
* 函数参数:
*           char LEDSTATE: 0-表示关闭 1-表示打开
* 函数返回值:无
******************************************************/
void changeAllLedByStateNumber(char LEDSTATE)
{HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,(LEDSTATE==1?GPIO_PIN_RESET:GPIO_PIN_SET));//打开锁存器    准备写入数据HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//关闭锁存器 锁存器的作用为 使得锁存器输出端的电平一直维持在一个固定的状态HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}/*****************************************************
* 函数功能:根据LED的位置打开或者是关闭LED
* 函数参数:
*           uint16_t LEDLOCATION:需要操作LED的位置
*           char LEDSTATE: 0-表示关闭 1-表示打开
* 函数返回值:无
******************************************************/
void changeLedStateByLocation(uint16_t LEDLOCATION,char LEDSTATE)
{HAL_GPIO_WritePin(GPIOC,LEDLOCATION,(LEDSTATE==1?GPIO_PIN_RESET:GPIO_PIN_SET));HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}

按键模块

    通过查询产品手册知,开发板上的四个按键引脚为PB0~PB2、PA0
CubeMX配置

代码样例
    由于G431开发板上按键数量较少以及本次按键不涉及长短按、单击双击等复杂按键的设计,因此,我们直接使用含锁机制的if判断即可。

  • 第一步,判断按键是否按键以及锁是否处于打开状态,如果两者有一个不满足函数直接返回;否则,进入下一步;
  • 第二步,上锁,延时消抖;
  • 第三步,再次读取各个按键,判断具体是哪个按键按下;
  • 第四步,判断按键是否松开,如果松开,则开锁;否则函数直接返回。
/********************************************** 函数功能:按键扫描 含按键消抖 无长按短按设计* 函数参数:无* 函数返回值:按键的位置*            返回值说明:B1-1 B2-2 B3-3 B4-4
*********************************************/
unsigned char scanKey(void)
{//按键锁static unsigned char keyLock = 1;//记录按键消抖时间// static uint16_t keyCount = 0;//按键按下if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET || HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == RESET|| HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == RESET || HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET) && keyLock == 1){//给按键上锁 避免多次触发按键keyLock = 0;//按键消抖 这里最好不要使用延时函数进行消抖 会影响系统的实时性// if(++keyCount % 10 < 5) return 0;// if(HAL_GetTick()%15 < 10) return 0;HAL_Delay(10);//按键B1if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET){return 1;}//按键B2if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == RESET){return 2;}//按键B3if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == RESET){return 3;}//按键B4if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET){return 4;}}//按键松开if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == SET && HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == SET&& HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == SET && HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == SET) && keyLock == 0){//开锁keyLock = 1;}return 0;
}

串口

    本次试题中,串口功能比较简单,只需要能够完成简单的接收数据即可。
CubeMX配置
    配置时一定一定记得改引脚!!!

代码样例
    HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)函数解析:

  • UART_HandleTypeDef *huart:串口通道;
  • uint8_t *pData:存放数据的buff;
  • uint16_t Size:一次接收数据的长度
        不过使用时还需要初始化,否则不能够进入中断接收数据;
/***使用HAL_UART_Receive_IT中断接收数据 每次接收完成数据后就会执行该函数***/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){// 重新使能中断HAL_UART_Receive_IT(huart,(uint8_t *)&Rxbuff,sizeof(Rxbuff)); }
}

定时器输出PWM波

CubeMX配置

修改PWM的频率及占空比样例代码(可直接调用)

/****************************************
* 函数功能:修改PWM频率工作
* 函数参数:
*           unsigned int autoreloadDate:重装载值
*           unsigned int compareDate:PWM的比较值
* 函数返回值:无
****************************************/
void pwmWorkByFre(unsigned int autoreloadDate,unsigned int compareDate)
{//设置重装载值__HAL_TIM_SetAutoreload(&htim2,autoreloadDate-1);__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,compareDate);HAL_TIM_GenerateEvent(&htim2, TIM_EVENTSOURCE_UPDATE);
}

LCD模块

    LCD模块官方会提供源码,内含初始化,大家会用即可。如下面是一段将LCD初始化成——文字颜色为白色、背景为蓝色的LCD屏:

/******************************************************************************
* 函数功能:LCD初始化
* 函数参数:无
* 函数返回值:无
*******************************************************************************/
void lcdInit(void)
{//HAL库的初始化LCD_Init();//设置LCD的背景色LCD_Clear(Blue);//设置LCD字体颜色LCD_SetTextColor(White);//设置LCD字体的背景色LCD_SetBackColor(Blue);
}

完整的配置文件

    文件说明:

  • sysInit()函数:自己添加的初始化配置;
  • sysWork()函数:系统工作逻辑函数;
#include "config.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"//外部定义变量
extern TIM_HandleTypeDef htim7,htim2;
extern UART_HandleTypeDef huart1;
extern TIM_HandleTypeDef htim3;//记录目前LCD处于的界面 0-密码输入界面  1-显示输出界面
int lcd_view_mod = 0;
//定时器7计数  计数值加1表示定时器触发一次也就是过了10ms
int time7_count = 0;
//保存上一次定时器7计数值
int time7_count_start_flag = 0;
//密码输入界面显示的数据
char psd_txt[20];
//输出状态界面显示数据
char sta_txt[20];char temp[20];
unsigned int crrl_t = 0;
uint32_t frd = 0;//用于循环
int i,j;//* 存储串口1接收的数据
uint8_t Rxbuff[7];//密码锁密码 注意 这里一定一定要加上字符串结束符'\0' 否则会出现字符串拼接的情况
char passwd[4] = {'1','2','3','\0'};
//输入的密码
char passwd_test[4] = {'0','0','0','\0'};
//记录密码输错次数
unsigned int passwd_wrong_count = 0;
//记录是否重头开始输入密码 0-是重头开始输入且没开始输入的  1-不是重头开始输入密码
char passwd_flag = 0;//记录按键的值
unsigned char key_num = 0;/***********************************************
* 函数功能:自定义的系统初始化
* 函数参数:无
* 函数返回值:无
***********************************************/
void sysInit(void)
{//LCD初始化lcdInit();//关闭所有的LEDchangeAllLedByStateNumber(0);//打开定时器7中断HAL_TIM_Base_Start_IT(&htim7);//打开串口的中断接收功能HAL_UART_Receive_IT(&huart1,(uint8_t *)&Rxbuff,sizeof(Rxbuff)); //打开定时器2通道2的PWM输出功能HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
}/***********************************************
* 函数功能:系统工作逻辑函数
* 函数参数:无
* 函数返回值:无
***********************************************/
void sysWork(void)
{//更新密码getPasswdByUsart();//密码的相关操作以及显示密码界面if(lcd_view_mod == 0){keyProc();PSDViewDisplay();pwmWorkByFre(1000,400);}//显示输出界面else if(lcd_view_mod == 1){STAViewDisplay();pwmWorkByFre(500,50);passwd_flag = 0;time7_count_start_flag = 1;}//LED灯显示ledDisplay();//5秒时间到 定时器值以及标志位归零 界面显示密码界面 密码输错次数归零if(time7_count>500){time7_count = 0;time7_count_start_flag = 0;lcd_view_mod = 0;passwd_wrong_count = 0;}
}/***非阻塞模式下定时器中断回调函数***/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{//定时器7的中断回调函数if(htim->Instance == TIM7){key_num = scanKey();if(time7_count_start_flag)time7_count++;}
}/***使用HAL_UART_Receive_IT中断接收数据 每次接收完成数据后就会执行该函数***/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){// 重新使能中断HAL_UART_Receive_IT(huart,(uint8_t *)&Rxbuff,sizeof(Rxbuff)); }
}/***********************************************
* 函数功能:显示密码输入界面
* 函数参数:无
* 函数返回值:无
***********************************************/
void PSDViewDisplay(void)
{LCD_DisplayStringLine(Line2,(uint8_t*)"       PSD");//在第一次输入密码前显示if(passwd_flag == 0){sprintf(psd_txt,"    B1 :%c       ",'@');LCD_DisplayStringLine(Line3,(uint8_t*)psd_txt);sprintf(psd_txt,"    B2 :%c       ",'@');LCD_DisplayStringLine(Line4,(uint8_t*)psd_txt);sprintf(psd_txt,"    B3 :%c       ",'@');LCD_DisplayStringLine(Line5,(uint8_t*)psd_txt);}else{sprintf(psd_txt,"    B1 :%c       ",passwd_test[0]);LCD_DisplayStringLine(Line3,(uint8_t*)psd_txt);sprintf(psd_txt,"    B2 :%c       ",passwd_test[1]);LCD_DisplayStringLine(Line4,(uint8_t*)psd_txt);sprintf(psd_txt,"    B3 :%c       ",passwd_test[2]);LCD_DisplayStringLine(Line5,(uint8_t*)psd_txt);}
}/***********************************************
* 函数功能:显示输出界面
* 函数参数:无
* 函数返回值:无
***********************************************/
void STAViewDisplay(void)
{LCD_DisplayStringLine(Line2,(uint8_t*)"       STA");LCD_DisplayStringLine(Line3,(uint8_t*)"    F :2000Hz");LCD_DisplayStringLine(Line4,(uint8_t*)"    D :10%");LCD_ClearLine(Line5);
}/***********************************************
* 函数功能:LED的相关显示
* 函数参数:无
* 函数返回值:无
***********************************************/
void ledDisplay(void)
{static int LED2_state = 1;//为了避免LED显示受到LCD影响 应该先关闭所有LEDchangeAllLedByStateNumber(0);//密码输入错误三次  LED2以0.1秒间隔闪烁 (5秒后熄灭)if(passwd_wrong_count>=3){time7_count_start_flag = 1;if(time7_count <= 500){//定时器计数值刷新  时间到了 LED2状态需要反转changeLedStateByLocation(LED2,LED2_state);LED2_state ^= 1;}}//密码验证成功 LED1点亮5秒 (5秒后熄灭)if(lcd_view_mod && time7_count <= 500){changeLedStateByLocation(LED1,1);}
}/********************************************
* 函数功能:
* 函数参数:无
* 函数返回值:无
********************************************/
void getPasswdByUsart(void)
{//分析串口接收到数据  需:旧密码匹配才能够设置新密码for(i=0;i<7;i++){//判断输入是否合理if(!((Rxbuff[i]>='0'&&Rxbuff[i]<='9') || Rxbuff[i]=='-'))return ;//判断旧密码是否正确if(i < 3){if(Rxbuff[i]!=passwd[i])return ;}//设置新密码if(i>3){passwd[i%4] = Rxbuff[i];}}//重置密码后也需要重置旧密码输入错误的次数passwd_wrong_count = 0;
}/********************************************
* 函数功能:
* 函数参数:无
* 函数返回值:无
********************************************/
void keyProc(void)
{//按键按下if(key_num){//按键B0-B2if(key_num!= 3){if(++passwd_test[key_num]>'9') passwd_test[key_num] = '0';passwd_flag = 1;}//按键B3else{//输入密码正确if(!strcmp(passwd,passwd_test)) {lcd_view_mod = 1;passwd_wrong_count = 0;}//输入密码错误else{passwd_flag = 0;passwd_wrong_count++;}}}
}/****************************************
* 函数功能:修改PWM的频率工作
* 函数参数:
*           unsigned int autoreloadDate:重装载值
*           unsigned int compareDate:PWM的比较值
* 函数返回值:无
****************************************/
void pwmWorkByFre(unsigned int autoreloadDate,unsigned int compareDate)
{//设置重装载值__HAL_TIM_SetAutoreload(&htim2,autoreloadDate-1);__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,compareDate);HAL_TIM_GenerateEvent(&htim2, TIM_EVENTSOURCE_UPDATE);
}

蓝桥杯嵌入式|第十三届蓝桥杯嵌入式省赛程序设计试题及其题解相关推荐

  1. 2022年蓝桥杯:第十三届蓝桥杯大赛软件赛省赛C/C++大学B组真题(考后回顾,文末附真题链接)

    目录 第十三届蓝桥杯大赛软件赛省赛C/C++大学B组真题(考后回顾) 试题 A: 九进制转十进制 试题 B: 顺子日期 试题 C: 刷题统计 试题 D: 修剪灌木 试题 E: X 进制减法 试题 F: ...

  2. 【蓝桥杯】第十三届蓝桥杯单片机国赛 代码程序

    第十三届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这 ...

  3. 【蓝桥杯】第十三届蓝桥杯单片机第二次省赛 代码程序

    第十三届蓝桥杯单片机第二次省赛 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这 ...

  4. 2022年蓝桥杯:第十三届蓝桥杯大赛软件赛省赛(全部正解做法代码 C/C++ B组)

    文章目录 试题 A: 九进制转十进制 问题描述 问题答案 试题 B: 顺子日期 问题描述 问题答案 试题 C: 刷题统计 问题描述 问题答案(正解) 试题 D: 修剪灌木 问题描述 问题答案(正解) ...

  5. 2022年蓝桥杯:第十三届蓝桥杯大赛软件赛省赛(题解C/C++B组)

    目录 试题 A: 九进制转十进制 问题描述 解题思路 问题答案 试题 B: 顺子日期 问题描述 问题答案 试题 C: 刷题统计 问题描述 解题思路 问题答案 试题 D: 修剪灌木 问题描述 解题思路 ...

  6. 关于第十三届蓝桥杯大赛校内选拔赛的通知

    关于第十三届蓝桥杯大赛校内选拔赛的通知 注:使用Python语言参加校赛并取得参加省赛资格的同学,跟我联系一下,我可以辅导你们参加蓝桥杯的省赛. 下面是我在蓝桥云课的讲课视频,我可以给你们再讲一遍. ...

  7. 蓝桥杯单片机第十三届第二场

    第十三届蓝桥杯单片机第二场 文章目录 第十三届蓝桥杯单片机第二场 前言 一.赛题分析 二.程序调试步骤 三.部分源程序 主函数部分 DAC处理函数 数码管处理函数 ADC处理函数 超声波处理函数 LE ...

  8. 第十三届蓝桥杯青少年STEMA(2021.08-2021.03)C++

    蓝桥杯2022年1月STEMA C++中级组编程真题解析 蓝桥杯2022年1月STEMA C++中级组编程真题解析_竹 子的博客-CSDN博客 第十三届蓝桥杯青少年C++中级组2021年11月比赛题目 ...

  9. 第十三届蓝桥杯大赛软件赛省赛真题

    第十三届蓝桥杯大赛软件赛省赛Java 大学 B 组 文章目录 第十三届蓝桥杯大赛软件赛省赛Java 大学 B 组 [考生须知] 试题 A: 星期计算 试题 B: 山 试题 C: 字符统计 试题 D: ...

最新文章

  1. java正则表达式及api_JAVA常用API:正则表达式regular expression
  2. spring定时器总结
  3. Tech·Ed 2007大会课程内容
  4. 我教育和科研计算机网是指,我校成为中国教育和科研计算机网湘潭城市节点单位...
  5. 15秋计算机基础作业3,东师15秋《计算机应用基础》在线作业3介绍.doc
  6. 漫谈 Gentoo 中文社区的建设
  7. python画条形图-Python数据可视化:基于matplotlib绘制「条形图」
  8. busybox制作根文件系统
  9. python中国地图数据下载_中国地图数据可视化(Python+selenium+Matplotlib),PythonSeleniumMatplotlib...
  10. Balrum 汉化指引
  11. 查询计算机的配置命令是什么,查看电脑配置指令大全
  12. 述职答辩提问环节一般可以问些什么_2.50 述职报告与评审提问注意事项
  13. android 动画变成素材,AE技法-把AE动画转换成Android原生动画,撂倒GIF做动画
  14. 帆软报表在已经搭载服务器上开发_报表案例_数据报表开发_做报表的步骤_报表开发流程-帆软...
  15. 刷APP任务平台可靠吗?
  16. STM32之串口的使用
  17. java mysql 生僻字 乱码_mysql 生僻字乱码
  18. 开源项目许可证相关-一张图看懂几种开源许可证
  19. Maven工程聚合错误Could not find artifact cn.itcast.parent:itcast-parent:pom:0.0.1-SNAPSHOT and 'parent.rel
  20. [附源码]java+ssm计算机毕业设计哈尔滨旅游资讯网站13hnn(源码+程序+数据库+部署)

热门文章

  1. java 贴吧代码_基于jsp的论坛贴吧-JavaEE实现论坛贴吧 - java项目源码
  2. 学汽车的女硕士就业问题
  3. C/C++ - 基本数据类型(默认:32位操作系统)
  4. 应急通信市场的大哥,MESH自组网的前世今生。
  5. 听见丨税改将刺激美国工厂增加更多机器人 日本神奈川县警方拟引进AI系统预测犯罪
  6. 冯诺依曼机的体系结构
  7. unity3d 多相机分流_unity 管理多个摄像机
  8. SQL Server 数据完整性规则
  9. 报错: com.atomikos.datasource.ResourceException: resume for XID
  10. 练习-定义和调用求最大公约数和最小公倍数的函数