单片机的P4端口控制8位一体数码管的段码,采用8个共阴极的LED数码管。单片机的P5端口作为位扫描控制端口,P5.0~P5.7分别与LED0~LED7的公共端COM引脚连接。
与静态方式的数码管驱动电路相比,下图所示的电路中占用了16个I/O端口线,8个数码管动态显示只需要两个8位端口,其中P4控制段码,P5控制位选线。动态扫描的原理:由P5端口向每个位轮流输出扫描信号,使每一瞬间只有一个数码管被选通(共阴极低电平选通,共阳极高电平选通),然后由P4端口送入该位要显示的字形码,点亮该位字形段显示的字形。这样在P4送出的段码和P5送出的位选线配合控制下,就可以使各数码管轮流点亮显示各自的字符。虽然显示器的几位数码管是依次被点亮的,但只要每位点亮时间超过1ms,隔一段时间使之再显示一遍,如此不断重复扫描,只要扫描频率足够快(大于50Hz),由于人的视觉暂存,看不出闪烁。动态扫描一般用软件实现,可以采用软件延时或者定时器延时来实现。
基于Proteus的MSP430单片机仿真实例10-8位数码管显示时钟
程序设计
//main.c
#include "msp430f247.h"
#include "stdlib.h"
#include "string.h"
/*****************************************软件延时,主频1M*******************/
#define CPU_F1 ((double)1000000)
#define delay_us1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000000.0))
#define delay_ms1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000.0))
/****************************************************************************/
//共阳极数码管段码表
unsigned char const Led_Tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//共阴极数码管段码表
unsigned char const Led_Tab2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x40};
unsigned char time_counter;//1S计数器
unsigned char time[3];//时、分、秒计数
unsigned char dis_buff[8];//显示缓冲区,存放要显示的6个字符的段码值和两个分隔符
void display(void);//扫描显示函数
void time_to_disbuffer(void);//时间值送显示缓冲区函数
/************************************************
函数名称:主函数
函数功能:8位一体数码管动态显示时钟
入口参数:无
出口参数:无
************************************************/
main()
{
_EINT();//打开中断,响应按键
WDTCTL = WDTPW + WDTHOLD;//关看门狗
P4DIR=0xff;//段码端口初始化
P5DIR=0xff;//位选端口初始化
time[2]=22;//时间初值
time[1]=51;
time[0]=55;
time_to_disbuffer();
dis_buff[2]=10;//
dis_buff[5]=10;//
while(1)
{
display();//显示扫描
if(++time_counter>=40)//更新时间
{
time_counter=0;
if(++time[0]>=60)
{
time[0]=0;
if(++time[1]>=60)
{
time[1]=0;
if(++time[2]>=24) time[2]=0;
}
}
time_to_disbuffer();//修改显示缓冲区
}
}
}
void display(void)
{
static char i;
P5OUT=0xff;
P4OUT=80;
P4OUT=Led_Tab2[dis_buff[i]];//时间值送显示缓冲区函数
P5OUT=~(1<<i);//位选端口选择
if(++i==8) i=0;
delay_ms1M(2);
}
void time_to_disbuffer(void)
{
dis_buff[0]=time[2]/10;//小时
dis_buff[1]=time[2]%10;
dis_buff[3]=time[1]/10;//分钟
dis_buff[4]=time[1]%10;
dis_buff[6]=time[0]/10;//秒
dis_buff[7]=time[0]%10;
//dis_buff[2]=0x04;//
//dis_buff[5]=0x04;//
}
程序说明
根据硬件电路可以看出,在任何一个时刻,P5.0~P5.7中只能有一个I/O端口输出低电平,即只有一位数码管亮,同时P4端口要输出该位相应的段码值。即时显示的内容没有变化,也要不停地进行循环扫描处理。
软件的设计应保证从外表看数码管显示的效果要连续,亮度均匀,同时没有拖尾现象。单片机为了保证各数码管显示的效果不产生闪烁情况,让数码管看起来好像全部点亮,就首先必须在1S内循环扫描8个数码管的次数应大于25次,这里是利用的人眼的视觉暂存效应。第二要考虑的是,在25ms时间间隔中,要逐一轮流点亮8个数码管,那么每个数码管点亮的持续时间要相同,这样亮度才能均匀。第三个要考虑的是每个数码管点亮的持续时间,这个时间长一些的话,数码管的亮度高一些,反之则暗一些。通常,每个数码管点亮的持续时间为1~2ms。