当前位置: 首页 > ai >正文

【Protues仿真】基于AT89C52单片机的数码管驱动事例

目录

1 AT89C52单片机驱动单个数码管

1.1 数码管基础知识

1.1.1外观与引脚

1.1.2 共阴(CC) vs 共阳(CA)

1.1.3段码表(以数字1为例)

1.1.4驱动方式A. 直连IO(最简单,占用IO多)一个段一根线,共阴或共阳公共端固定接GND/VCC。适合单个数码管、教学实验。

1.1.6 快速排查清单

1.2 完整例子1——AT89C52单片机驱动单个数码管0~9循环计数

1.2.1 电路原理图

1.2.2 控制程序

1.3 完整例子2——AT89C52单片机实现比分计数器

1.3.1 74HC573透明锁存器

1.3.2 引脚与封装

1.3.3 真值表(简化)

1.3.4 典型应用:51 单片机驱动 4 位共阴七段数码管

1.3.5 最小示例(Keil C,12 MHz 晶振)

1.3.6 常见问题速查

1.4 AT89C52单片机实现比分计数器电路原理图

1.5 控制程序


摘要:本文介绍了AT89C52单片机驱动数码管的基础知识及实现方法。主要内容包括:1.数码管工作原理,包括共阴/共阳结构、段码表、驱动方式;2.两个具体应用实例:单个数码管0-9循环计数和比分计数器;3.详细硬件电路设计(含74HC573锁存器应用)和配套C语言程序实现;4.常见问题排查指南。通过定时器中断实现精确控制,采用动态扫描技术实现多位显示,并提供了完整的代码示例和电路原理图。

1 AT89C52单片机驱动单个数码管

1.1 数码管基础知识

7段数码管(7-segment display)是最常见的数字显示器件之一,广泛用于仪表、时钟、计数器等场合。

1.1.1外观与引脚

如上图所示,7个发光段分别命名为 a、b、c、d、e、f、g(顺时针方向排列),再加一个小数点 dp。

单个数码管常见封装:
直插 DIP-10(2.54 mm)
贴片 SMD-10

引脚排列没有统一标准,务必看数据手册或用万用表「二极管档」量:红笔固定接公共端,黑笔依次碰其它脚,某一段亮就说明该脚对应段。

1.1.2 共阴(CC) vs 共阳(CA)

共阴:所有 LED 阴极并在一起 → 公共脚接 GND,要点亮某段就给该段阳极送高电平(+V)。

共阳:所有 LED 阳极并在一起 → 公共脚接 +V,要点亮某段就给该段阴极送低电平(GND)。

记忆口诀:
共阴 = “给1亮”
共阳 = “给0亮”

1.1.3段码表(以数字1为例)


数字1需要点亮 b、c 两段。

类型

a b c d e f g dp

十六进制

说明

共阴

0 1 1 0 0 0 0 0

0x06

b、c=1,其余=0

共阳

1 0 0 1 1 1 1 1

0xF9

b、c=0,其余=1

完整段码速查:
0 1 2 3 4 5 6 7 8 9
共阴:0x3F 0x06 0x5B 0x4F 0x66 0x6D 0x7D 0x07 0x7F 0x6F
共阳:取反即可(~共阴 & 0xFF)

1.1.4驱动方式
A. 直连IO(最简单,占用IO多)
一个段一根线,共阴或共阳公共端固定接GND/VCC。
适合单个数码管、教学实验。

B. 译码/驱动芯片
74HC47(BCD→7段,共阳)
CD4511(BCD→7段,带锁存,共阴)
TM1637、MAX7219(集成扫描与亮度调节)

C. MCU+三极管/MOS(动态扫描多个位)
节省IO:段线共用,位选线轮流导通。
需要定时刷新(>100 Hz 无闪烁)。
1.1.5 多连排数码管动态扫描
以4位共阴为例:

12个IO:8段+4位选

流程:

关所有位(位选高)

送第N位段码

打开第N位(位选低)

延时1~2 ms

回到1,循环

伪代码:

const uint8_t seg_cc[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void display_4digit(uint16_t val){for(uint8_t pos=0; pos<4; pos++){set_digit_OFF();output_SEG(seg_cc[val%10]); // 输出段码set_digit_ON(pos);          // 打开位delay_ms(2);val /= 10;}
}

1.1.6 快速排查清单

不亮:检查公共端电压、限流电阻(每段330 Ω~1 kΩ)。

乱亮:段码高低反了(把共阴/共阳搞反)。

闪烁:动态扫描频率太低,提高刷新或加定时器中断。

1.2 完整例子1——AT89C52单片机驱动单个数码管0~9循环计数

1.2.1 电路原理图

如上图所示,AT89C52单片机驱动单个数码管0~9循环计数电路原理图由AT89C52单片机、上拉排阻、数码管、晶振和复位电路组成,通过AT89C52单片机控制P0的输出电平实现数码管数字显示的控制。

1.2.2 控制程序

//头文件与位定义
# include <reg51.h>
# include <intrins.h>
//数码管对应数字
// 0:10000000 1:11110010 2:01001000	3:01100000 4:00110010 5:00100100 6:00000100 7:11110000 8:00000000 9:00100000
unsigned char display_table[] ={ 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0, 0x00, 0x20 }; // 	 共阳极数码管显示编码16进制
unsigned int i=0;
//定时器T0初始化
void inittimer()
{TMOD = 0x01;        // T0 方式 1TH0  = 0xFC;        // 1 msTL0  = 0x18;TR0  = 1; ET0 = 1; EA = 1;//中断设置值
}
//定时器延时函数
void Delay(unsigned int ms)
{unsigned int i;for (i = 0; i < ms; i++){while (!TF0);  // 等待定时器T0溢出TF0 = 0;       // 清除溢出标志}
}
//定时器T0模式1中断服务函数
void Timer0_ISR() interrupt 1
{TH0 = 0xFC; TL0 = 0x18;}
void main()		   // 主程序
{inittimer();while(1){P0 = 0x00;for(i = 0; i < 10; i++){if (i == 10	)	 // 当i=10时,将0清零。就是当数码管显示9后,再从0开始{i = 0;}P0 = display_table[i];Delay(1000);}}
}

如上程序所示,程序使用定时器T0的T1模式实现精确延时控制,从而实现控制数码管的显数显示。

1.3 完整例子2——AT89C52单片机实现比分计数器

1.3.1 74HC573透明锁存器

74HC573是一块“8 位透明锁存器(Octal D-Type Transparent Latch)”,带三态输出,最常被拿来做“IO口扩展+数据保持”,比如用3片74HC573 就能让 8 位单片机口线分时输出 24 位数据,正好驱动 8×16 LED 点阵或多位七段数码管

1.3.2 引脚与封装

封装:DIP-20、SOP-20、TSSOP-20 等

关键脚位(俯视图左下角圆点逆时针数):
1 OE̅ 输出使能(低电平有效,拉高则 Q0~Q7 高阻)
11 LE 锁存使能(高=透明,低=锁存)
2~9 D0~D7 数据输入
19~12 Q0~Q7 三态输出
20 VCC,10 GND

1.3.3 真值表(简化)

OE̅

LE

D

Q

0

1

X

随D(透明)

0

0

X

保持上次数据

1

X

X

高阻态

1.3.4 典型应用:51 单片机驱动 4 位共阴七段数码管

接线示意
MCU-P0 → 74HC573(段码) → 330 Ω 电阻 → a~g,dp
MCU-P2.0~P2.3 → 三极管 → 位选线(共阴端)
锁存器:
OE̅ 接地(一直使能)
LE → 单片机 P3.6(段锁存)

时序

1把段码送 P0

2给 LE 一个高脉冲(锁存段码)

3打开对应位选线,延时 2 ms

4关位选、重复扫描

1.3.5 最小示例(Keil C,12 MHz 晶振)

#include <reg52.h>
sbit HC573_LE = P3^6;      // 段锁存
unsigned char code seg7[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void delay_ms(unsigned char t)
{unsigned int i;while(t--) for(i=0;i<123;i++);
}
void main()
{unsigned char i=0;while(1){P0 = seg7[i];          // 送段码HC573_LE = 1;          // 锁存HC573_LE = 0;P2 = ~(1<<0);          // 点亮第 1 位delay_ms(2);P2 = 0xFF;             // 关闭所有位if(++i>9) i=0;}
}

1.3.6 常见问题速查

输出全高阻:OE̅ 被拉高,请接地。

数据写不进去:LE 没有拉到高电平或脉冲宽度不足(>10 ns 即可)。

电流不够:段码端只能提供 ±4 mA,驱动大电流 LED 请加三极管或 ULN2803。

1.4 AT89C52单片机实现比分计数器电路原理图

如上图所示,电路原理图由AT89C52单片机、上拉排阻、控制按键、晶振和复位电路、锁存器和6个数码管组成。通过五个独立按键控制高低电平,可以实现数值增加、减少或清零,并通过数码管显示数值。

1.5 控制程序

//头文件与位定义
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit AJJ= P2^1;//A-
sbit BJJ= P2^2;//B-
sbit CLC= P2^3;//A+
sbit AJ= P2^4;//A+
sbit BJ= P2^5;//B+
sbit LE_D = P2^6;//段选
sbit LE_W = P2^7;//位选uchar code table_D[] = {0xC0,0xF9,0xA4,0XB0,0x99,0x92,0x82,0xF8,0x80,0x98};//段值0-9
uchar code table_W[] = {0x01,0x02,0x04,0x08,0x10,0x20};	//位值1-6	uint time = 0;
uint Num_D = 0;
uint Num_W = 0;
uchar ge,shi,bai;//个 十 百位
uint num = 0;
uint num1 = 0;void init();//定时器T0初始化
void delay(uint dtime);//延时函数
void display1(uint num);//显示函数
void display2(uint num);//显示函数//定时器T0段选位选初始化
void init(){				LE_D = 0;LE_W = 0;AJ=1;BJ=1;TMOD = 0x01;			//0000 0001TH0 = 0xFC;				//1msTL0 = 0x17;EA = 1;ET0 = 1;TR0 = 1;
}//定时器T0延时函数
void delay(unsigned int dtime)
{unsigned int i;for (i = 0; i <dtime; i++){while (!TF0);  // 等待定时器T0溢出TF0 = 0;       // 清除溢出标志}
}
//定时器T0模式1中断服务函数
void Timer0_ISR() interrupt 1
{TH0 = 0xFC; TL0 = 0x17;time++;
}void main(){init();num1 = 0;num1 = 0;while(1){if((time >= 300)&&(AJ==0)){time=0;num1++;}else if((time >= 300)&&(BJ==0)){time=0;num++;}else if((time >= 300)&&(AJJ==0)&&(num>0)){time=0;num1--;}else if((time >= 300)&&(BJJ==0)&&(num>0)){time=0;num--;}else if((time >= 300)&&(CLC==0)){time=0;num=0;num1=0;}display1(num1);display2(num);}
}//后三个数码管显示数字的函数
void display1(uint num){		bai = num / 100;				//百位应显示的数字shi = num % 100 /10;		//十位应显示的数字ge = num % 10;					//个位应显示的数字//数码管显示个位数字LE_D = 1;P0 = table_D[ge];			//段——>位 会在段所指的位置上显示段LE_D = 0;							//位——>段 新的数字会显示到之前的位置上LE_W = 1;P0 = 	0x20;					//0010 0000LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;//数码管显示十位数字LE_D = 1;P0 = table_D[shi];	LE_D = 0;	LE_W = 1;P0 = 0x10;					//0001 0000LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;//数码管显示百位数字LE_D = 1;P0 = table_D[bai];LE_D = 0;LE_W = 1;P0 = 0x08;					//0000 1000LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;
}//前三个数码管显示数字的函数
void display2(uint num){		bai = num / 100;				//百位应显示的数字shi = num % 100 /10;		//十位应显示的数字ge = num % 10;					//个位应显示的数字//数码管显示个位数字LE_D = 1;P0 = table_D[ge];			//段——>位 会在段所指的位置上显示段LE_D = 0;							//位——>段 新的数字会显示到之前的位置上LE_W = 1;P0 = 	0x04;					//0000 0100LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;//数码管显示十位数字LE_D = 1;P0 = table_D[shi];	LE_D = 0;	LE_W = 1;P0 = 0x02;					//0000 0010LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;//数码管显示百位数字LE_D = 1;P0 = table_D[bai];LE_D = 0;LE_W = 1;P0 = 0x01;					//0000 0001LE_W = 0;delay(1);LE_W = 1;						//消隐P0 = 0;LE_W = 0;
}

http://www.xdnf.cn/news/18327.html

相关文章:

  • Windows下,将本地视频转化成rtsp推流的方法
  • strcasecmp函数详解
  • AI模型部署 - 大语言模型(LLM)部署技术与框架
  • js来比较两个对象内容有误差异
  • mysql数据库学习
  • 想在手机上操作服务器?cpolar让WaveTerminal终端随身携带,效率倍增
  • 【Springboot进阶】Java切面编程对性能的影响深度分析
  • 【Ruoyi解密-02.登录流程:】登录-找密码不抓瞎
  • selenium3.141.0执行JS无法传递element解决方法
  • Linux的奇妙冒险——进程间通信(管道、SystemV IPC)
  • 完全背包(模板)
  • webrtc中win端音频---windows Core Audio
  • 2025图表制作完全指南:设计规范、工具选型与行业案例
  • Chrome/360 浏览器扩展深度解析:内置扩展与普通扩展的实现机制对比
  • (栈)Leetcode155最小栈+739每日温度
  • 力扣 30 天 JavaScript 挑战 第37天 第九题笔记 知识点: 剩余参数,拓展运算符
  • Spring Boot集成腾讯云人脸识别实现智能小区门禁系统
  • 【C++去除整数某一位数字求新数和倍数保留2位小数控制】2022-10-22
  • 人工智能 -- 循环神经网络day1 -- 自然语言基础、NLP基础概率、NLP基本流程、NLP特征工程、NLP特征输入
  • 打造医疗新质生产力
  • 如何用算力魔方4060安装PaddleOCR MCP 服务器
  • visual studio更改git提交的用户名和邮件
  • Seaborn数据可视化实战:Seaborn基础与实践-数据可视化的艺术
  • 高效处理NetCDF文件经纬度转换:一个纯CDO驱动的Bash脚本详解
  • [大模型微调]基于llama_factory用 LoRA 高效微调 Qwen3 医疗大模型:从原理到实现
  • WPF中UI线程频繁操作造成卡顿的处理
  • 中文房间悖论:人工智能理解力的哲学拷问
  • 深度解析游戏引擎中的相机:视图矩阵
  • 小体积晶振1610/2016/3225选型参数
  • 小游戏AssetBundle加密方案解析