51单片机学习——静态和动态数码管

一、数码管的原理

数码管的每一段都由一个单独的发光二极管控制,亮的地方不同就可以表示不同的数字。但需要按照一定的顺序点亮。数码管分两种,一种是共阳极,另一种是共阴极。注意:如果是共阳极数码管我们单片机是可以直接驱动的,如果是共阴极数码管单片机的IO是不能直接驱动数码管的,需要外部提供大电流驱动芯片来处理。比如74HC245芯片就是一个驱动芯片。

二、什么是静态和动态数码管

静态数码管和动态数码管是驱动上的差异,而不是数码管本身的差异。因为我们同一时间只能让一个数码管亮,但是我们有时候会使用不止一个数码管,来组合的显示数字。因此我们就利用人眼的视觉暂留效应,在很短的时间内,切换数码管的亮灭,这样我们就能看到所有的数码管都是亮的。

三、静态数码管的驱动

通过看原理图发现,只需要将J8和P0端口连接起来,就完成了接线。通过看原理图我们还发现,我们这里使用的数码管是共阳极数码管。所以我们哪个引脚输出是0,那么这个位控制的数码管段就是亮的。输出1,则这个数码管段是灭的。需要注意的是,我们接线的时候,注意P0端口的高位和数码管高位的对应,简单地说就是P0^0对应数码管的DP端。依次类推然后接线。

四、静态数码管实战编程

#include <reg52.h>
#include <intrins.h>

void delay1s(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=46;c>0;c--)
        for(b=152;b>0;b--)
            for(a=70;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}


void main(void)
{
	unsigned char shuma[10] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09}; 
    //从0-9对应的数码管显示数字
    unsigned char shuma1[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,    0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
	//对应的是顺着的时候,数码管对应数字的编码 也就是P0.0对应 a 依次对应即可
	unsigned char i = 0;
	while(1)
	{
		  for (i=0; i<10; i++)
			{
				P0 = shuma[i];
				delay1s();
			}
  }
}

这个程序的主要目标是,在静态数码管上面依次显示0到9的数字,首先我们通过前面的原理和看数据手册,先手工计算出来,不同的数字对应的不同的数码管亮灭。然后再用一个循环每间隔 1秒,给P0端口,放一个不同的值,这样我们就可以显示不同的数字了。

五、动态数码管实战

通过看原理图,我们就可以发现,动态数码管是共阴极的,因此我们在静态数码管获得的每个数字对应的段码,是不能直接用在动态数码管上面的,想要使用 按位取反即可。我们还可以看到所有的数码管所对应的码段,都被并联到了一起,因此如果在J6这边,给定一组数据,那么所有数码管得到的都是一样的,那么我们就需要在J1端,去控制只要J1端在同一时间,只让其中的一个引脚是低电平,其他的都是高电平,那么就能保证在同一时间段只亮一个数码管。在极短的时间内进行切换,我们就可以在不同的数码管上进行显示了。

通过看原理图和实物图我们发现,J1和J10是通过很多跳线帽连到了一起,然后J10连接的是一个38译码器,他的主要功能是用3根线,就可以控制8个位的不同的0和1的状态。下面是他的3根线和8个输出引脚电平的关系。

通过看图我们发现他的A0, A1, A2对应的就是我们的A,B,C三个引脚,也就是对应J9插座的3,2,1,然后我们通过接线将3 2 1分别接到P1.0 P1.1 P1.2三个引脚上面,也就是说我们的P1.0, P1.1, P1.2分别对应上图的A0, A1, A2。然后我们就可以进行编程了。

sbit A0 = P1^0;    
sbit A1 = P1^1;
sbit A2 = P1^2;


#define SHUMAGUAN P0

void DuanXuan(unsigned char num)
{
	switch (num){
		case 0: A0 = 0,A1 = 0, A2 = 0;break;
		case 1: A0 = 1,A1 = 0, A2 = 0;break;
		case 2: A0 = 0,A1 = 1, A2 = 0;break;
		case 3: A0 = 1,A1 = 1, A2 = 0;break;
		case 4: A0 = 0,A1 = 0, A2 = 1;break;
		case 5: A0 = 1,A1 = 0, A2 = 1;break;
		case 6: A0 = 0,A1 = 1, A2 = 1;break;
		case 7: A0 = 1,A1 = 1, A2 = 1;break;
	}
	
}


void delay1ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}


/*
 *函数功能:在特定的位上显示特定的数字
 *输入参数:bits:要在哪一位数码管上显示 数码管从左往右 依次是0到7
 *          num:需要显示的数字
 */
void ShuMaGuanShow(unsigned char bits, unsigned char num)
{
	unsigned char shuma[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
	
	DuanXuan(bits);  //用来选择数码管需要显示的位置
	SHUMAGUAN = ~shuma[num];
    delay1ms();      
	SHUMAGUAN = 0;   //用来进行消隐,不理解的话将这行,去掉看结果就懂了
}

当我们想要在某一位进行显示时,我们只需要调用这个函数即可。

### 使用51单片机定时器中断实现数码管动态显示 #### 实现思路 为了使数码管能够稳定而清晰地显示出所需的信息,通常采用动态扫描的方式。这种方式下,多个数码管依次轮流点亮,在人的视觉暂留效应作用下形成连续稳定的显示效果。定时器中断在此过程中起到至关重要的作用——它负责按照设定的时间间隔触发CPU执行特定的任务函数来更新各个数码管的状态。 #### 关键技术点 - **定时器初始化**:设置合适的预置值以获得所需的延时时间[^2]。 - **中断服务程序编写**:每当发生一次溢出事件即调用该部分代码完成当前位数码管的数据刷新并切换至下一个待显位置[^3]。 - **共阳极/阴极连接方式的选择**:依据实际电路决定具体的编码逻辑[^1]。 #### 示例代码展示 下面给出一段基于8051架构处理器利用Timer0作为硬件资源驱动四位七段LED显示器循环滚动输出数字'0'-‘9’的简单实例: ```c #include <reg52.h> sbit DIO=P2^7; //定义公共端控制引脚 unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //定义字型表 unsigned int count=0; void Timer0_Init(void){ TMOD|=0X01; //选择定时模式1(16位) TH0=(65536-5000)/256; TL0=(65536-5000)%256; ET0=1; //允许定时器0中断 EA=1; //开总中断 } void main(){ P0=table[count%10]; //初始状态设为第一个字符对应的二进制形式 DIO=0; //先拉低选通所有数码管 Timer0_Init(); //启动定时机制 while(1); } // 中断服务子程序 void timer0_isr() interrupt 1 { static unsigned char i=0; TR0=0; //关闭定时器防止重入 TH0=(65536-5000)/256; TL0=(65536-5000)%256; switch(i++){ case 0:P2=0xFE;break; case 1:P2=0xFD;break; case 2:P2=0xFB;break; case 3:P2=0xF7;break; default:i=0;break; } P0=table[(count++)%10]; DIO=~P2&0x0F; //仅保留最低四位有效信号用于指示哪个数码管被激活 TR0=1; //重新开启定时器继续计数周期 } ``` 这段代码实现了四个独立工作的静态数码管通过分时复用来模拟多路同时发光的效果。每次进入ISR都会改变所要亮起的那个器件的位置及其上应呈现的具体图案,从而达到整体上看去就像全部都在常亮一样的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值