C51单片机学习笔记(五)——数码管的静态显示和动态显示

本文详细介绍了C51单片机控制数码管的静态和动态显示原理及实现方法,并通过实例展示了如何利用定时器实现计时功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C51单片机学习笔记(五)——数码管的静态显示和动态显示

1.数码管的显示原理

  • 数码管有一位和多位一体两类,它是由8个LED(a,b,c,d,e,f,g,dp)排列组成,任意一个LED叫作一个“段”。通过给a,b,c,d,e,f,g,dp各个脚加上不同的控制电压可以使不同的LED导通发亮,从而显示0~9各个数字和ABCDEF各个字母。
  • 由于8个LED共有16个引脚,为了减少引脚,形成了共阳极和共阴极两种数码管,如下图,如果是共阴极,点亮方法就是公共脚加低电平,引出脚加高电平,如果是共阳极,公共脚加高电平,引出脚加低电平即可。(我的数码管是共阳极,所以下面我就使用共阳极进行说明)
    在这里插入图片描述

2.数码管的静态显示

  • 所谓静态显示,就是数码管的笔画点亮后,这些笔画就一直处于点亮状态,而不是处于周期性点亮状态。下面我将以我的原理图为例说明如何点亮静态显示。
    在这里插入图片描述
  • 我的数码管的a,b,c,d,e,f,g,dp接在P0.0~P0.7脚,故我让哪一个二极管亮,就使其脚加低电平,几个LED组合在一起就可以拼出一个数字或字母,下面给出常用的字形码

在这里插入图片描述

  • 例如要使用‘3’,则数码管的a,b,g,c,d应点亮,其引脚为低电平,其他引脚为高电平,二进制数为dp g f e d c b a 1011 0000,每四位转成十六进制就是b0,所以要先显示‘3’,给P0端口赋值0xb0即可,其他字符的编码类似。
#include<reg52.h> 
#define uchar unsigned char 
#define uint unsigned int
sbit DI1=P1^0; //定义四位数码管位选信号 
sbit DI2=P1^1; 
sbit DI3=P1^2; 
sbit DI4=P1^3; 
unsigned char i = 0;
void delay(uint z) //定义延时函数
{ 
	uint x,y;
	for(x = z;x>0;x--)
		for(y = 110;y>0;y--); 
} /*定义数码管显示字符跟数字的对应数组关系*/ 
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, //数码管显示编码(0-F) 
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; 
void main() 
{ 
	P0=0x00; //P0口初始化 
	DI1=0; //第一位数码管位选 
	
	while(1)
	{
		P0 = table[i];
		delay(1000);	  //延时约1s
		i++;
		if(i>15)   //n=15时显示F,当n=16时从头开始
		i = 0;
	}
}

3.数码管的动态显示(不用锁存器)

  • 由于我的板子上没有锁存器。。。所以这里只介绍不用锁存器的动态显示,锁存器的好处只是可以节省I/O口,其实不用锁存器依然可以使数码管动态显示。
  • 动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。这样一来,就没有必要每一位数码管配一个锁存器,从而大大地简化了硬件电路。选亮数码管采用动态扫描显示。
  • 所谓动态扫描,即是通过分时轮流送出字形码和相应的位选,使各个数码管轮流受控显示。在轮流显示过程中,每位元数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极体的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示资料,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O口,而且功耗更低。
#include<reg51.h> 
#define uchar unsigned char 
sbit DI1=P1^0; //定义四位数码管位选信号 
sbit DI2=P1^1; 
sbit DI3=P1^2; 
sbit DI4=P1^3; 
void delay(uchar x) //定义延时函数 
{ 
	uchar j; 
	while(x--)
	{ 
		for(j=0;j<125;j++) 
		{;} 
	} 
} /*定义数码管显示字符跟数字的对应数组关系*/ 
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, //数码管显示编码(0-F) 
0x80,0x90,0xa0,0x83,0xc6,0xa1,0x84,0x8e,0x00};
 void main() 
 { 
 	P0=0x00; //P0口初始化 
 	DI1=0; //第一位数码管位选 
 	P0=table[0]; //第一位数码管显示0 
 	delay(5); 
 	DI1=1; //关闭第一位数码管位选 
 	DI2=0; //第二位数码管位选 
 	P0=table[1]; //第二位数码管显示1 
 	delay(5); 
 	DI2=1; //关闭第二位数码管位选 
 	DI3=0; //第三位数码管位选 
 	P0=table[2]; //第三位数码管显示2 
 	delay(5); 
 	DI3=1; //关闭第三位数码管位选 
 	DI4=0; //第四位数码管位选 
 	P0=table[3]; //第四位数码管显示3 
 	delay(5); 
 	DI4=1; //关闭第四位数码管位选 }

4.中断与数码管结合的计时器

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar num = 0;
sbit DI1=P1^0; 
sbit DI2=P1^1; 
sbit DI3=P1^2; 
sbit DI4=P1^3; 
uchar i4 = 0;
uchar i3 = 0;
uchar i2 = 0;
uchar i1 = 0;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code table2[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; 
void delay(uint z) //定义延时函数
{ 
	uint x,y;
	for(x = z;x>0;x--)
		for(y = 110;y>0;y--); 
}
void display()
{
	P0=0x00; //P0口初始化 
 	DI1=0; //第一位数码管位选 
 	P0=table[i1]; //第一位数码管显示0 
 	delay(5); 
 	DI1=1; //关闭第一位数码管位选 
 	DI2=0; //第二位数码管位选 
 	P0=table2[i2]; //第二位数码管显示1 
 	delay(5); 
 	DI2=1; //关闭第二位数码管位选 
 	DI3=0; //第三位数码管位选 
 	P0=table[i3]; //第三位数码管显示2 
 	delay(5); 
 	DI3=1; //关闭第三位数码管位选 
 	DI4=0; //第四位数码管位选 
 	P0=table[i4]; //第四位数码管显示3 
 	delay(5); 
 	DI4=1; //关闭第四位数码管位选
}
void main()
{
	//P0 = 0x00;
	TMOD = 0x01;//将定时器0设为方式1,即16位定时器
	/*TH0中每增加1,就相当于计了256个数,所以TH0装入初值是对256取模,TL0是对256取余*/
	TH0 = (65536-45872)/256;//给定时器的高八位赋初值
	TL0 = (65536-45872)%256;//给定时器的低八位赋初值
	EA = 1;//开总中断
	ET0 = 1;//开定时器0中断
	TR0 = 1;//启动定时器T0
	while(1)
	{	   
		
		if(num == 20) //num=20代表用了50ms*20  = 1s
		{
			num = 0;
			if(i4 == 9)
			{
				i4 = 0;
				
				if(i3 == 5)
				{
					i3 = 0;
					
					if(i2 == 9)
					{
						i2 = 0;
						i1++;
					}
					else
					{
						i2++;
					}
				}
				else
				{
					i3++;
				}
			}
			else
			{
				i4++;
			}	
		}
		display();
	}
}
void T0time() interrupt 1
{
	TH0 = (65536-45872)/256;
	TL0 = (65536-45872)%256;
	num++;		  
}
在C51单片机上实现数码管静态显示2024,你需要明确以下几个步骤: 1. **配置I/O口**:选择合适的I/O口作为数码管的数据线(例如P0~P3)。对于共阴极数码管,低电平代表发光,所以一般会设置为输出模式,并接高阻抗(比如开路)。 2. **数码管数据编码**:将数字"2024"转换成对应的段选信号。可以创建一个包含8个字段的数组,每个字段代表一个数码管段(如abcdefg小数点): ```c unsigned char digitCode[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07}; ``` 这里`digitCode[0]`对应2,`digitCode[1]`对应0,以此类推。 3. **静态显示代码**: - 首先清零所有的段选信号。 - 然后逐位设置数字的对应段选信号,同时保持其他位为0。 ```c void displayDigit(unsigned char code) { P0 = 0x00; // 清零所有段 // 按照数码管编码显示每个数字 for (int i = 0; i < 8; ++i) { if (code & (1 << i)) { P0 |= digitCode[i]; // 设置相应段为1 } } } void displayNumber(unsigned int num) { // 两位一组显示 for (int i = 0; i <= 3; ++i) { displayDigit(num % 10); // 取余数得到个位 num /= 10; // 移除个位 delay_ms(25); // 延迟一段时间让用户看到变化 } } ``` - `delay_ms()`函数是模拟延时的,实际应用中可能需要替换为硬件延时或中断服务函数。 4. **主函数**: - 初始化I/O口,然后开始显示数字"2024"。 ```c int main(void) { init_GPIO(); // 初始化I/O口 displayNumber(2024); while (1); // 无限循环等待外部信号或按键操作 } ``` 注意,由于C51的资源限制,可能会有内存限制或者代码优化的需求。此外,这个示例假设你已经有一个基本的延时函数或者中断机制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值