89c51单面机c语言时钟控制器编程

89c51单面机c语言时钟控制器编程、、、就是在数码管上每隔一秒钟显示该秒对应的数字、、当显示第60秒时、、蜂鸣器响一下、、、、依次循环 就是一个简易的分秒计时器 用c语言怎么编程啊 那位大侠帮帮忙啊、、、、

方案1:AT89S52,DS12887时钟芯片,实践通过,运行稳定。自己根据程序连接引脚。
LCD显示的。
#include<reg52.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define LCDCOM XBYTE[0xcffc] //LCD写命令寄存器地址
#define LCDDATA XBYTE[0xcffd] //LCD写数据寄存器地址
#define LCDSTATUS XBYTE[0xcffe] //LCD读状态寄存器地址

#define DSA XBYTE[0x8f0a] //实时时钟寄存器A
#define DSB XBYTE[0x8f0b] //实时时钟寄存器B
#define DSC XBYTE[0x8f0c] //实时时钟寄存器C
#define DSD XBYTE[0x8f0d] //实时时钟寄存器D
#define SECOND XBYTE[0x8f05] //实时时钟分报警
sbit bflag=ACC^7;

uchar idata dt[7]={06,7,11,17,05,0,2}; //时间初值
uchar at[7]={9,8,7,4,2,0,6}; //年,月,日,时,分,秒,星期时标寄存器地址
uchar xdata *addr=0x8f00; //实时时钟片选地址

//函数的声明部分
//void delay1(uint x);
void lcd_busy();
void lcd_cmd(uchar lcd_cmd);
void lcd_data(uchar lcd_data);
void lcd_moveto(uchar position);
void init(void);
//void delay( unsigned int number );
void init_ds(void); //实时时钟初始化
void WDS(void); //写时标函数
void RDS(void); //读时标函数

uchar ymd[10]={2,0,0,0,0,0,0,0,0,0}; //年月日
uchar hms[8]={0,0,0,0,0,0,0,0}; //时分秒
uchar weekday[3];
uchar code dis_buf[12]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2e,0x3a};
void init_ds(void) //实时时钟初始化
{
DSA=0x2f; //选时钟32.768kHz;中断周期500ms
ACC=DSC; //清中断请求标志
ACC=DSD; //VRT=1;数据有效
DSB=0x7e; //中断允许,时标值为二进制码,24小时制,芯片工作,方波输出允许
}

void WDS(void) //写时标函数
{
uchar i;
DSB=0x8e; //置SET位为1
DSB=0x8e;
for(i=0;i<7;i++)
{
*(addr+at[i])=dt[i]; //置时标初值
}
}
void RDS(void)
{
uchar i;
do
{
ACC=DSA;
}
while(bflag==1);
for(i=0;i<7;i++)
{
dt[i]=*(addr+at[i]);
}
}

void lcd_busy() //检测lcd忙程序
{
do
{
ACC=LCDSTATUS;
}
while(bflag==1); //当他忙的时候就不停的检测,直到空闲为止
}

void lcd_cmd(uchar lcd_cmd) //写命令函数
{
LCDCOM=lcd_cmd;
lcd_busy();
}

void lcd_data(uchar lcd_data) //写数据函数
{
LCDDATA=lcd_data;
lcd_busy();

}

void lcd_moveto(uchar position) //确定显示位置
{
uchar temp; //为显示位置对应的地址
if (position<16)
temp=(position+0x80-1); //为在第一行
else
temp=((position-16)+0xc0); //为第二行
lcd_cmd(temp);
}

void init(void) //lcd初始化
{
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x38); //置功能:2行,5*7字符
lcd_busy();
lcd_cmd(0x06); //置输入模式:地址增量,显示屏不移动
lcd_busy();
lcd_cmd(0x0c); //置显示开,不显示光标,光标不闪烁
lcd_busy();
lcd_cmd(0x01); //清显示
lcd_busy();
}

void shizhong(void) //时钟的每一位取出来
{
ymd[2]=dt[0]/10;
ymd[3]=dt[0]%10;
ymd[4]=10;
ymd[5]=dt[1]/10;
ymd[6]=dt[1]%10;
ymd[7]=10;
ymd[8]=dt[2]/10;
ymd[9]=dt[2]%10;
hms[0]=dt[3]/10;
hms[1]=dt[3]%10;
hms[2]=11;
hms[3]=dt[4]/10;
hms[4]=dt[4]%10;
hms[5]=11;
hms[6]=dt[5]/10;
hms[7]=dt[5]%10;
使用芯片:AT89S52,DS12887时钟芯片,实践通过,运行稳定。自己根据程序连接引脚。
#include<reg52.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define LCDCOM XBYTE[0xcffc] //LCD写命令寄存器地址
#define LCDDATA XBYTE[0xcffd] //LCD写数据寄存器地址
#define LCDSTATUS XBYTE[0xcffe] //LCD读状态寄存器地址

#define DSA XBYTE[0x8f0a] //实时时钟寄存器A
#define DSB XBYTE[0x8f0b] //实时时钟寄存器B
#define DSC XBYTE[0x8f0c] //实时时钟寄存器C
#define DSD XBYTE[0x8f0d] //实时时钟寄存器D
#define SECOND XBYTE[0x8f05] //实时时钟分报警

sbit bflag=ACC^7;

uchar idata dt[7]={06,7,11,17,05,0,2}; //时间初值
uchar at[7]={9,8,7,4,2,0,6}; //年,月,日,时,分,秒,星期时标寄存器地址
uchar xdata *addr=0x8f00; //实时时钟片选地址

//函数的声明部分
//void delay1(uint x);
void lcd_busy();
void lcd_cmd(uchar lcd_cmd);
void lcd_data(uchar lcd_data);
void lcd_moveto(uchar position);
void init(void);
//void delay( unsigned int number );
void init_ds(void); //实时时钟初始化
void WDS(void); //写时标函数
void RDS(void); //读时标函数

uchar ymd[10]={2,0,0,0,0,0,0,0,0,0}; //年月日
uchar hms[8]={0,0,0,0,0,0,0,0}; //时分秒
uchar weekday[3];
uchar code dis_buf[12]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2e,0x3a};

/*void delay1(uint x) //延时1ms程序
{
uchar j;
while(x--)
{
for(j=0;j<125;j++)
{;}
}
}

void delay( unsigned int number )
{
unsigned char i;
unsigned int u;

while(u<number)
{
for(i=0;i<=125;i++);
u++;
}
} */

void init_ds(void) //实时时钟初始化
{
DSA=0x2f; //选时钟32.768kHz;中断周期500ms
ACC=DSC; //清中断请求标志
ACC=DSD; //VRT=1;数据有效
DSB=0x7e; //中断允许,时标值为二进制码,24小时制,芯片工作,方波输出允许
}

void WDS(void) //写时标函数
{
uchar i;
DSB=0x8e; //置SET位为1
DSB=0x8e;
for(i=0;i<7;i++)
{
*(addr+at[i])=dt[i]; //置时标初值
}
}

void RDS(void)
{
uchar i;
do
{
ACC=DSA;
}
while(bflag==1);
for(i=0;i<7;i++)
{
dt[i]=*(addr+at[i]);
}
}

void lcd_busy() //检测lcd忙程序
{
do
{
ACC=LCDSTATUS;
}
while(bflag==1); //当他忙的时候就不停的检测,直到空闲为止
}

void lcd_cmd(uchar lcd_cmd) //写命令函数
{
LCDCOM=lcd_cmd;
lcd_busy();
}

void lcd_data(uchar lcd_data) //写数据函数
{
LCDDATA=lcd_data;
lcd_busy();

}

void lcd_moveto(uchar position) //确定显示位置
{
uchar temp; //为显示位置对应的地址
if (position<16)
temp=(position+0x80-1); //为在第一行
else
temp=((position-16)+0xc0); //为第二行
lcd_cmd(temp);
}

void init(void) //lcd初始化
{
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x38); //置功能:2行,5*7字符
lcd_busy();
lcd_cmd(0x06); //置输入模式:地址增量,显示屏不移动
lcd_busy();
lcd_cmd(0x0c); //置显示开,不显示光标,光标不闪烁
lcd_busy();
lcd_cmd(0x01); //清显示
lcd_busy();
}

void shizhong(void) //时钟的每一位取出来
{
ymd[2]=dt[0]/10;
ymd[3]=dt[0]%10;
ymd[4]=10;
ymd[5]=dt[1]/10;
ymd[6]=dt[1]%10;
ymd[7]=10;
ymd[8]=dt[2]/10;
ymd[9]=dt[2]%10;
hms[0]=dt[3]/10;
hms[1]=dt[3]%10;
hms[2]=11;
hms[3]=dt[4]/10;
hms[4]=dt[4]%10;
hms[5]=11;
hms[6]=dt[5]/10;
hms[7]=dt[5]%10;
switch(dt[6])
{

case 1:weekday[0]='m';weekday[1]='o';weekday[2]='n';break;
case 2:weekday[0]='t';weekday[1]='u';weekday[2]='e';break;
case 3:weekday[0]='w';weekday[1]='e';weekday[0]='n';break;
case 4:weekday[0]='t';weekday[1]='h';weekday[2]='u';break;
case 5:weekday[0]='f';weekday[1]='r';weekday[2]='i';break;
case 6:weekday[0]='s';weekday[1]='a';weekday[0]='t';break;
case 7:weekday[0]='s';weekday[1]='u';weekday[0]='n';break;
}
}

void main(void)
{
uchar i;
WDS();
init_ds();
init();
while(1)
{
RDS();
shizhong();
lcd_moveto(3);
for(i=0;i<10;i++)
{
lcd_data(dis_buf[ymd[i]]);
}
lcd_moveto(17);
for(i=0;i<8;i++)
{
lcd_data(dis_buf[hms[i]]);
}
lcd_data(0x20);
for(i=0;i<3;i++)
{
lcd_data(weekday[i]);
}
}
}
方案2:用内部的定时器做数字钟,通过数码管显示出来
使用芯片:AT89S52,DS12887时钟芯片,实践通过,运行稳定。自己根据程序连接引脚。
#include<reg52.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define LCDCOM XBYTE[0xcffc] //LCD写命令寄存器地址
#define LCDDATA XBYTE[0xcffd] //LCD写数据寄存器地址
#define LCDSTATUS XBYTE[0xcffe] //LCD读状态寄存器地址

#define DSA XBYTE[0x8f0a] //实时时钟寄存器A
#define DSB XBYTE[0x8f0b] //实时时钟寄存器B
#define DSC XBYTE[0x8f0c] //实时时钟寄存器C
#define DSD XBYTE[0x8f0d] //实时时钟寄存器D
#define SECOND XBYTE[0x8f05] //实时时钟分报警

sbit bflag=ACC^7;

uchar idata dt[7]={06,7,11,17,05,0,2}; //时间初值
uchar at[7]={9,8,7,4,2,0,6}; //年,月,日,时,分,秒,星期时标寄存器地址
uchar xdata *addr=0x8f00; //实时时钟片选地址

//函数的声明部分
//void delay1(uint x);
void lcd_busy();
void lcd_cmd(uchar lcd_cmd);
void lcd_data(uchar lcd_data);
void lcd_moveto(uchar position);
void init(void);
//void delay( unsigned int number );
void init_ds(void); //实时时钟初始化
void WDS(void); //写时标函数
void RDS(void); //读时标函数

uchar ymd[10]={2,0,0,0,0,0,0,0,0,0}; //年月日
uchar hms[8]={0,0,0,0,0,0,0,0}; //时分秒
uchar weekday[3];
uchar code dis_buf[12]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2e,0x3a};

/*void delay1(uint x) //延时1ms程序
{
uchar j;
while(x--)
{
for(j=0;j<125;j++)
{;}
}
}

void delay( unsigned int number )
{
unsigned char i;
unsigned int u;

while(u<number)
{
for(i=0;i<=125;i++);
u++;
}
} */

void init_ds(void) //实时时钟初始化
{
DSA=0x2f; //选时钟32.768kHz;中断周期500ms
ACC=DSC; //清中断请求标志
ACC=DSD; //VRT=1;数据有效
DSB=0x7e; //中断允许,时标值为二进制码,24小时制,芯片工作,方波输出允许
}

void WDS(void) //写时标函数
{
uchar i;
DSB=0x8e; //置SET位为1
DSB=0x8e;
for(i=0;i<7;i++)
{
*(addr+at[i])=dt[i]; //置时标初值
}
}

void RDS(void)
{
uchar i;
do
{
ACC=DSA;
}
while(bflag==1);
for(i=0;i<7;i++)
{
dt[i]=*(addr+at[i]);
}
}

void lcd_busy() //检测lcd忙程序
{
do
{
ACC=LCDSTATUS;
}
while(bflag==1); //当他忙的时候就不停的检测,直到空闲为止
}

void lcd_cmd(uchar lcd_cmd) //写命令函数
{
LCDCOM=lcd_cmd;
lcd_busy();
}

void lcd_data(uchar lcd_data) //写数据函数
{
LCDDATA=lcd_data;
lcd_busy();

}

void lcd_moveto(uchar position) //确定显示位置
{
uchar temp; //为显示位置对应的地址
if (position<16)
temp=(position+0x80-1); //为在第一行
else
temp=((position-16)+0xc0); //为第二行
lcd_cmd(temp);
}

void init(void) //lcd初始化
{
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x30); //置功能:1行,5*7字符
lcd_busy();
lcd_cmd(0x38); //置功能:2行,5*7字符
lcd_busy();
lcd_cmd(0x06); //置输入模式:地址增量,显示屏不移动
lcd_busy();
lcd_cmd(0x0c); //置显示开,不显示光标,光标不闪烁
lcd_busy();
lcd_cmd(0x01); //清显示
lcd_busy();
}

void shizhong(void) //时钟的每一位取出来
{
ymd[2]=dt[0]/10;
ymd[3]=dt[0]%10;
ymd[4]=10;
ymd[5]=dt[1]/10;
ymd[6]=dt[1]%10;
ymd[7]=10;
ymd[8]=dt[2]/10;
ymd[9]=dt[2]%10;
hms[0]=dt[3]/10;
hms[1]=dt[3]%10;
hms[2]=11;
hms[3]=dt[4]/10;
hms[4]=dt[4]%10;
hms[5]=11;
hms[6]=dt[5]/10;
hms[7]=dt[5]%10;
switch(dt[6])
{

case 1:weekday[0]='m';weekday[1]='o';weekday[2]='n';break;
case 2:weekday[0]='t';weekday[1]='u';weekday[2]='e';break;
case 3:weekday[0]='w';weekday[1]='e';weekday[0]='n';break;
case 4:weekday[0]='t';weekday[1]='h';weekday[2]='u';break;
case 5:weekday[0]='f';weekday[1]='r';weekday[2]='i';break;
case 6:weekday[0]='s';weekday[1]='a';weekday[0]='t';break;
case 7:weekday[0]='s';weekday[1]='u';weekday[0]='n';break;
}
}

void main(void)
{
uchar i;
WDS();
init_ds();
init();
while(1)
{
RDS();
shizhong();
lcd_moveto(3);
for(i=0;i<10;i++)
{
lcd_data(dis_buf[ymd[i]]);
}
lcd_moveto(17);
for(i=0;i<8;i++)
{
lcd_data(dis_buf[hms[i]]);
}
lcd_data(0x20);
for(i=0;i<3;i++)
{
lcd_data(weekday[i]);
}
}
}

再给一个:用内部的定时器做数字钟,通过数码管显示出来。

#include <regx52.h>
#define uchar unsigned char
#define uint unsigned int
uchar dispcode[]={ 0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00}; //定义0到F的段选码

uchar dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f}; //8位数码管的位选码
uchar dispbuf[8]={ 0,0,16,0,0,16,0,0}; //定义一个缓冲区
uchar dispbitcnt;
uchar second;
uchar minite;
uchar hour;
uint tcnt;
uchar mstcnt;
uchar i,j;

void main(void)
{
TMOD=0x02; //定时器0工作方式2
TH0=0x06; //每250us中断一次
TL0=0x06;
TR0=1; //启动定时器0
ET0=1; //定时器0中断允许
EA=1; //CPU开中断

while(1)
{
if(P0_0==0)
{ for(i=5;i>0;i--)
for(j=248;j>0;j--); //延时检查是否是P0_0被按下
if(P0_0==0) //如果被按下
{
second++; //秒就加1
if (second==60)
{
second=0;
}
dispbuf[0] =second%10; //存放秒的个位
dispbuf[1] =second/10; //存放秒的十位
while (P0_0==0); //等待P0_0变高
}
}
if(P0_1==0)
{ for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_1==0)
{
minite++;
if (minite==60)
{
minite=0;
}
dispbuf[3] =minite%10;
dispbuf[4] =minite/10;
while (P0_1==0);
} }
if(P0_2==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_2==0)
{
hour++;
if(hour==24)
{
hour=0;
}
dispbuf[6] =hour%10;
dispbuf[7] =hour/10;
while (P0_2==0);
} } } }
void t0 (void) interrupt 1 using 0 //定时器0中断服务程序
{
P1=dispcode[dispbuf[dispbitcnt]]; //为位选码
P3=dispbitcode[dispbitcnt]; //为段选码
dispbitcnt++;
if(dispbitcnt==8)
{
dispbitcnt=0;
}

tcnt++;
if(tcnt==4000) //此时有一秒钟了(4000*250us)
{
tcnt=0;
second++;
if(second==60)
{
second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
}
注:至于你说的蜂鸣器,这个很简单,在程序里设置一个标志位
sbit busy_louder 在硬件连接上采用一个放大器 与单片机的一个引脚相接 即时到60秒时,计时器清零,同时标志位置位,即可~
希望对你有帮助。
温馨提示:答案为网友推荐,仅供参考
相似回答