51单片机数码管硬件接口如下图所示
四个共阳极数码管,P20~P23是通过四个PNP三极管来控制数码管的位选,当给对应位选端低电平时,三极管导通,即对应位的数码管工作,P0是控制数码管的 段选(四个数码管并联)。我以前的博客里有写到过数码管的工作原理,这里就不细讲。
由于我的开发板只有四位数码管,所以我只显示了分和秒,数字钟的具体操作如下
# include
//引用了51单片机的官方库文件
#define uint unsigned int //宏定义
#define uchar unsigned char
void T0INI() ; //声明函数
void delay(uchar i);
void display();
uint second,minter,hour,time_counter; //秒,分,时,中间变量
unsigned char leddata[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82, //定义了一个数码管显示字符型数组
0xf8,0x80,0x90};
/*
*********************************************************************
**主函数
*********************************************************************
*/
void main()
{
T0INI();
while(1)
{
display();
}
}
/*
*********************************************************************
**函数名称:display
**函数作用:数码管显示
*********************************************************************
*/
void display()
{
P2 = 0x0e; //打开位选端P20
P0 = leddata[minter/10]; //显示计时器分的十位
delay(5);
P2 = 0x0f; //关闭位选
P2 = 0x0d; //打开位选端P21
//P0 =( leddata[minter%10] & 0x7f); //显示秒表的个位
P0 = leddata[minter%10];
delay(5);
P2 = 0x0f; //关闭位选
P2 = 0x0b; //打开位选端P22
P0 = leddata[second/10]; //显示计时器分的十位
delay(5);
P2 = 0x0f; //关闭位选
P2 = 0x07; //打开位选端P23
P0 = leddata[second%10]; //显示计时器分的十位
delay(5);
P2 = 0x0f; //关闭位选
}
/*
*********************************************************************
**函数名称:delay
**函数作用:延时函数
*********************************************************************
*/
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/*
*****************************************************************************
**函数名称:T0INI()
**函数功能:定时器0初始化
*******************************************************************************
*/
void T0INI() //定时器T0初始化
{
IE = 0X82; //cpu开总中断
TCON = 0x10; //打开定时器T0
TMOD = 0x01; //设置T0为工作模式1,16位定时计数器
TH0 = 0X3c;
TL0 = 0xb0; //12Mhz定时50ms
}
/*
********************************************************************************
** 函数名称 : T0_zd(void) interrupt 1 using 0
** 函数功能 : 定时器中断
********************************************************************************
*/
void T0_zd(void) interrupt 1 using 0
{
TH0 = 0X3c;
TL0 = 0xb0; //12Mhz定时50ms
time_counter++;
if(time_counter==20)
{
time_counter=0;
second++; //定时1秒加1
if(second==60)
{
second=0;
minter++;
if(minter==60)
{
minter=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
}
}