嵌入式软件--51单片机 DAY 2
一、数码管
1.数码管概况
2.设计
(1)硬件设计
我们可以通过阴极控制显示的位置,通过阳极控制显示的内容。两个数码管共有8个阴极引脚和16个阳极引脚,如果所有引脚都直接接入MCU,会造成MCU引脚的极大浪费。
为了节省MCU的引脚,我们可以将两个数码管的阳极接在一起。
如此我们就有了8个阴极,8个阳极16个引脚。我们只需通过8个GPIO引脚就能控制这8位数码管的显示内容了。
既然是八位,我们很快想到了38译码器,通过三位二进制数字的输入控制八种结果。
由于51单片高电平的驱动能力很微弱,不足以点亮数码管,因此可以使用74HC245N作为驱动芯片,该芯片的用法如下。
有了74HC245之后,51单片引脚的输出就只用作信号,而驱动数码管的电流则由74HC245的电源提供。
(2)软件设计
为了实现当前需求,需要考虑两点,分别是显示位置和显示内容。确定显示位置称为数码管的位选,确定显示内容称为数码管的段选。
1》位选
P13 P14 P15控制显示位置,连接数码管阴极,如果为0低电平就能导通显示。故控制位选。
P13接到了A0,P14接到了A1,P15接到了A2。
例:如果p15-p13输入为000,那么与y0相连的1号数码显示。
如果001,第二位显示
010,第三位显示
011,第四位显示
100,第五位显示
······
P17 P16 P15 P14 P13 P12 P11 P10
0 0 1 1 1 0 0 0
P1编码的中三位控制着位选。
2》段选
根据原理图可知,数码的段选通过单片机的P00~P07这7个引脚控制,具体的对应关系如下。
阳极连接。如果不点亮,给0即可。想显示,给1即可。
以上显示,代表着数字0,即给ABCDEF一个高电平1,G给0不亮,DP给0代表小数点不亮。
所以段选,P07(高位)--P01:0 0 1 1 1 1 1 1
那么可以给寄存器P0一个值0x3F.
通过p00-p07显示数码管的内容。通过让ABCDEFG、DP的亮灭,显示数字。
如此可以得到映射关系表:
3》代码实现
要求:静态显示,在任意位置,显示任意数字。
位选决定位置。根据位选的数位,决定P13~P15的取值。
段选,0~9的数字显示通过P00-P07控制。数字0要让ABCDEF亮起,如此编码就为:00111111
十六进制0x3F。数字2即为0x5B.
如果让数字在第一个位置亮起,P15~P13:0 0 0
段选好说,将数字编码2赋值于P0,2对应十六进制0X5B,即可通过控制数码管显示对应的数字。
位选需要动动脑筋,switch能够做到,但没有效率。我们用position形参,传递的是第几位。假设P1是定义的八位变量,P1=10 101 010,我们要在第4位显示数字,那么P15-P13:011 position:0000 0011,现在要做的就是将position的末三位赋值到P1的中三位,并不影响P1其他数位上的数字。
所以考虑怎样给到P1的中三位。
P1:10 101 010
position:0000 0 011
为了更好的观察规律,先将position左移三位。
P1:10 101 010
position:00 011 000
将P1的中三位置0,在与position做或运算。那么先让P1中三位置零,就与上11000111,其他几位都是1,1与任何数相与都是原来的数。
那么调整下方法:让position左移三位,让P1&11000111,在P1与position作或运算。
position<<=3;
P1&=11000111;//P1&=0xC7
p1|=position;
代码表示为:
#include <STC89C5xRC.H>
#define SMG_EN P36 // 数码管总开关
#define LED_EN P34 // LED灯总开关
typedef unsigned char u8; // 给无符号字符类型取别名,代表无符号8位
static u8 s_digit_codes[10] = {0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F // 9
};//编码数组
//定义函数
void DigitalTube_DisplaySingle(u8 position, u8 num_code)//一个参数位选:P13/P14/P15,一个参数段选
{P1 &= 0xC7;//按位与运算position <<= 3;P1 |= position;P0 = num_code;//数字编码赋予P0
}
void main()
{// 打开数码管总开关SMG_EN = 0;// 关闭LED灯总开关LED_EN = 0;DigitalTube_DisplaySingle(0, s_digit_codes[2]);//让数字显示在位选0第一个位置,显示内容为2while (1) {};
}
烧录以上代码到51核心板内,数码管第一个位置显示2就完成了。
4》变量声明
在C89标准中,所有声明的变量必须在作用域的最前边声明。C99就没有这个约束了。注意一下即可!
二、数码管动态显示
1.要求
我们先搞整数的显示。
2.设计
8位数码管同一时刻只能显示一个位置,通过高速的循环显示可以做到以上效果。
(1)思路
(2)代码实现
我们首先要定义一个显存数组。
#include <STC89C5xRC.H>
#define SMG_EN P36 // 数码管总开关
#define LED_EN P34 // LED灯总开关
typedef unsigned char u8; // 给无符号字符类型取别名,代表无符号8位
typedef unsigned long u32;
static u8 s_digit_codes[10] = {0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F // 9
};//编码数组
//定义显存数组
u8 buffer[8];
//定义函数
void DigitalTube_DisplaySingle(u8 position, u8 num_code)//一个参数位选:P13/P14/P15,一个参数段选
{P0=0x00;P1 &= 0xC7;//按位与运算position <<= 3;P1 |= position;P0 = num_code;//数字编码赋予P0
}
//设置显存数组,待展示数字
void DigitalTube_DisplayNum(u32 num)
{u8 i;for(i=0;i<8;i++){
buffer[i]=0x00;}//将数组内元素都初始化if (num==0){buffer[7]=s_digit_codes[0];return;}i=7;while (num>0){buffer[i]=s_digit_codes[num%10];num/=10;i--;}}
//动态扫描
void DigitalTube_Refresh()
{
u8 i;
for ( i = 0; i < 8; i++)
{DigitalTube_DisplaySingle(i,buffer[i]);
}}
void main()
{// 打开数码管总开关SMG_EN = 0;// 关闭LED灯总开关LED_EN = 0;DigitalTube_DisplayNum(12345);while (1) {DigitalTube_Refresh();};
}
上图的效果就实现了。
(3)实现负数
负数的表示编码为0x40,将之作为段选数组的最后一位,codes【10】。
Int_Digital.c
#include <STC89C5xRC.H>
#include "Int_DigitalTube.h"
#include "Com_Util.h"
//定义段选内容编码
static u8 codes[11]={0x3F,//00x06,//10x5B,//20x4F,//30x66,//40x6D,//50x7D,//60x07,//70x7F,//80x6F,//90x40//负号
};
//定义显存数组
static buffer[8];
//开关启动
void Int_DigitalTube_Init()
{SMG_EN=0;LED_EN=0;
}void Int_DigitalTube_DisplaySingle(u8 dig, u8 num)
{P0=0x00;P1&=0xC7;dig<<=3;P1|=dig;P0=num;
}void Int_DigitalTube_Displaynum(long num)
{
u8 i;
for(i=0;i<8;i++)
{buffer[i]=0x00;
}
if(num==0)
{buffer[7]=codes[0];return;
}
if(num<0)
{num=-num;i=7;while(num>0){buffer[i]=codes[num%10];num/=10;i--;}buffer[i]=codes[10];Com_Util_Delay1ms(1);
}else
{i=7;while(num>0){buffer[i]=codes[num%10];num/=10;i--;Com_Util_Delay1ms(1);}
}}void Int_DigitalTube_Refresh()
{u8 i;for(i=0;i<8;i++){Int_DigitalTube_DisplaySingle(i,buffer[i]);}
}
main.c
#include <STC89C5xRC.H>
#include "Com_Util.h"
#include "Int_DigitalTube.h"
void main()
{Int_DigitalTube_Init();Int_DigitalTube_Displaynum(-1235);while(1){Int_DigitalTube_Refresh();}
}
三、模块化编程
随着我们的代码越来越复杂,我们的main.c越来越长,阅读性也越来越差。如果将来开始做项目,我们可能要同时操作好几个模块,这种情况下我们无法再把代码写到同一个文件,而是要分模块管理代码。具体实现方法,就是将源码按照不同功能和模块,拆成若干部分源码,再用头文件相互引用。
1.命名规范
变量命名
函数命名
文件命名
2.代码分层规范
(1)目录
(2)驱动层
所有与芯片直接交互的自身硬件代码,例如GPIO开关、硬件UART/ADC的驱动、计时器等。
目录:Dri/
前缀:Dri_
(3)接口层
位于驱动层之上,通过标准接口驱动的外部硬件代码,没有外部硬件设备,可以不用这一层。
目录:Int/
前缀:Int_
(4)中间层
提供更高级的服务,如操作系统、文件系统、通信协议栈等。
简单项目用不到这一层。
目录:Mid/
前缀:Mid_
(5)应用层
包含应用程序的主要逻辑。实现与上层交互,不直接访问这一层。
目录:App/
前缀:App_
3.创建项目模板
为方便后续项目的创建,可以创建一个基础模板,后边项目全部基于模板创建。
(1)创建一个新的项目,取名为模板。
(2)配置项目
(3)项目规范结构
(4)编写通用代码
Com_Util.c
#include "Com_Util.h"
#include <INTRINS.H>void Com_Util_Delay1ms(u16 count)
{u8 i, j;while (count > 0) {count--;_nop_();i = 2;j = 199;do {while (--j);} while (--i);}
}
Com_Util.h
#ifndef __COM_UTIL_H__
#define __COM_UTIL_H__typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;void Com_Util_Delay1ms(u16 count);#endif // !1
(5)导出模板
下次使用本地模板点开ept文件即可。
相关文章:

嵌入式软件--51单片机 DAY 2
一、数码管 1.数码管概况 2.设计 (1)硬件设计 我们可以通过阴极控制显示的位置,通过阳极控制显示的内容。两个数码管共有8个阴极引脚和16个阳极引脚,如果所有引脚都直接接入MCU,会造成MCU引脚的极大浪费。 为了节省…...

高精度加法,减法,乘法,除法
加法: 大整数该如何储存? 用数组储存: 把个位放在数下标为0的位置,十位放在数组下标为1的位置(也就是高位放在数组的后面) 因为这样,如果需要增加一位最高位,那我们就可以直接在…...
学习计划(大三上)
第二周 总结Java并发编程的艺术 学习JVM(博客文章) 第三周 学习JVM(博客文章) 图解TCP/IP 4章 第四周 完成简历项目 学习JVM(博客文章) 图解TCP/IP 4章 第五周 完成简历项目 深入学习RocketMQ底层…...

【第0006页 · 数组】寻找重复数
【前言】本文以及之后的一些题解都会陆续整理到目录中,若想了解全部题解整理,请看这里: 第0006页 寻找重复数 今天想讨论的一道题在 LeetCode 上评论也是颇为“不错”。有一说一,是道好题,不过我们还是得先理解了它才…...

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——10.继承
1.继承的概念及定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保 持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象 程序设计的层…...

uniapp+vue3实现双通道透明MP4播放支持小程序和h5
双通道透明MP4视频播放的截图 以下是合成后结果,二个合并在一起进行播放 下载资源,打开运行直接使用看到效果 https://download.csdn.net/download/qq_40039641/89715780...
汇编:嵌入式软件架构学习资源
成为嵌入式软件架构设计师需要掌握多方面的知识,包括嵌入式系统、实时操作系统、硬件接口、软件设计模式等。 以下是一些推荐的博客和网站,可以帮助你深入学习嵌入式软件架构设计: ### 1. **Embedded.com** - **网址**: [Embedded.com](htt…...

python编程知识(实现数据加密和解密)
👨💻个人主页:开发者-曼亿点 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 曼亿点 原创 👨💻 收录于专栏:…...

如何使div居中?CSS居中终极指南
前言 长期以来,如何在父元素中居中对齐一个元素,一直是一个让人头疼的问题,随着 CSS 的发展,越来越多的工具可以用来解决这个难题,五花八门的招式一大堆,这篇博客,旨在帮助你理解不同的居中方法…...

Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 本章目录 1.0 基于 Redis 实现的分布式锁存在的问题 2.0 Redisson 功能概述 3.0 Redisson 具体使用 4.0 Redisson 可重入锁原理 5.0 Redisson 锁重试原理 6.0 Redisson WatchDo…...
PostgreSQL中的多版本并发控制(MVCC)深入解析
引言 PostgreSQL作为一款强大的开源关系数据库管理系统,以其高性能、高可靠性和丰富的功能特性而广受欢迎。在并发控制方面,PostgreSQL采用了多版本并发控制(MVCC)机制,该机制为数据库提供了高效的数据访问和更新能力…...

SpringBoot项目-实现简单的CRUD功能和分页查询
背景 本博文主要是创建了一个新的SpringBoot项目,实现基本的增删改查,分页查询,带条件的分页查询功能。是方便初学者学习后端项目的一个比较清晰明了的实践代码,读者可根据博文,从自己动手创建一个新的SpringBoot项目…...
CCF编程能力等级认证GESP—C++2级—20240907
CCF编程能力等级认证GESP—C2级—20240907 单选题(每题 2 分,共 30 分)判断题(每题 2 分,共 20 分)编程题 (每题 25 分,共 50 分)数位之和小杨的矩阵 单选题(每题 2 分,共…...

C语言手撕实战代码_二叉排序树(二叉搜索树)_构建_删除_插入操作详解
二叉排序树习题1.设计算法构建一棵二叉排序树(又称二叉搜索树BST)2.查找二叉排序树中结点为x的结点所在的层数3.删除二叉排序树T中值为x的结点4.查找二叉排序树中所有小于key的关键字5.编写算法,将一棵二叉树t分解成两棵二叉排序树t1和t2,使得t1中的所有…...
YC教父的创始人模式VS职业经理人模式:AI时代的独立开发者崛起
近年来,由风投资助的创始人模式因其相对较低的入门门槛而在创业圈内广受欢迎。然而,真正的挑战在于独立开发者(一人商业)模式。随着AI技术的飞速发展,一人商业模式有望成为未来的主流。本文将探讨独立开发者的工作范围…...

[SUCTF 2019]Pythonginx
给了源码 app.route(/getUrl, methods[GET, POST]) def getUrl():url request.args.get("url")host parse.urlparse(url).hostnameif host suctf.cc:return "我扌 your problem? 111"parts list(urlsplit(url))host parts[1]if host suctf.cc:retu…...
省市县相关校验sql随笔
1.层级校验 要判断一个给定的省、市、区(县)名字是否符合正确的层级关系,假设你的表结构如下: CREATE TABLE regions (id INT PRIMARY KEY,name VARCHAR(255),parent_id INT, -- 指向上一级区域的id,例如市的parent_id指向省的…...
uniapp ios sticky定位,内部 u-tabs(包含scroll-view)消失问题
uniapp中用sticky定位时,元素内部如果有scroll-view,ios在触发bounce机制时,scroll-view的元素会消失,解决方法是页面上包一层高度为100vh的scroll-view <scroll-view style"height: 100vh;" scroll-y scrolltolowe…...

web群集--nginx配置文件location匹配符的优先级顺序详解及验证
文章目录 前言优先级顺序优先级顺序(详解)1. 精确匹配(Exact Match)2. 正则表达式匹配(Regex Match)3. 前缀匹配(Prefix Match) 匹配规则的综合应用验证优先级 前言 location的作用 在 NGINX 中࿰…...

Vivado编译报错黑盒子问题
1 问题描述 “Black Box Instances: Cell **** of type ** has undefined contents and is considered a back box. The contents of this cell must be defined for opt_design to complete successfully.” 检查工程代码提示的模块,该模块为纯手写的Veril…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...