小蜜蜂51单片机之共阳数码管的动态显示

关键词:共阳数码管的动态显示;调试错误注意点;数码管段码表;Delay函数的不同设置;小蜜蜂

一、知识点

1、动态显示的原理:

 2、静态显示和动态显示的区别:

左上:静态显示原理,几个COM端输入1,表示该数码管被点亮,能够显示数字(输入0,则表示不会显示数字),另一端P0输入数字对应的段码(因为是公共端,所以只能显示一个数字)

左下:多位数字用静态显示方法呈现,但占用较多IO口

右:动态显示,轮流点亮数码管(COM只有一个是1,其余都是0)

二、实验

实验目的:

实验步骤:

S1:定义数码管段码表数组

参考:http://t.csdnimg.cn/JnM7U

 代码:

unsigned char code SMG_duanma[18]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF,0xFF};
//数码管0-9,A-F,-,空白(b,d用小写表示)

S2:复制静态数码管的信道选择函数代码

unsigned char SelectHC573(unsigned char channel)
{
	switch(channel)
	{
		case 4:P2=(P2&0x1F)|0x80;break;//1001 1111  //100->8
		case 5:P2=(P2&0x1F)|0xA0;break;//1011 1111  //101->A
		case 6:P2=(P2&0x1F)|0xC0;break;//1101 1111  //110->C
		case 7:P2=(P2&0x1F)|0xE0;break;//1111 1111  //高三位清零&,|将高三位置值
	}
}

S3:编写数码管显示函数

原理:

Y6控制位置,Y7控制段码 (显示的数字)

代码:
void DisplaySMG(unsigned char value,pos)//value表示数值,pos表示显示的位置
{
	SelectHC573(6);//打开控制位置显示的总闸
	P0=0x01<<pos;//0x01左移pos位,表示COM(pos)位置1
	SelectHC573(7);//打开控制数字显示的总闸
	P0=value;
}

S4:编写数码管动态显示函数

1.初步:利用静态数码管显示单个位的值为小模块组合显示2018
void Display_Dynamic()
{
	DisplaySMG_Bit(SMG_duanma[2],0);
	DisplaySMG_Bit(SMG_duanma[0],1);
	DisplaySMG_Bit(SMG_duanma[1],2);
	DisplaySMG_Bit(SMG_duanma[8],3);//分别在四个位置显示2、0、1、8
}
2.改进:让一个数码管显示一会儿(即延迟),再显示下一个数码管(轮流显示)
void SMG_Delay(unsigned int t)
{
	while(t--);
}

void Display_Dynamic()
{
	DisplaySMG_Bit(SMG_duanma[2],0);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[0],1);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[1],2);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[8],3);//分别在四个位置显示2、0、1、8
	SMG_Delay(500);
}
 实验现象:运行提示错误

心路历程:

最开始我只是看到说P2重定义,有很多的提醒,但一直觉得没什么错,不知道怎么解决,直到我翻到最上面的提示,才发现是段码表数组处有语法错误,修改后根据提示再调试再修改,解决了问题(和P2重定义无关)

经验总结:

1.出现错误提示从最上面看起,边修改边调试

2.注意函数是否有返回值,第二次错误提示即是unsigned char SelectHC573(unsigned char channel),我没有写返回值,所以需将其改为void类型

实验现象:

前4个数码管稳定显示2018(最后一个数码管有红色阴影)——>有残影说明你没消影,加个P0=0XFF就行了(弹幕),或者修改延时,延时越久越闪(视觉暂留现象,故不能长时间延时),用延时来消影

完整动态显示2018代码:
#include <REGX52.H>

unsigned char code SMG_duanma[18]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF,0xFF};
//数码管0-9,A-F,-,空白(b,d用小写表示)

void SelectHC573(unsigned char channel)
{
	switch(channel)
	{
		case 4:P2=(P2&0x1F)|0x80;break;//1001 1111  //100->8
		case 5:P2=(P2&0x1F)|0xA0;break;//1011 1111  //101->A
		case 6:P2=(P2&0x1F)|0xC0;break;//1101 1111  //110->C
		case 7:P2=(P2&0x1F)|0xE0;break;//1111 1111  //高三位清零&,|将高三位置值
	}
}

void DisplaySMG_Bit(unsigned char value,pos)//value表示数值,pos表示显示的位置
{
	SelectHC573(6);//打开控制位置显示的总闸
	P0=0x01<<pos;//0x01左移pos位,表示COM(pos)位置1
	SelectHC573(7);//打开控制数字显示的总闸
	P0=value;
}

void SMG_Delay(unsigned int t)
{
	while(t--);
}

void Display_Dynamic()
{
	DisplaySMG_Bit(SMG_duanma[2],0);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[0],1);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[1],2);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[8],3);//分别在四个位置显示2、0、1、8
	SMG_Delay(500);
}

void main(void)
{
	while(1)
	{
		Display_Dynamic();
	}
}

S5:在void Display_Dynamic()中添加--分隔符以及最后两位显示月份(固定的)

代码:
unsigned char yue=1;
    DisplaySMG_Bit(SMG_duanma[16],4);
    SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[16],5);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[yue/10],6);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[yue%10],7);
	SMG_Delay(500);
 实验现象:数码管稳定显示2018--01

S6:让月份动起来,从1->2->...->12->1->...

思路: 

1.在while循环里实现yue++,并设定月份循环限制(if语句或直接yue%=12)

2.为了让yue++没有那么快(数码管显示才会稳定可见),需要加延时函数,但这个延时和上面设置的不同,while并不是空循环,而是有Display_Dynamic();(这里写延时是让1到12变慢 并且延时同时还要刷新数码管)

添加代码如下:
void Delay(unsigned char t)
{
	while(t--)
	{
		Display_Dynamic();
	}
}
void main(void)
{
	while(1)
	{
		Display_Dynamic();
		yue++;
		if(yue>12)
			yue=1;//也可以直接yue=yue%12;,不用if语句
		Delay(100);
	}
}
 备注:类似定时器中断效果,你如果单纯用延时函数,8个数码管都会暗下去,直到下一次循环重新显示,不符合要求,但后面学了中断,就不会用这个方法了,这个方法效率低(B站弹幕)

完整代码:

#include <REGX52.H>

unsigned char yue=1;
unsigned char code SMG_duanma[18]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF,0xFF};
//数码管0-9,A-F,-,空白(b,d用小写表示)

void SelectHC573(unsigned char channel)
{
	switch(channel)
	{
		case 4:P2=(P2&0x1F)|0x80;break;//1001 1111  //100->8
		case 5:P2=(P2&0x1F)|0xA0;break;//1011 1111  //101->A
		case 6:P2=(P2&0x1F)|0xC0;break;//1101 1111  //110->C
		case 7:P2=(P2&0x1F)|0xE0;break;//1111 1111  //高三位清零&,|将高三位置值
	}
}

void DisplaySMG_Bit(unsigned char value,pos)//value表示数值,pos表示显示的位置
{
	SelectHC573(6);//打开控制位置显示的总闸
	P0=0x01<<pos;//0x01左移pos位,表示COM(pos)位置1
	SelectHC573(7);//打开控制数字显示的总闸
	P0=value;
}

void SMG_Delay(unsigned int t)
{
	while(t--);
}

void Display_Dynamic()
{
	DisplaySMG_Bit(SMG_duanma[2],0);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[0],1);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[1],2);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[8],3);//分别在四个位置显示2、0、1、8
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[16],4);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[16],5);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[yue/10],6);
	SMG_Delay(500);
	DisplaySMG_Bit(SMG_duanma[yue%10],7);
	SMG_Delay(500);
}

void Delay(unsigned char t)
{
	while(t--)
	{
		Display_Dynamic();
	}
}

void main(void)
{
	while(1)
	{
		Display_Dynamic();
		yue++;
		if(yue>12)
			yue=1;//也可以直接yue=yue%12;,不用if语句
		Delay(100);
	}
}
经验+1:新添加的Delay函数需要在 Display_Dynamic();之后出现,否则会出现失去Display_Dynamic();的定义而报错的现象(先定义后使用)

感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值