图1 8位数码管动态显示电路
本例利用51单片机的P0、P1口来控制8位数码管的动态显示。 这样就达到了用更少的I/O口控制多位数码管的目的。
1.2. 设计理念
在单片机项目的设计过程中,我们经常会遇到I/O端口不够的情况。 就像生活中的我们一样,总是想用一点钱买很多东西。 我们别无选择,只能想办法把一分钱分成几块。 花瓣花。 单片机项目设计也是如此。 寻找使用更少的 I/O 端口来控制更多外设的方法。
根据我们前面的例子,控制一个数码管至少需要8个I/O口(如果公共端不需要控制,如果公共端也需要控制,那么就需要9个I/O口)。 按照这个思路,一个8位数码管至少需要8*8个I/O口,而51单片机只有4*8个I/O口。 该怎么办? 采用动态扫描方式!
数码管的8个段选择端口连接到单片机的8个I/O端口。 同时,数码管的8位选择端口与单片机的其他8个I/O端口连接。 程序中依次控制8位数码管显示数字,利用人眼的“视觉暂留”效应,只要将每个数码管的显示时间设计得恰到好处,就可以实现“同时显示”。 ” 可以实现8位数码管的显示。
1.3. 基础知识 1.3.1. 数码管动态显示原理
数码管动态显示电路如下。
数码管动态显示
8位数码管的公共端(COM端、位选择口)分别连接到单片机的8个I/O口。 每个数码管的8个段选择端a~g和dp都连接在一起,然后连接到单片机。 8 个 I/O 端口。
当需要在某个数码管上显示字符时,首先控制与该数码管相连的COM端子的I/O口输出相应的电平,使该位有效,然后从段选择端口Just值。 动态显示的特点是每个数码管依次点亮显示,但这会有一个缺点。 就是因为每个数字的点亮时间比较短,会导致数码管显示的亮度不足。 解决方案是使用驱动电路。
由于所有数码管的段选口都是公用的,如果想让每个数码管显示不同的值,必须先从段选口发送要显示字符的段码值,然后再发送要显示字符的段码值。要显示的字符。 管位选择有效,其他数码管位段选择无效。 这样就保证了此时只显示选中的数码管,然后延时一定时间(延时几毫秒),延时结束。 最后关闭所有数码管的位选口,从而完成一台数码管的显示; 其他数码管也按照这个流程进行处理,这样就可以看到所有数码管“同时”显示各自的数字。 这就是人眼的“视觉暂留”效应,无法捕捉如此快速的显示变化。 只要延迟时间设置得当,你就会感觉到所有数码管都在显示。
延迟时间的长短对数码管的显示效果影响很大。 “视觉暂留”效果的要求是图像变化时间不少于24帧每秒(24Hz),你会感觉到这些图像在连续变化。 对于多位数码管,每个数码管的扫描显示时间应满足“(1/24)/数码管数量”的要求。 扫描时间太长(每个数码管的延迟时间太长)。 它会显得闪烁; 如果扫描时间太短(每一位显示的时间太短),一切都会显得很亮。
1.4. 电路设计
图 1 显示了该示例的电路图。
因为8个数码管的段选端全部连接在一起,然后连接到单片机的I/O口。 单片机1位I/O口的驱动能力只有10mA左右,并且不能同时驱动8个段。 因此,需要增加驱动电路来增加I/O端口的驱动能力。
在实际使用中,可以采用晶体管、反相器、译码器、驱动器、锁存器以及专用驱动电路来增加I/O端口的驱动能力。 在本例中,我们使用晶体管来构成驱动电路。 数码管的段选择口通过限流电阻与单片机的P1口相连,位选择口通过晶体管驱动电路与单片机的P0口相连。
1.5. 编程
本例的程序代码如下。
多位数码管动态显示的编程可概括如下:
第一步:发送段值
将某个数码管要显示的段码值输出到单片机的段码控制端口。
第二步:选择送货座位
选择要显示的数码管,单片机控制该数码管的段选有效,其他不显示的段选端子全部闭合。
第三步:延迟
延时一定时间,延时时间按照公式“(1/24)/数码管数”设定。
第 4 步:关闭
关闭所有数码管段选择。
第5步:循环扫描
重复步骤1到4,一一发送段码值,选择不同的数码管。
#include
sbit CS1=P0^0; //8位数码管位选端口定义,第1位
sbit CS2=P0^1; //8位数码管位选端口定义,第2位
sbit CS3=P0^2; //8位数码管位选端口定义,第3位
sbit CS4=P0^3; //8位数码管位选端口定义,第4位
sbit CS5=P0^4; //8位数码管位选端口定义,第5位
sbit CS6=P0^5; //8位数码管位选端口定义,第6位
sbit CS7=P0^6; //8位数码管位选端口定义,第7位
sbit CS8=P0^7; //8位数码管位选端口定义,第8位
//共阳极数码管,数字0~9的段码表
unsigned char code Tab[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//延时函数,
void Delay(unsigned int DelayCounter)
{
unsigned int i;
while(DelayCounter--)
{
for(i=0;i<120;i++);//延时约1ms
}
}
//
void main(void)
{
unsigned char n;
unsigned long int m;
unsigned char cData1,cData2,cData3,cData4,cData5,cData6,cData7,cData8;
P0=0xff;
while(1)
{
for(m=10000000;m<99999999;m++)//
{
for(n=0;n<10;n++)//控制数码管显示的快慢,修改n的值,可观察数码管显示的速度
{
cData1=m/10000000;//获取显示的数,从左开始第1位要显示的数
cData2=(m000000)/1000000;//获取显示的数,从左开始第2位要显示的数
cData3=(m00000)/100000;//获取显示的数,从左开始第3位要显示的数
cData4=(m0000)/10000;//获取显示的数,从左开始第4位要显示的数
cData5=(m000)/1000;//获取显示的数,从左开始第5位要显示的数
cData6=(m00)/100;//获取显示的数,从左开始第6位要显示的数
cData7=(m0)/10;//获取显示的数,从左开始第7位要显示的数
cData8=m;//获取显示的数,从左开始第8位要显示的数
//显示,从左开始第1位
P1=Tab[cData1];//第一步:送段码值
CS1=0;//第二步:位选通
Delay(2);//第三步:延时
P0=0xff;//第四步:关闭所有段选,所有数码管显示都关闭
//显示,从左开始第2位
P1=Tab[cData2];
CS2=0;
Delay(2);
P0=0xff;
//显示,从左开始第3位
P1=Tab[cData3];
CS3=0;
Delay(2);
P0=0xff;
//显示,从左开始第4位
P1=Tab[cData4];
CS4=0;
Delay(2);
P0=0xff;
//显示,从左开始第5位
P1=Tab[cData5];
CS5=0;
Delay(2);
P0=0xff;
//显示,从左开始第6位
P1=Tab[cData6];
CS6=0;
Delay(2);
P0=0xff;
//显示,从左开始第7位
P1=Tab[cData7];
CS7=0;
Delay(2);
P0=0xff;
//显示,从左开始第8位
P1=Tab[cData8];
CS8=0;
Delay(2);
P0=0xff;
}
}
}
}
1.6. 模拟示例
编写程序代码,编译生成HEX文件,将HEX文件加载到proteus电路的单片机中,开始仿真,观察数码管的显示。 我们可以通过修改延迟时间来缩短或延长延迟时间,并观察数码管。 展示会有什么不同的变化。