基于STM32G431嵌入式学习笔记——四、LED+KEY+LCD综合练习(基于第12届蓝桥杯显示部分题目)

news/2024/4/29 12:48:45/文章来源:https://blog.csdn.net/qq_53826699/article/details/127964832

在学习了前三节LED、LCD、KEY基本操作后,我们就已经成功掌握蓝桥杯必考的三大样内容了,本节以第12届蓝桥杯显示部分内容进行综合练习:

一、真题引入

1.功能概述

在这里插入图片描述

2.LCD显示界面
(1)车位显示界面

在这里插入图片描述

(2)费率显示界面

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

(3)LCD通用显示要求

在这里插入图片描述

3.按键功能

在这里插入图片描述

4.LED指示灯功能

在这里插入图片描述

5.初始状态说明

在这里插入图片描述

二、题目分析

上述为作者将三大模块的输出截取出来的题目要求,并非蓝桥杯竞赛全部比赛要求。

1.解题思路

为了使解题过程循序渐进一气呵成,我们首先要先总结出以下几点内容:

①LCD屏幕一共两个屏幕界面,因此要书写两段LCD输出的代码
②板子上电后就有内容显示,默认处于车位显示界面,因此可以首先书写该屏幕的内容保证初始化没问题
③按键是为LED、LCD服务的,因此最后书写按键状态切换的逻辑
④LED在本题中一共两种状态——LED1亮 or 都灭

2.解题步骤

因此解题步骤如下:
编写车位显示界面 --> 编写费率显示界面 --> 编写LED灯功能 -->编写按键的逻辑限制

三、环境搭建

新建CubeMX
在这里插入图片描述配置外部时钟
在这里插入图片描述在这里插入图片描述配置基础引脚(LED与KEY)
我们可以看出这里并没有像第一节那样去将所有的灯引脚置为High,是因为当时这么做的目的是初始化的时候LED灯全灭,这是硬件控制的方法
事实上我们也可以用一行代码实现我们想要的功能,即采用软件控制的方法(见后续代码实现中的操作)
在这里插入图片描述配置工程基础信息
在这里插入图片描述进入keil,初始化编译
在这里插入图片描述添加lcd.c lcd.h模块文件,并编译
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述

四、通用功能函数书写以及文件导入

1.key.h
#include "stm32g4xx_hal.h"#define KEY1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define KEY2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define KEY3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define KEY4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)char key_scan(void);
char key_scan_cd(void);

在这里插入图片描述

2.key.c
#include "stm32g4xx_hal.h"
#include "key.h"char key_scan(void)
{static int count1,count2,count3,count4;char value=0;count1 = count2 = count3 = count4 = 0;if(KEY1==0){HAL_Delay(10);if(KEY1==0){count1++;if(count1==1){value = 1;while(KEY1==GPIO_PIN_RESET);}}}else{count1 = 0;}if(KEY2==0){HAL_Delay(10);if(KEY2==0){count2++;if(count2==1){value = 2;while(KEY2==GPIO_PIN_RESET);}}}else{count2 = 0;}if(KEY3==0){HAL_Delay(10);if(KEY3==0){count3++;if(count3==1){value = 3;while(KEY3==GPIO_PIN_RESET);}}}else{count3 = 0;}if(KEY4==0){HAL_Delay(10);if(KEY4==0){count4++;if(count4==1){value = 4;while(KEY4==GPIO_PIN_RESET);}}}else{count4 = 0;}return value;
}
char key_scan_cd(void)
{static int count1,count2,count3,count4;char value=0;count1 = count2 = count3 = count4 = 0;if(KEY1==0){HAL_Delay(10);if(KEY1==0){count1++;if(count1>70){value = 11;}}}else{if(count1>0&&count1<=50){value = 1;}count1 = 0;}if(KEY2==0){HAL_Delay(10);if(KEY2==0){count2++;if(count2>70){value = 22;}}}else{if(count2>0&&count2<=50){value = 2;}count2 = 0;}if(KEY3==0){HAL_Delay(10);if(KEY3==0){count3++;if(count3>70){value = 33;}}}else{if(count3>0&&count3<=50){value = 3;}count3 = 0;}if(KEY4==0){HAL_Delay(10);if(KEY4==0){count4++;if(count4>70){value = 44;}}}else{if(count4>0&&count4<=50){value = 4;}count4 = 0;}return value;
}

在这里插入图片描述

3.led.h
#include "stm32g4xx_hal.h"
//灯光的亮灭
#define ON 1
#define OFF 0
//定义引脚
#define LED1 GPIO_PIN_8
#define LED2 GPIO_PIN_9
#define LED3 GPIO_PIN_10
#define LED4 GPIO_PIN_11
#define LED5 GPIO_PIN_12
#define LED6 GPIO_PIN_13
#define LED7 GPIO_PIN_14
#define LED8 GPIO_PIN_15
#define LEDALL GPIO_PIN_All//相关函数的声明
void control_led(uint16_t LED, uint8_t status);

在这里插入图片描述

4.led.c
#include "led.h"void control_led(uint16_t LED, uint8_t status)
{if(status == 0)//灭灯{HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}else//亮灯{       HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}
}

在这里插入图片描述随后将两个.c文件导入项目工程中:
在这里插入图片描述
导入后编译,随即.h文件会相应归类到对应的.c文件中

温馨提示,建议采用下述步骤导入:
①创建两个.h的空白文件,保存
②创建两个.c文件,分别在其中输入#include “led.h” #include"key.h",后保存。
③将两个.c文件导入项目工程
④编译一遍,通过后进行后续操作。
⑤书写两个.h文件的内容
⑥书写两个.c文件的内容
⑦再次编译

五、本题目中功能函数书写

为了方便,接下来书写的函数均定义在main.c中,不创建额外文件。

1.按键函数

在这里插入图片描述

void key_proc(void)
{char value = key_scan();switch(value){case 1:/*切换LCD显示屏界面的操作*/break;case 2:/*CNBR、VNBR费率增加0.5元*/break;case 3:/*CNBR、VNBR费率减少0.5元*/break;}
}

(0)头文件的添加
因为用到了key_scan()函数,所以需要在开头添加头文件:
在这里插入图片描述

(1)case1:LCD屏幕内容的切换
最简单的思路就是设置一全局变量,该值为1则显示一界面,0为另一个界面。
在这里插入图片描述初始值设定为1是因为题目要求默认处于车位显示界面
在这里插入图片描述因此key_proc函数更新(借助三元运算符实现0和1的转换)

void key_proc(void)
{char value = key_scan();switch(value){case 1:/*切换LCD显示屏界面的操作*/lcd_flag = (lcd_flag == 1 ? 0 : 1);break;case 2:/*CNBR、VNBR费率增加0.5元*/break;case 3:/*CNBR、VNBR费率减少0.5元*/break;}
}

(2)case 2 case 3 费率的变化
依旧是在文件中定义两个全局变量,表示两种费率的数值:
在这里插入图片描述
函数更新为:

void key_proc(void)
{char value = key_scan();switch(value){case 1:/*切换LCD显示屏界面的操作*/lcd_flag = (lcd_flag == 1 ? 0 : 1);break;case 2:/*CNBR、VNBR费率增加0.5元*/cnbr += 0.5f;vnbr += 0.5f;break;case 3:/*CNBR、VNBR费率减少0.5元*/cnbr -= 0.5f;vnbr -= 0.5f;break;}
}
2.LED灯显示函数

由于这是内容节选题目,LED灯仅要求实现一个功能

空闲涉及到空闲车位的计数,设置一全局变量:
在这里插入图片描述
添加头文件
在这里插入图片描述

void led_proc()
{if(idle>0){control_led(LED1,ON);//LED1亮}else{control_led(LED1,OFF);}
}

仍需注意修改lcd.c中三个Write函数以解决LED与LCD的冲突
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.LCD屏幕显示函数

更新头文件
在这里插入图片描述

(1)设置背景色——黑色

LCD_SetBackColor(Black);

(2)设置前景色——白色

LCD_SetTextColor(White);

(3)设置车位显示界面
与停车界面有关的全局变量也需要提前声明:
在这里插入图片描述这里用到了sprintf函数,其位于stdio.h中
在这里插入图片描述

  if(lcd_flag == 1)//车位显示界面{LCD_DisplayStringLine(Line2,(unsigned char *)"       Data         ");/*sprintf函数用于将我们本应该直接格式化输出的语句内容存储至字符串位于stdio.h中*/sprintf(str,"   CNBR:%d           ",car1);//第四行即将显示的内容LCD_DisplayStringLine(Line4,(unsigned char *)str);sprintf(str,"   VNBR:%d           ",car2);//第六行即将显示的内容LCD_DisplayStringLine(Line6,(unsigned char *)str);sprintf(str,"   IDLE:%d           ",idle);//第八行即将显示的内容LCD_DisplayStringLine(Line8,(unsigned char *)str);}

(4)设置费率显示界面

  else//费率设置界面{LCD_DisplayStringLine(Line2,(unsigned char *)"       Para         ");sprintf(str,"   CNBR:%.2f        ",cnbr);LCD_DisplayStringLine(Line4,(unsigned char *)str);sprintf(str,"   VNBR:%.2f        ",vnbr);LCD_DisplayStringLine(Line6,(unsigned char *)str);}

至此,lcd显示函数书写完毕,现展示完整代码:

void lcd_proc()
{LCD_SetBackColor(Black);LCD_SetTextColor(White);if(lcd_flag == 1)//车位显示界面{LCD_DisplayStringLine(Line2,(unsigned char *)"       Data         ");/*sprintf函数用于将我们本应该直接格式化输出的语句内容存储至字符串位于stdio.h中*/sprintf(str,"   CNBR:%d           ",car1);//第四行即将显示的内容LCD_DisplayStringLine(Line4,(unsigned char *)str);sprintf(str,"   VNBR:%d           ",car2);//第六行即将显示的内容LCD_DisplayStringLine(Line6,(unsigned char *)str);sprintf(str,"   IDLE:%d           ",idle);//第八行即将显示的内容LCD_DisplayStringLine(Line8,(unsigned char *)str);}else//费率设置界面{LCD_DisplayStringLine(Line2,(unsigned char *)"       Para         ");sprintf(str,"   CNBR:%.2f        ",cnbr);LCD_DisplayStringLine(Line4,(unsigned char *)str);sprintf(str,"   VNBR:%.2f        ",vnbr);LCD_DisplayStringLine(Line6,(unsigned char *)str);}
}

三个函数定义完成后,不要忘记在程序开头进行函数声明
在这里插入图片描述

4.主函数内容的编写

①进入while循环前进行LCD初始化
②在while循环中调用三个模块函数
在这里插入图片描述

完成!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_225383.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git学习(一)

git学习之基本配置以及简单推拉操作 1 git的基本配置 1.1 配置提交者的姓名 1.1.1 语法 git config --global user.name "姓名"1.1.2 示例代码 git config --global user.name "张三"1.1.3 示例代码运行截图 1.2 配置提交者的邮箱 1.2.1 语法 git c…

day5-day6【代码随想录】螺旋矩阵II

文章目录前言一、螺旋矩阵||&#xff08;力扣59&#xff09;二、螺旋矩阵&#xff08;力扣54&#xff09;前言 坚持循环不变量原则。 模拟顺时针画矩阵的过程: 填充上行从左到右 填充右列从上到下 填充下行从右到左 填充左列从下到上 由外向内一圈一圈这么画下去 一、螺旋矩阵…

MyBatis-Plus之DQL编程控制

增删改查四个操作中&#xff0c;查询是非常重要的也是非常复杂的操作&#xff0c;本次介绍的有&#xff1a; 条件查询方式查询投影查询条件设定字段映射与表名映射 1. 条件查询 1.1 条件查询的类 MyBatisPlus将书写复杂的SQL查询条件进行了封装&#xff0c;使用编程的形式完…

精彩回顾|关系网络赋能银行数字化转型的应用与实践

本文是根据11月10日Galaxybase图创课堂&#xff1a;乘金融科技之风&#xff1a;关系网络赋能银行数字化转型的应用与实践整理&#xff0c;错过的小伙伴们可以观看回放&#xff1a;https://uao.so/pct862806 精彩回顾 近年&#xff0c;知识图谱的重要性和实际应用逐步呈上升趋…

C++入门教程||C++while循环

whlie 语法 C 中 while 循环的语法&#xff1a; while(condition) {statement(s); } 在这里&#xff0c;statement(s) 可以是一个单独的语句&#xff0c;也可以是几个语句组成的代码块。condition 可以是任意的表达式&#xff0c;当为任意非零值时都为真。当条件为真时执行…

企业实战!基于Harbor搭建企业镜像仓库

企业实战&#xff01;基于Harbor搭建企业镜像仓库 虽然Docker官方提供了Docker Hub作为公共的Registry服务器&#xff0c;给到用户进行镜像的保存和管理工作。但对于企业而言&#xff0c;考虑到安全性和网络效率等原因&#xff0c;通常会搭建私有的Registry服务器&#xff0c;用…

程序员在平台兼职接单,月入30K,方法我全写出来了!(附接单渠道和注意事项)

本月兼职的收入又到账了&#xff0c;程序员副业实在是太香了&#xff01; 虽然这点小钱还远远达不到财富自由&#xff0c;也比不上那些真正的大佬&#xff0c;但在这个行业寒冬里&#xff0c;能有一笔相对稳定的收入&#xff0c;作为全职之外的补充&#xff0c;还是让人倍感踏实…

闪电连接算法之Python实现

文章目录简介原理Python实现简介 LAPO&#xff0c;即闪电连接优化(Lightning Attachment Procedure Optimization)&#xff0c;听名字就知道是受到了闪电的刺激&#xff0c;而获得灵感的一种算法。 为了走进LAPO的内心&#xff0c;于是上网搜了一下闪电的图片 呃不好意思&…

Eigen Segmentation fault (core dumped)

不会GDB吃大亏问题描述&#xff1a;解法&#xff1a;写在前面的话&#xff1a;我是PCL新手。也是Cmake新手。Eigen有点折腾人。 问题描述&#xff1a; 在调用PCL库实现一些有趣的功能&#xff0c;考虑到考虑到兼容不同平台&#xff0c;现状如下&#xff1a; VS2015&#xff1…

【新知实验室】腾讯云TRTC初体验

一、前言 今年腾讯云音视频发布了“三合一”的RT-ONE™网络。该网络整合了腾讯云实时通信网络&#xff08;TRTC&#xff09;、即时通信网络&#xff08;IM&#xff09;以及流媒体分发网络&#xff08;CDN&#xff09;三张网络&#xff0c;为业界最完整的音视频通信PaaS平台构建…

Pr 时间重映射卡点

哈喽&#xff0c;各位小伙伴&#xff01;今天我们来学习一下如何通过用Pr时间重映射做出卡点的效果~ 卡点音乐 一首适合卡点&#xff08;群青为例&#xff09;的音乐可以帮助我们更好的掌握视频的节奏&#xff0c;卡点可以采用手动卡点&#xff0c;方法可以通过在峰值最高处标…

使用SSM搭建图书商城管理系统(完整过程介绍、售后服务哈哈哈)

经过几位下载同学的反应、大部分运行未成功的原因有以下几点、特此记录以下。代码是完全没有问题的 项目地址&#xff1a;https://download.csdn.net/download/weixin_43304253/85811914 代码运行环境&#xff1a; tomcat&#xff1a;8 IDEA&#xff1a;2020 JDK&#xff1a;1…

Handler 原理

线程的应用场景 Android是单线程模型&#xff0c;Activity、Service、Broadcast等组件的创建&#xff0c;都是在主线程完成的&#xff0c;即UI线程。但如果需要执行一些耗时的操作时&#xff0c;比如&#xff1a;I/O的读写、大文件的读写、数据库操作以及网络上传和下载等操作都…

关于数据治理工具的选型,你了解多少?

数据治理的本质是盘点数据资产、治理数据质量&#xff0c;实施数据全生命周期的管理&#xff0c;这里面包括了建组织、立制度或者使用一款数据治理的软件帮助企业开展数据治理的相关工作等等。根据不同的数据治理项目特点&#xff0c;会用到不同的技术或工具。拥有一套趁手好用…

pdf生成:puppeteer

一、Puppeteer Puppeteer是Google Chrome团队出品的一款无界面Chrome工具&#xff0c;它提供了丰富的API&#xff0c;让开发者像鼠标一样控制浏览器的各种行为。Puppeteer是一个Node库&#xff0c;提供发了一个高级API来通过DevTools协议控制Chromium或Chrome。Puppeteer默认以…

LVGL学习笔记

芯片启动到LVGL初始化完成大体流程如下: 界面增加打印后代码如下: static void drag_event_handler(lv_event_t * e) {lv_obj_t * obj lv_event_get_target(e);lv_indev_t * indev lv_indev_get_act();if(indev NULL) return;lv_point_t vect;lv_indev_get_vect(indev, …

scala语法(一)(有java基础速学)

在拥有java基础上学习scala&#xff0c;注意以下几点 1. 变量声明 var | val 变量名 [: 变量类型] 变量值 val name: String "nico" 声明变量时&#xff0c;类型可以省略&#xff08;就是叫 类型推断&#xff09; val name "nico"类型确定后&#xff…

【面试题】JS基础-异步

1. 异步 1.1 为什么要异步&#xff1f; JS是单线程语言&#xff0c;只能同时做一件事。JS和DOM渲染共用同一个线程&#xff0c;因为JS可修改DOM结构。当遇到等待的情况时&#xff0c;例如网络请求、定时任务&#xff0c;程序不能卡住。所以需要异步来解决JS单线程等待的问题&…

Git -- submoudule子模块使用

文章目录子模块的作用添加子模块拉取带子模块的项目修改子模块代码子模块的作用 通常情况下&#xff0c;我们做项目时会有几个业务功能区分比较明确的模块&#xff0c;比如简单来说&#xff0c;一个项目我们可以分为认证授权模块、工具类模块、常规业务模块。 而像认证…

【Redis技术探索】「高可用架构模式」哨兵(sentinel)模式实现主从故障互切换模式详解

哨兵&#xff08;sentinel&#xff09;模式实现主从故障互切换模式详解Redis的多种模式Redis单机模式Redis单机模式的优点Redis单机模式的缺点Redis主从复制旧版本配置新版本配置查看主节点信息主从模式的优点主从复制的弊端Redis哨兵模式分析哨兵结构组成哨兵模式的主从切换Re…