嵌入式软件--51单片机 DAY 2

news2024/11/15 8:30:42

一、数码管

1.数码管概况

2.设计

(1)硬件设计

我们可以通过阴极控制显示的位置,通过阳极控制显示的内容。两个数码管共有8个阴极引脚和16和阳极引脚,如果所有引脚都直接接入MCU,会造成MCU引脚的极大浪费。

为了节省MCU的引脚,我们可以将两个数码管的阳极接在一起。

如此我们就有了8个阴极,8个阳极16个引脚。我们只需通过8个GPIO引脚就能控制这8位数码管的显示内容了。

既然是八位,我们很快想到了38译码器,通过三位二进制数字的输入控制八种结果。

由于51单片高电平的驱动能力很微弱,不足以点亮数码管,因此可以使用74HC245N作为驱动芯片,该芯片的用法如下。

有了74HC245之后,51单片引脚的输出就只用作信号,而驱动数码管的电流则由74HC245的电源提供。

(2)软件设计

为了实现当前需求,需要考虑两点,分别是显示位置和显示内容。确定显示位置称为数码管的位选,确定显示内容称为数码管的段选。

1》位选

P12  P13  P14控制显示位置,连接数码管阴极,如果为0低电平就能导通显示。故控制位选。

P13接到了A0,P14接到了A1,P15接到了A2。

例:如果p15-p13输入为000,那么与y0相连的1号数码显示。

如果001,第二位显示

010,第三位显示

011,第四位显示

100,第五位显示

······

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, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 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第一个位置,显示内容为2
    while (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, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F  // 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();
    };
}

上图的效果就实现了。

三、模块化编程

1.命名规范

变量命名

函数命名

文件命名

2.代码分层规范

(1)目录

(2)驱动层

所有与芯片直接交互的自身硬件代码,例如GPIO开关、硬件UART/ADC的驱动、计时器等。

目录:Dri/

前缀:Dri_

(3)接口层

位于驱动层之上,通过标准接口驱动的外部硬件代码,没有外部硬件设备,可以不用这一层。

目录:Int/

前缀:Int_

(4)中间层

提供更高级的服务,如操作系统、文件系统、通信协议栈等。

简单项目用不到这一层。

目录:Mid/

前缀:Mid_

(5)应用层

包含应用程序的主要逻辑。实现与上层交互,不直接访问这一层。

目录:App/

前缀:App_

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java编程基础-类加载机制

文章目录 基本概念类加载器的层次结构类的加载过程双亲委派模型自定义类加载器注意事项 Java 类加载器&#xff08;Class Loader&#xff09;是 Java 运行时环境的一部分&#xff0c;它负责在应用程序运行时加载类和接口的字节码。类加载器对于 Java 的动态特性和安全性有着至关…

Microsoft DirectML 现在支持 Copilot+ PC 和 WebNN

DirectML 是一个底层应用程序接口&#xff0c;使开发人员能够在任何兼容 DirectX 12 的 AMD、英特尔和英伟达&#xff08;NVIDIA&#xff09;GPU 上运行机器学习工作负载 。它首次出现在Windows 10 的 1903 版本中。最近&#xff0c;微软 开始在 DirectML 中支持现代 SoC 中的N…

新能源汽车超级电容和电池能量管理系统的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 电池模型 4.2 电池荷电状态&#xff08;SOC&#xff09;估算 4.3 超级电容器模型 4.4 能量管理 5.完整工程文件 1.课题概述 新能源汽车的能量管理系统&#xff08;Energy Management System, EMS…

Conda离线部署django

要在没有网络连接的环境中使用conda部署Django&#xff0c;你需要预先在有网络连接的机器上创建一个包含所有必要包的环境&#xff0c;并导出该环境的配置文件。然后&#xff0c;你可以将这个配置文件和必要的包传输到目标机器上进行安装。 下面是详细的步骤&#xff1a; 1. …

mysql优化案例分享

一、mysql介绍 1、InnoDB引擎 mysql5.5.8版本开始后。InnoDB引擎就是默认存储引擎&#xff0c;本文介绍知识点也都是围绕该引擎展开。 知识点1聚集存储 InnoDB引擎采用聚集存储&#xff0c;即每张表的存储都是主键的顺序进行存放&#xff0c;也就是每行存储的物理顺序和主键…

基于SparkGraphX实现带权重的PageRank算法

基于SparkGraphX实现带权重的PageRank算法 文章目录 基于SparkGraphX实现带权重的PageRank算法一、什么是PageRank算法二、PageRank算法的实现三、PagRank算法实现步骤四、大数据量的PageRank算法实现总结 一、什么是PageRank算法 网页排序算法之PageRank 二、PageRank算法的…

【AI视频】Runway注册、基本设置、主界面详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI视频 | Runway 文章目录 &#x1f4af;前言&#x1f4af;Runway的正确启动方式推荐使用Google Chrome打开Chrome翻译 &#x1f4af;Runway的注册&#x1f4af;My Account&#xff08;我的账户&#xff09;General&#xff08;常…

HTTPie CLI:重塑命令行HTTP交互的现代工具

更多内容前往个人网站&#xff1a;孔乙己大叔 在快速发展的数字时代&#xff0c;API&#xff08;应用程序编程接口&#xff09;已成为连接不同服务和应用的桥梁。无论是开发者还是系统管理员&#xff0c;与HTTP服务进行有效且高效的交互都是日常工作的核心部分。然而&#xff0…

idea中git提交或push到远程后回退到之前的某次提交简单有效的解决方案

场景&#xff1a; 1、先模拟出团队多人开发多分支&#xff0c;在各个分支分别提交代码&#xff0c;然后都合并到master分支 2、模拟如下两个分支dev、dev-0902合并到master&#xff0c;并且合并master后push到远程了 3、假如更新版本计划有变&#xff0c;只上dev-0902分支&…

stm32之I2C通信外设

系列文章目录 1. stm32之I2C通信协议 2. stm32之软件I2C读写MPU6050陀螺仪、加速度传感器应用案例 3. stm32之硬件I2C读写MPU6050陀螺仪、加速度传感器应用案例 文章目录 系列文章目录前言一、I2C通信外设1.1 I2C外设简介1.2 软件模拟和硬件外设对比 二、I2C外设电路结构2.1 I…

【数据结构-二维前缀异或和】【分区算法优化】力扣1738. 找出第 K 大的异或坐标值

给你一个二维矩阵 matrix 和一个整数 k &#xff0c;矩阵大小为 m x n 由非负整数组成。 矩阵中坐标 (a, b) 的 目标值 可以通过对所有元素 matrix[i][j] 执行异或运算得到&#xff0c;其中 i 和 j 满足 0 < i < a < m 且 0 < j < b < n&#xff08;下标从 …

IP网络广播系统(IP网络广播系统是什么及它的优势与应用)

一、引言 在当今数字化的时代&#xff0c;音频传播技术也在不断革新。IP网络广播系统作为一种先进的音频传输解决方案&#xff0c;正逐渐在各个领域发挥重要作用。那么&#xff0c;究竟什么是IP网络广播系统呢&#xff1f;它又有着怎样独特的优势和广泛的应用呢&#xff1f;本…

1、Django Admin学习模型

此专栏应用环境和模型基于此文 开发环境 系统&#xff1a;windows11 开发工具&#xff1a;vscode 开发语言&#xff1a;python 3.8 开发框架&#xff1a;django 3.2 数据库&#xff1a;mysql8.4.1 项目目录 settings 注册两个应用 INSTALLED_APPS [django.contrib.ad…

免下载看视频,使用极空间部署P2P磁力种子流媒体服务器『TorrServer』

免下载看视频&#xff0c;使用极空间部署P2P磁力种子流媒体服务器『TorrServer』 哈喽小伙伴们好&#xff0c;我是Stark-C~ 说到在NAS上的观影体验&#xff0c;很多小伙伴的理解可能就是先下载到本地&#xff0c;然后在使用播放器打开观看。今天为大家分享另外一种观影方式&a…

JS设计模式之“语言之魂” - 原型模式

前言 当我们学习JavaScript的时候&#xff0c;经常会听到原型&#xff08;prototype)、原型链&#xff08;prototype chain&#xff09;和原型模式&#xff08;prototype pattern&#xff09;这些概念&#xff0c;它们之间有什么关联呢&#xff1f;怎么样才能使用好原型模式呢…

linux 硬件 arm架构

一.ARM&#xff1a; 1.时钟晶振&#xff1a; 在单片机系统里晶振的作用非常大&#xff0c;他结合单片机内部的电路&#xff0c;产生单片机所必须的时钟频率&#xff0c;单片机的一切指令的执行都是建立在这个基础上的&#xff0c;晶振的提供的时钟频率越高&#xff0c;那单片机…

Valley14.2免授权php跨境电商在线商城

6Valley 14.2 Nulled – 多供应商电子商务 – 完整的电子商务移动应用程序、Web、卖家和管理面板 后台可自定义收款&#xff0c;和翻译多国语言&#xff0c;中文需要自己对比翻译&#xff01;一般用不到中文。毕竟是跨境电商平台 带商家即时通讯&#xff0c;全套带文档和APP双端…

DReg-NeRF: Deep Registration for Neural Radiance Fields论文解读

目录 一、导言 二、NeRF2NeRF 三、相关工作 1、神经辐射场 2、点云配准 3、NeRF配准 四、DReg-NeRF 1、NeRF神经辐射场查询 2、特征提取 3、transformer 4、Decoder 五、损失函数 一、导言 该论文来自于ICCV2023&#xff0c;主要提到一种DReg-NeRF的配准方法&#…

SQL 数据查询

文章目录 3.4.1 单表查询定义特点单表无条件查询单表带条件查询对查询结果进行排序限制查询结果数量 3.4.2 分组查询定义特点&#xff1a;聚集函数GROUP BY短语HAVING子句分组查询小结 3.4.3 连接查询定义特点&#xff1a;等值连接与非等值连接查询自然连接&#xff08;内连接&…

全局安装react

1、首先安装react脚手架 npm install -g create-react-app2、创建react项目 create-react-app my-app3、 PS D:\桌面\papers\subject> create-react-app my-react-appCreating a new React app in D:\桌面\papers\subject\my-react-app.Installing packages. This might …