单片机C语言实现数码管控制

数码管作为人机接口的重要显示部件,广泛应用于各行各业。本文将围绕数码管的原理和使用展开讨论,实验内容也是由浅入深,结合C语言特性,着意于在实验中掌握数码管和C语言知识。文章采用与单片机C语言实现独立按键检测与矩阵键盘操作同样的开发板。以下先给出数码管的电路原理图。


上图中的4个数码管为共阳极数码管。数码管实际是由8个发光二极管组成的,而共阳极是指将这8个二极管的正极连接到一个公共端。所以当这8个二极管的任何一个负极通低电平的时候,相应的二极管就会被点亮,相反,通高电平则灭。详细请参照以下原理图。


图中任取一个数码管,有a, b, c, d, e, f, g, p分别代表组成该数码管的发光二极管。当要该数码管显示0到9之间任一数字的时候,要给每一个二极管不一样的电平(0或1),8个二极管分别由P0口的8个I/O口控制,P0口的控制输出即为段码。

上面说的是单个数码管的显示,然后我们有四个数码管,怎么选择我要用哪个数码管呢?回到数码管原理图,可以看到数码管底下的DIG口分别连接到4个驱动三极管,并最终由P2口的4个端子来控制。这样就可以选择哪个数码管工作,譬如希望最左侧数码管亮,我们称其为千位数码管(因为有4个数码管,分别代表个十百千),则只需给P2.0口送低电平。

实验一

好了,现在就来做个实验,实验目标是使千位数码管显示数字6。直接上代码。

#include "reg51.h"
 //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 sbit QIAN = P2^0; //QIAN表示千位
 void main()
 {
 	P0 = seg[6];
	QIAN = 0;
	while(1)
	{
		
	}
 }
程序中,显示定义了段码,进入main函数后,先给P0口数字6的显示段码,再选通千位数码管,这样千位数码管就顺利地显示6。这里我们重点讲解seg数组。

char seg[10]

10:10个数连续存放。

seg:代表了第一个数的首地址。

char:每个数最大值不超过255,即一个内存单元(如果定义成int则每个数要占用两个内存单元)。

但是这10个数存在哪呢?

有两种方法。第一种也就是当我们采用char seg[...]={...}这种定义方法时,程序下载烧到ROM后,当下次上电时候,程序会自动将这数组拷贝到RAM。第二种当定义成code char seg[...]={...}时候,程序下载烧到ROM后,内核只从ROM中读取,并不通过RAM。这样的好处是节省了内存资源,但同时程序执行时seg数组也不能被更改。

实验二

接下来我们要使4个数码管都显示,本例显示1234。直接上代码:

#include "reg51.h"
 //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 sbit QIAN = P2^0;
 char i;
 char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。

 void delay(unsigned int x)
 {
 	while(x)   //注意这里不是1
	{
		x--;
	}	
 }

 void load_smg()   //将数码管显示缓冲区的数据,显示到数码管上
 {
 	char i;
 	for(i=0;i<4;i++)	
	{
		P0=0xFF;   //消除上一个循环的影子,因为i每一次叠代时,数码管都会有上一次叠代的痕迹,0xFF则是使所有数码管灭掉。
		P0 = seg[smgbuf[i]];
		P2 = ~(1<<i);
		delay(200);
	}
 }

 void main()
 {
	while(1)
	{
		load_smg();
	}
 }
实验三

下面我们希望用四个数码管显示一个可变的数字,这个数字记录了程序执行进入main函数的次数。还是直接上代码(为了方便代码管理,拆分代码到main.c和smg.c):

main.c文件

#include "reg51.h"
unsigned int count;
extern void load_smg();

void main()
 {
	int a;
	while(1)
	{
		load_smg();
		a++;
		if(a>=200)
		{
			count++;
			a=0;			
		}
	}
 }
smg.c文件

 #include "reg51.h" 
  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 char i;
 char smgbuf[4]={1,2,3,4}; //从RAM的smgbuf这个地址开始连续存放4个数,并且每个数占一个单元。
 sbit QIAN = P2^0;
 extern unsigned int count;	//外部申明

 void delay(unsigned int x)
 {
 	while(x)   
	{
		x--;
	}	
 }

void fill_smgbuf() //向LED缓冲区填充数据
{
	smgbuf[0]=count/1000;  //千位,我们希望千位数码管来显示数字的千位
	smgbuf[1]=(count%1000)/100;  //百位
	smgbuf[2]=((count%1000)%100)/10;   //十位
	smgbuf[3]=((count%1000)%100)%10;   //个位
}

void load_smg()   //将缓冲区的数据,显示到数码管上
 {
 	char i;
	fill_smgbuf();
 	for(i=0;i<4;i++)	
	{
		P0=0xFF;  
		P0 = seg[smgbuf[i]];
		P2 = ~(1<<i);
		delay(200);
	}
 }
实验四
接下来我们要引入独立按键控制数码管上的数字加1(K1键)或减1(K2键)。还是上代码:

main.c文件

#include "reg51.h"

extern void load_smg();
extern delay(unsigned int x);
extern void key1();
extern void key2();

unsigned int count;

void main()
 {
	while(1)
	{
		load_smg();
		key1();
		key2();
	}
 }
smg.c文件

 #include "reg51.h" 
  //char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 code char seg[10]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
 char smgbuf[4]={1,2,3,4}; 
 extern unsigned int count;	

 void delay(unsigned int x)
 {
 	while(x)   
	{
		x--;
	}	
 }

void fill_smgbuf() 
{
	smgbuf[0]=count/1000;  
	smgbuf[1]=(count%1000)/100;  
	smgbuf[2]=((count%1000)%100)/10;   
	smgbuf[3]=((count%1000)%100)%10;   
}

void load_smg()   
 {
 	char i;
	fill_smgbuf();
 	for(i=0;i<4;i++)	
	{
		P0=0xFF;   
		P0 = seg[smgbuf[i]];
		P2 = ~(1<<i);
		delay(200);
	}
 }
key.c文件

#include "reg51.h"
extern delay(unsigned int x);
extern unsigned int count;
sbit K1=P2^4;  //+1
sbit K2=P2^5;	//-1

void key1()
{
	static char st;
	if(K1==0)
	{
		if(st==0)
		{
			delay(5000);
			if(K1==0)
			{
				st=1;
				count++;
			}
		}
	}
	else
	{
		st=0;
	}
}

void key2()
{
	static char st;
	if(K2==0)
	{
		 if(st==0)
		 {
		 	delay(5000);
			if(K2==0)
			{
				st=1;
				count--;
			}
		 }
	}
	else
	{
		st=0;
	}
}
这个实验有一个地方需要注意,即每当复位,按K2键,数码管显示535。这是因为开机后程序默认count值为0,即16个0。当按下K2键后,减1,变成负1。而负1在内存中为16个1(负数的补码为其绝对值的原码取反再加1),又因为count定义为unsigned,所以显然count为65535。65535再被1000除,得到了535。

总结:

1、掌握数的分离方法,例如求出5678的个十百千位。

2、C语言数组是数据批量处理的基础。

3、尝试分别用四个键去控制个十百千四个数码管的闪烁。





  • 25
    点赞
  • 145
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值