【51单片机快速入门指南】2.1:数码管显示数字、小数 (科学计数法)

目录

  • 硬知识
    • 数码管简介
    • 多位数码管简介
    • 数码管动态显示原理
    • 74HC245 芯片简介
    • 74HC138 芯片简介
  • 上机实战
    • 源码
      • Tube.c
      • Tube.h
      • main.c
  • 效果
    • 显示整数
      • 正数
      • 负数
    • 显示小数(保留三位有效数字)
      • 正数
      • 负数

普中51-单核-A2
STC89C52
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


硬知识

选自《普中51单片机开发攻略_V1.2》

数码管简介

       数码管是一种半导体发光器件,也称 LED 数码管,其基本单元是发光二极管。
       数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元,也就是多一个小数点(DP),这个小数点可以更精确的表示数码管想要显示的内容;
       按能显示多少个【8】可分为 1 位、 2 位、 3 位、 4 位、 5 位、 6 位、7 位等数码管。
       按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。
       共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极 COM 接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。
       共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极 COM 接到地线 GND 上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。
       不同位数的数码管实物图如下所示:
在这里插入图片描述
在这里插入图片描述

       由图可知,一位数码管的引脚是 10 个,显示一个 8 字需要 7 个小段, 另外还有一个小数点,所以其内部一共有 8 个小的发光二极管,最后还有一个 公共端,多数生产商为了封装统一,单位数码管都封装 10 个引脚,其中第 3 和 第 8 引脚是连接在一起的。
       公共端可分为共阳极和共阴极,图中间为共阳极内部原理图,右图为共阴极内部原理图。
       对共阴极数码管来说,其 8 个发光二极管的阴极在数码管内部全部连接在一起,所以称“共阴”,而它们的阳极是独立的,通常在设计电路时一般把阴极接地。 当我们给数码管的任意一个阳极加一个高电平时,对应的这个发光二极管就点亮 了。如果想要显示出一个 8 字,并且把右下角的小数点也点亮的话,可以给 8 个阳极全部送高电平,如果想让它显示出一个 0 字,那么我们可以除了给第“g, dp” 这两位送低电平外,其余引脚全部都送高电平,这样它就显示出 0 字了。
       如果使用共阴数码管,需要注意增加单片机 IO 口驱动电流,因为共阴数码管是要靠单片机 IO 口输出电流来点亮的,但单片机 I/O 口难以输出稳定的、如此大的电流,所以数码管与单片机连接时需要加驱动电路,可以用上拉电阻的方法或使用专门的数码管驱动芯片,比如 74HC573、74HC245 等,其输出电流较大, 电路接口简单。
       共阳极数码管其内部 8 个发光二极管的所有阳极全部连接在一起,电路连接时,公共端接高电平,因此我们要点亮哪个发光管二极管就需要给阴极送低电平, 此时显示数字的编码与共阴极编码是相反的关系,数码管内部发光二极管点亮时,也需要 5mA 以上的电流,而且电流不可过大,否则会烧坏发光二极管。因此不仅要防止数码管电流过大,同时要防止流经数码管的电流集中到单片机时电流不能过大,否则会损坏主芯片。
       一般共阳极数码管更为常用,这是因为数码管的非公共端往往接在 IC 芯片的 I/O 上,而 IC 芯片的驱动能力往往是比较小的,如果采用共阴极数码管,它的驱动端在非公共端, 就有可能受限于 IC 芯片输出电流不够而显示昏暗,要外加上拉电阻或者是增加三极管加大驱动能力。但是 IC 芯片的灌电流, 即输入电流范围比较大。所以使用共阳极数码管的好处是:将驱动数码管的工作交到公共端(一般接驱动电源),加大驱动电源的功率自然要比加大 IC 芯片 I/O 口的驱动电流简单许多。另一方面,这样也能减轻主芯片的负担。

多位数码管简介

       多位数码管,即两个或两个以上单个数码管并列集中在一起形成一体的数码管。当多位一体时,它们内部的公共端是独立的,而负责显示什么数字的段线 (a-dp)全部是连接在一起的,独立的公共端可以控制多位一体中的哪一位数码管点亮,而连接在一起的段线可以控制这个能点亮数码管亮什么数字,通常把公共端叫做“位选线”,连接在一起的段线叫做“段选线”,有了这两个线后, 通过单片机及外部驱动电路就可以控制任意的数码管显示任意的数字了。

数码管动态显示原理

       当多位数码管应用于某一系统时,它们的“位选”是可独立控制的,而“段选”是连接在一起的,我们可以通过位选信号控制哪几个数码管亮,而在同一时刻,位选选通的所有数码管上显示的数字始终都是一样的,因为它们的段选是连接在一起的,送入所有数码管的段选信号都是相同的,所以它们显示的数字必定一样,数码管的这种显示方法叫做静态显示。
       而动态显示,就是利用减少段选线,分开位选线,利用位选线不同时选择通断,改变段选数据来实现的。比如在第一次选中第一位数码管时,给段选数据 0, 下一次位选中第二位数码管时显示 1。为了在显示 1 的时候,0 不会消失(当然实际上是消失了),必须在人肉眼观察不到的时间里再次点亮第一次点亮的 0。 而这时就需要记住,人的肉眼正常情况下只能分辨变化超过 24ms 间隔的运动。 也就是说,在下一次点亮 0 这个数字的时间差不得大于 24ms。这时就会发现, 数码管点亮是在向右或者向左一位一位点亮,形成了动态效果。如果把间隔时间改长就能直接展现这一现象。

74HC245 芯片简介

在这里插入图片描述

       74HC245 是一种三态输出、八路信号收发器,主要应用于大屏显示,以及其它的消费类电子产品中增加驱动能力。
在这里插入图片描述
       给 OE 使能管脚低电平,DIR 管脚为高电平传输方向是 A->B 输出,DIR 为低电平传输方向是 B->A,至于输出高电平还是输出低电平取决于输入端的状态,如果输入为低电平,输出即为低;输入为高电平,输出即为高。如果 OE 使能管脚为高电平, 不论 DIR 管脚是高还是低,输出是高阻态。
       开发板上OE管脚已接GND,DIR管脚已接VCC,传输方向是 A->B。

74HC138 芯片简介

在这里插入图片描述
       74HC138D 是一种三通道输入、八通道输出译码器,主要应用于消费类电子产品。
在这里插入图片描述
在这里插入图片描述
       给 E1、E2 使能管脚低电平,E3 管脚为高电平,至于哪个管脚输出有效电平(低电平),要看 A0,A1,A2 输入管脚的电平状态。如果 A0,A1,A2 都为低电平,则 Y0 输出有效电平(低电平),其他管脚均输出高电平。如果 A0 为高电平,A1, A2 都为低电平,则 Y1 输出有效电平(低电平),其他管脚均输出高电平。
       A0、A1、A2 输入就相当于 3 位 2 进制数,A0 是低位,A1 是次高位,A2 是高位。而 Y0~Y7 具体哪一个输出有效电平,就看输入二进制对应的十进制数值。比如输入是 101(A2,A1,A0),其对应的十进制数是 5,所以 Y5 输出有效电平(低电平)。

上机实战

stdint.h见【51单片机快速入门指南】1:基础知识和工程创建

源码

Tube.c

#include <REGX52.H>
#include "intrins.h"
#include "stdint.h"
#include "Tube.h"#define Tube_Port P0sbit P74138_A0 = P2^2;
sbit P74138_A1 = P2^3;
sbit P74138_A2 = P2^4;//显示的延时 400us @11.0592MHz
void LED_Tube_Delay()
{unsigned char i;_nop_();i = 181;while (--i);
}//位选
void F74138(uint8_t num)
{num &= 7;P74138_A0 = (num & 1);P74138_A1 = (num & 2) >> 1;P74138_A2 = (num & 4) >> 2;
}code uint8_t Tube_Codes_0ToF[] =
{Tube_Code_0,Tube_Code_1,Tube_Code_2,Tube_Code_3,Tube_Code_4,Tube_Code_5,Tube_Code_6,Tube_Code_7,Tube_Code_8,Tube_Code_9,Tube_Code_A,Tube_Code_b,Tube_Code_C,Tube_Code_d,Tube_Code_E,Tube_Code_F
};//以科学计数法显示小数
void Display_Double(double Num)
{uint8_t i = 0;int8_t pow = 0;uint8_t DisplayNum = 0;double Num_clone;char Tube_Double_Buffer[8] = {0};if (Num < 0){Tube_Double_Buffer[7] = Tube_Code_Negative_Sign;				Num = -Num;}if (Num < 1e-8)													//视为0{for(i = 0; i < 7; ++i)Tube_Double_Buffer[i + 1] = Tube_Code_NULL;Tube_Double_Buffer[0] = Tube_Codes_0ToF[0];}else if (Num > 1e8)												//视为溢出,Error{Tube_Double_Buffer[6] = Tube_Code_NULL;Tube_Double_Buffer[5] = Tube_Code_E;	Tube_Double_Buffer[4] = Tube_Code_r;						Tube_Double_Buffer[3] = Tube_Code_r;						Tube_Double_Buffer[2] = Tube_Code_o;						Tube_Double_Buffer[1] = Tube_Code_r;						Tube_Double_Buffer[0] = Tube_Code_NULL;}else {Num_clone = Num;if(Num_clone < 1000){while(Num_clone < 1000){Num_clone *= 10;++pow;}pow = 3-pow;											//求指数}else{pow = 3;while(Num_clone > 9999){Num_clone /= 10;++pow;												//求指数}}Num_clone /= 10;for(i = 0; i < 3; ++i)										//三位有效数字{DisplayNum = (int)(Num_clone + (i == 0) * 0.5) % 10;	//末位四舍五入Tube_Double_Buffer[i + 4] = Tube_Codes_0ToF[DisplayNum];Num_clone /= 10;}Tube_Double_Buffer[6] |= Tube_Code_Dot;						//补小数点Tube_Double_Buffer[3] = Tube_Code_E;	if(pow < 0){Tube_Double_Buffer[2] = Tube_Code_Negative_Sign;		//指数符号为负pow = -pow;}for(i = 0; i < 2; ++i){DisplayNum = pow % 10;Tube_Double_Buffer[i] = Tube_Codes_0ToF[DisplayNum];	//指数pow /= 10;}}for(i = 0; i < 8; ++i){Tube_Port = Tube_Code_NULL;									//关闭位选F74138(i);													Tube_Port = Tube_Double_Buffer[i];							//显示LED_Tube_Delay();}return;
}//显示整数
void Display_Int(int32_t Num)
{uint8_t i = 0;uint8_t DisplayNum = 0;char Tube_Double_Buffer[8] = {0};if(Num >= 10000000 || Num <= -10000000)									{Display_Double((double)Num);							//以指数形式输出return;}else{if(Num < 0){Tube_Double_Buffer[7] = Tube_Code_Negative_Sign;	//负号Num = -Num;}for(i = 0; i < 7; ++i){DisplayNum = Num % 10;if(Num == 0 && i != 0)Tube_Double_Buffer[i] = Tube_Code_NULL;elseTube_Double_Buffer[i] = Tube_Codes_0ToF[DisplayNum];Num /= 10;}for(i = 0; i < 8; ++i){Tube_Port = Tube_Code_NULL;					//关闭位选F74138(i);Tube_Port = Tube_Double_Buffer[i];			//显示LED_Tube_Delay();}return;}
}//显示数字
void Display_Num(double Num)
{if(Num == (int32_t)Num)Display_Int((int32_t)Num);elseDisplay_Double(Num);return;
}

Tube.h

#ifndef TUBE_H_
#define TUBE_H_#define Tube_Code_NULL 0x00#define Tube_Code_0 0x3f
#define Tube_Code_1 0x06
#define Tube_Code_2 0x5b
#define Tube_Code_3 0x4f
#define Tube_Code_4 0x66
#define Tube_Code_5 0x6d
#define Tube_Code_6 0x7d
#define Tube_Code_7 0x07
#define Tube_Code_8 0x7f
#define Tube_Code_9 0x6f#define Tube_Code_A 0x77
#define Tube_Code_b 0x7c
#define Tube_Code_C 0x39
#define Tube_Code_c 0x58
#define Tube_Code_d 0x5e
#define Tube_Code_E 0x79
#define Tube_Code_F 0x71
#define Tube_Code_G 0x3d
#define Tube_Code_H 0x76
#define Tube_Code_I 0x30
#define Tube_Code_i 0x10
#define Tube_Code_J 0x0e
#define Tube_Code_K	0x7a
#define Tube_Code_L 0x38
#define Tube_Code_M 0x55
#define Tube_Code_n	0x54
#define Tube_Code_o 0x5c
#define Tube_Code_P 0x73
#define Tube_Code_q 0x67
#define Tube_Code_r 0x50
#define Tube_Code_S 0x64
#define Tube_Code_t 0x78
#define Tube_Code_U	0x3e
#define Tube_Code_u 0x1c
#define Tube_Code_v 0x62
#define Tube_Code_W 0x6a
#define Tube_Code_X 0x36
#define Tube_Code_y 0x6e
#define Tube_Code_Z 0x49#define Tube_Code_Dot 0x80
#define Tube_Code_Negative_Sign 0x40void Display_Int(int32_t Num);
void Display_Double(double Num);
void Display_Num(double Num);#endif

main.c

#include <REGX52.H>
#include "intrins.h"
#include "stdint.h"
#include "Tube.h"void main(void)
{	while(1){Display_Num(114514);}		
}

效果

显示整数

正数

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

较大的数
在这里插入图片描述
在这里插入图片描述

负数

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

显示小数(保留三位有效数字)

正数

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

负数

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

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

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

相关文章

防USB病毒

Windows XP 需要用此步驟。Windows 7 就不需要了。 步驟1. 於「開始/執行」中執行 regedit&#xff0c;進入登錄編輯程式。2. 找到機碼名稱: HKEY_CURRENT_USER\Software\microsoft\Windows\CurrentVersion\Explorer\MountPoints23. 點選該機碼&#xff0c;按右鍵選擇「使用權限…

项目案例分享四:DC升级后Sysvol停止复制,日志报13508

最近在240个站点AD升级项目过程中遇到个别DC升级后Sysvol里面的内容同步到一半就不动了&#xff0c;连续一个星期都没有动静&#xff0c;今天在此跟大家分享此问题的处理方法。1.环境介绍其中DC01和DC02是中国总部的DC&#xff0c;中国地区其他两百多站点通过KCC生成的链路和DC…

【51单片机快速入门指南】2.2:任意位/任意长度数码管显示数字、小数

目录源码Tube.cTube.hmain.c效果8位数码管正整数负整数正小数负小数6位数码管正整数负整数正小数负小数4位数码管正整数负整数正小数负小数普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 源码 移植时主要只修改Tube_Num数量、…

【51单片机快速入门指南】2.3:GPIO读取矩阵键盘 8个IO读16键

目录硬知识矩阵键盘介绍测试程序Key_Board.cKey_Board.hmain.c实验现象普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 选自《普中51单片机开发攻略_V1.2》 矩阵键盘介绍 独立按键与单片机连接时&#xff0c;每一个按键…

【51单片机快速入门指南】2.4:74HC595、LED点阵屏及其SPI控制

目录硬知识IO 口扩展方式-串转并74HC595 芯片介绍硬件设计测试源码HC74595.cHC74595.hmain.h实验现象SPI控制普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 选自《普中51单片机开发攻略_V1.2》 IO 口扩展方式-串转并 …

【51单片机快速入门指南】3:中断系统

目录硬知识中断概念中断系统中断结构中断优先级中断处理普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 硬知识 选自《普中51单片机开发攻略_V1.2》、《STC89C52系列单片机器件手册》 中断概念 中断是为使单片机具有对外部或内…

正能量之项目经理的自我修养

正能量之项目经理的自我修养 作者&#xff1a;张子良 版权所有&#xff0c;转载请注明出处 引子 还记得曾经看过的《喜剧之王》么&#xff1f;还记的那曾经经典的台词么&#xff1a;“我不是死跑龙套的”&#xff0c;“人如果没有理想&#xff0c;和咸鱼又有什么区别呢&#xf…

利用D触发器和异或门实现两个IO解读电机编码器的计数值和方向

目录反转变正转正转变反转iPad Pro 2020 14.8.1 仿真软件&#xff1a;iCircuit 突发奇想&#xff0c;做个记录。应该可以用于诸如51单片机、Arduino或是电赛中可能用到的MSP430G2553这类外设十分稀缺的单片机上。一个想法&#xff0c;啊&#xff0c;不一定对。 黄色波形是编码…

TCP协议的三次握手和四次分手

HTTP连接 HTTP协议即超文本传送协议(Hypertext Transfer Protocol )&#xff0c;是Web联网的基础&#xff0c;也是手机联网常用的协议之一&#xff0c;HTTP协议是建立在TCP协议之上的一种应用。HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应&#xff0c;在请…

CountDownLatch线程同步辅助

2019独角兽企业重金招聘Python工程师标准>>> http://bughope.iteye.com/blog/2081935 在上一篇文章中写道用一个静态的变量保存线程的执行状态,并用时间等待的方法后来仔细考虑,其实是 线程不安全的.多个线程同时执行这个类时,这个静态变量的值就不能保证了. 用一个…

【51单片机快速入门指南】3.1:配置外部中断触发方式和中断优先级

目录源码EXTI.cEXTI.hmain.c实验现象普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 源码 stdint.h见【51单片机快速入门指南】1&#xff1a;基础知识和工程创建 中断知识见【51单片机快速入门指南】3&#xff1a;中断系统 将…

(转)工厂方法模式

转自&#xff1a;http://www.jellythink.com/archives/62 问题描述 之前讲到了C设计模式——简单工厂模式&#xff0c;由于简单工厂模式的局限性&#xff0c;比如&#xff1a;工厂现在能生产ProductA、ProductB和ProductC三种产品了&#xff0c;此时&#xff0c;需要增加生产Pr…

一种父线程阻塞等待子线程的有效方法

最近在做一个查询优化时&#xff0c;考虑到一次查询耗时较多&#xff0c;所以打算用多线程来做&#xff0c;之前是串行查询。比如一个用户查询触发50个线程&#xff0c;在只有一个用户的情况下&#xff0c;性能比串行查询确实提高了许多&#xff0c;但当多个用户同时触发查询的…

C语言利用循环队列实现滑动平均值滤波器,提高计算速度

目录源码Filter.cFilter.h使用效果普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 串口示波器&#xff1a;Vofa 1.3.10 网上查到的滑动平均值滤波器在计算平均值的时候还要再for累加一遍&#xff0c;这太浪费时间了&#xff0c…

Exchange Server 2013日记功能

9.6 日记9.6.1 日记功能为什么很重要首先&#xff0c;了解日记功能与存档功能之间的区别十分重要&#xff1a;首先&#xff0c;了解日记功能与存档功能之间的区别十分重要&#xff1a; “日记”可以记录组织中的所有通信&#xff08;包括电子邮件通信&#xff09;&#xff0c;以…

VB数据库经典实例总结(二)

大家先看一张似图非图的图、 我们先称它为“过程”也许有不对的地方&#xff0c;在我学数据库到这个阶段、到这个刚刚接触、初生牛犊不怕虎的阶段对它的理解是这样的、所有的都是这个过程、只是在这中间掺杂了一些知识点&#xff08;我们要掌握的&#xff09;针对有些个别的&am…

适用于单片机的FFT快速傅里叶变换算法,51单片机都能用

目录源码FFT.cFFT.h使用方法效果其他部分的代码main.c普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 算法来自FFT算法的使用说明与C语言版实现源码 —— 原作者&#xff1a;吉帅虎 速度更快的版本见C语言实现的FFT与IFFT源代码…

第9课 - 函数重载分析(下)

第9课 - 函数重载分析&#xff08;下&#xff09; 1. 重载与指针 1.1 下面的函数指针将保存哪个函数的地址&#xff1f; 1.2 函数重载遇上函数指针 将重载函数名赋值给函数指针时&#xff1a; &#xff08;1&#xff09;根据重载规则挑选与函数指针参数列表一致的候选者 &#…

常见窗函数的C语言实现及其形状,适用于单片机、DSP作FFT运算

目录源码WindowFunction.cWindowFunction.h使用形状三角窗巴特利特窗巴特利特-汉宁窗布莱克曼窗布莱克曼-哈里斯窗博曼窗切比雪夫窗平顶窗高斯窗海明窗汉宁窗纳托尔窗Parzen窗矩形窗&#xff08;模拟&#xff09;效果无窗汉宁窗平顶窗平台&#xff1a;Windows 10 20H2 Visual …

.net Json JavaScriptSerializer JsonHelper类

结合.net 的JavaScriptSerializer 类实现Json数据处理 调用1&#xff1a; Model.Users m BLL.UsersBLL.GetUserById(Convert.ToInt32(id));string result "";if (m ! null)result JsonHelper.ObjectToJSON(m);context.Response.Write(result); 调用2&#xff…