1.是个循环,而且是个死循环。他在单片机中是常要用到的,功能就是只要单片机上电它使程序不停里执行死循环里的内容!
2.这个看你的单片机的硬件电路了,你最好也先看懂硬件电路才编程。通常LED的公共端是用三极管选通的!看来你的LED是共阳极接法的,就是8个LED正极共同接到三极管的发射极,集电极接VCC,基极连到P1口的接法,如果你会三极管,应该就能看懂为什么了!P1=0,三极管正向导通,VCC加到LED上,如果LED的另一端接的是低电平,使LED正偏,则LED亮。想想吧~~
3。CPU不停地执行while(1)里面的语句,但是当有中断发生时,CPU得先去执行中断,然后才能返回到while处继续执行,也就相当等待中断了!也就是说:有中断发生CPU就立该执行中断,没有的话就一直执行while(1)里面的~~
;----------
这就是注释,注释不一定非要写文字吗,只要是分号,后面就是注释,这样的注释也是很常见的,可以把程序分成几部分,或分成几段,这样看起来,比较清楚。这还不好理解吗?
基于c8051f020单片机最小系统的实时时钟显示程序
c8051f020 FYD12864-0402B LCD显示,按键电子时钟//
#include c8051f020.h
#includelcd.h
#include intrins.h
#define uchar unsigned char
void lcd_ini();
void DISPInitial();
void ascii_change(void);
void delay();
void wri_add(uchar com);
void wri_dat(uchar com1);
void shan(void);
void disp();
void tkey(void);
void PORT_Init (void);
sbit cs=P1^7;
sbit sid=P1^6;
sbit sclk=P1^5;
bit flag=1;
uchar dat,count,f=1;//f测试哪个单元为当前闪烁状态
uchar data clock[3]={24,00,00};
uchar code clockname[10]={"北京时间:"};
uchar data num[6];
/*******主程序*************/
void main()
{
lcd_ini();
count=10;//机器周期为1us,每次定时50ms,此变量用来控制循环次数,在下面赋值为20,共定时1秒
TMOD=0x01;
TL0=0XB0;
TH0=0X3C;
EA=1;
ET0=1;
IT0=1;
EX0=1;
TR0=1;
while(1)
{
back:ascii_change();
disp();
delay();
if(flag==1)
goto back;
tkey();
shan();
delay();
}
}
/****lcd初始化*******/
/*void lcd_ini()
{
wri_add(0x30);
delay();
wri_add(0x0c);
delay();
wri_add(0x01);
delay();
wri_add(0x06);
delay();
}*/
void PORT_Init (void)
{
XBR0 = 0x00; //不让他连上IO口
XBR1 = 0x14; //允许外部中断连在端口上
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P0MDOUT |= 0x00; // enable TX0 as a push-pull output
// P1MDOUT |= 0x07; // enable P1.6 (LED) as push-pull output
P2MDOUT=0xfe; //为了驱动步进电机的控制线
//P3MDOUT = 0xFF;
P74OUT=0x00; //配置成漏极方式可以让LCD显示成功 ,我试了配置成推挽方式不能正常显示
}
/********定时程序*************/
void timer1() interrupt 1 using 2
{
TL0=0XB0;
TH0=0X3C;
count--;
if(count==0)
{
count=10;
clock[2]++;//秒//
}
else
goto out;
if(clock[2]==60)
{
clock[2]=0;
clock[1]++;//分//
}
if(clock[1]==60)
{
clock[1]=0;
clock[0]++;
}
if(clock[0]==24)//时//
clock[0]=0;
out:_nop_();
}
/*******十位个位转换成ASCII码************/
void ascii_change(void)
{
num[5]=clock[2]-(clock[2]/10)*10+0x30;
num[4]=clock[2]/10+0x30;
num[3]=clock[1]-(clock[1]/10)*10+0x30;
num[2]=clock[1]/10+0x30;
num[1]=clock[0]-(clock[0]/10)*10+0x30;
num[0]=clock[0]/10+0x30;
}
/********廷时程序*************/
void delay()
{
uchar i,j;
for (i=250;i0;i--)
for (j=250;j0;j--);
}
/*****Write address*********/
void wri_add(uchar com)
{
uchar i,j,k;
cs=0;
cs=1;
dat=0xf8;
for(i=1;i=8;i++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
dat=com;
dat=dat0xf0;
for(j=1;j=8;j++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
dat=com;
dat=_cror_(dat,4);// 此为高低四位交换
dat=dat0xf0;
for(k=1;k=8;k++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
}
/*********Write data*************/
void wri_dat(uchar com1)
{
uchar i,j,k;
cs=0;
cs=1;
dat=0xfa;
for(i=1;i=8;i++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
dat=com1;
dat=dat0xf0;
for(j=1;j=8;j++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
dat=com1;
dat=_cror_(dat,4);// 此为高低四位交换
dat=dat0xf0;
for(k=1;k=8;k++)
{
sid=(bit)(dat0x80);
sclk=0;
sclk=1;
sclk=0;
dat=dat1;
}
}
/******display program***********/ //显示时间
void disp()
{
uchar i,k=0;
wri_add(0x80);
for (i=1;i=9;i++)
wri_dat(clockname[i-1]);
wri_add(0x90);
for (i=1;i=6;i++)
{
k++;
if(k==3||k==5)
wri_dat(clockname[8]);//时间之间的冒号。
wri_dat(num[i-1]);
}
}
/*******闪烁程序*************************/
void shan(void)
{
uchar i,k=0;
wri_add(0x90);
if(f==1)
{
num[0]=' ';
num[1]=' ';
}
else
goto next;
for (i=1;i=6;i++)
{
k++;
if(k==3||k==5)
wri_dat(clockname[8]);//时间之间的冒号。
wri_dat(num[i-1]);
}
goto return1;
next: if(f==2)
{
num[2]=' ';
num[3]=' ';
}
else
goto next1;
for (i=1;i=6;i++)
{
k++;
if(k==3||k==5)
wri_dat(clockname[8]);//时间之间的冒号。
wri_dat(num[i-1]);
}
goto return1;
next1: if(f==3)
{
num[4]=' ';
num[5]=' ';
}
else
goto return1;
for (i=1;i=6;i++)
{
k++;
if(k==3||k==5)
wri_dat(clockname[8]);//时间之间的冒号。
wri_dat(num[i-1]);
}
return1:_nop_();
}
/*******外部中断***********/
void intr0() interrupt 0 using 2
{
flag=~flag;//判断是否闪烁位//
TR0=~TR0; //闪关定时否则开定时
f=1;
}
/**********按键程序************/
void tkey(void)
{
uchar judcekey;
judcekey=P10x0f;
if(judcekey==0x0f)
goto return2;
/*******移位键*********/
if (judcekey==0x0e)
f++;
if (f==4)
f=1;
/**********加一键*********/
if(judcekey==0x0d)
{clock[f-1]++;}
if (f==1)
{ if (clock[f-1]==24){
clock[f-1]=0;}
}
else{ if (clock[f-1]==60)
clock[f-1]=0;
}
/******减一键***********/
if(judcekey==0x0b)
{clock[f-1]--;}
if (f==1)
{ if (clock[f-1]==0xff){
clock[f-1]=23;}
}
else
{ if (clock[f-1]==0xff)
clock[f-1]=59;
}
return2:_nop_();
}
//本程序已经调试成功并能够正确执行
//实际晶振为11.0592MHz
//为方便计算,假设为12MHz
#includereg52.h //包含52单片机头文件
#define uchar unsigned char //宏定义
#define uint unsigned int //红定义
//#include24c02.h
sbit dula=P2^6; //定义锁存器锁存端
sbit wela=P2^7;
sbit rs=P3^5; //定义1602液晶RS端
sbit lcden=P3^4; //定义1602液晶LCDEN端
sbit s1=P3^0; //定义按键——功能键
sbit s2=P3^1; //定义按键——增大键
sbit s3=P3^2; //定义按键——减小键
//sbit s4=P3^6; //闹钟查看器
sbit rd=P3^7;
sbit beep=P2^3; //蜂鸣器
sbit dscs=P1^4;
sbit dsas=P1^5;
sbit dsrw=P1^6;
sbit dsds=P1^7;
sbit dsirq=P3^3;
bit flag1,flag_ri; //定义两个位变量
uchar count,s1num,flag,t0_num; //其他变量定义
char miao,fen,shi,day,month,year,week,amiao,afen,ashi;
uchar code table[]=" 20 - - "; //定义初始上电时液晶默认显示状态
//uchar code table1[]=" : : ";
void write_ds(uchar,uchar); //函数声明
uchar read_ds(uchar);
void set_time();
void delay(uint z) //延时函数
{
uint x,y;
for(x=z;x0;x--)
for(y=110;y0;y--);
}
void di() //蜂鸣器报警声音
{
beep=0;
delay(100);
beep=1;
}
void write_com(uchar com) //写液晶命令函数
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date) //写液晶数据函数
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_sfm(uchar add,uchar date) //写时分秒函数
{
uchar shi,ge;
shi=date/10; //分解一个2位数的十位和个位
ge=date%10;
write_com(0x80+0x40+add); //设置显示位置
write_date(0x30+shi); //送去液晶显示十位
write_date(0x30+ge); //送去液晶显示个位
}
void write_nyr(uchar add,uchar date) //写年月日函数
{
uchar shi,ge;
shi=date/10; //分解一个2位数的十位和个位
ge=date%10;
write_com(0x80+add); //设置显示位置
write_date(0x30+shi); //送去液晶显示十位
write_date(0x30+ge); //送去液晶显示个位
}
void write_week(char we)
{ //写液晶星期显示函数
write_com(0x80+12);
switch(we)
{
case 1: write_date('M');
delay(5);
write_date('O');
delay(5);
write_date('N');
break;
case 2: write_date('T');
delay(5);
write_date('U');
delay(5);
write_date('E');
break;
case 3: write_date('W');
delay(5);
write_date('E');
delay(5);
write_date('D');
break;
case 4: write_date('T');
delay(5);
write_date('H');
delay(5);
write_date('U');
break;
case 5: write_date('F');
delay(5);
write_date('R');
delay(5);
write_date('I');
break;
case 6: write_date('S');
delay(5);
write_date('A');
delay(5);
write_date('T');
break;
case 7: write_date('S');
delay(5);
write_date('U');
delay(5);
write_date('N');
break;
}
}
void init() //初始化函数
{
uchar num;
rd=0; //软件将矩阵按键第四列一端置低用以分解出独立按键
dula=0; //关闭两锁存器锁存端,防止操作液晶时数码管出现乱码
wela=0;
lcden=0;
fen=0; //初始化分钟变量值
miao=0;
shi=0;
day=1;
month=1;
year=12;
week=1;
count=0;
s1num=0;
// init_24c02();
//一下几行在首次设置DS12C887时使用,以后不必在写入
// write_ds(0x0A,0x20); //打开振荡器
// write_ds(0x0B,0x26); //设置24小时模式,数据二进制格式 ,开启闹铃中断
set_time(); //设置上电默认时间
write_com(0x38); //初始化1602液晶
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80); //设置显示初始坐标
for(num=0;num15;num++) //显示年月日星期
{
write_date(table[num]);
delay(5);
}
/* for(num=0;num12;num++)
{
write_date(table1[num]);
delay(5);
}
*/
write_com(0x80+0x40+6); //写出时间显示部分的两个冒号
write_date(':');
delay(5);
write_com(0x80+0x40+9);
write_date(':');
delay(5);
// miao=read_add(1);
// fen=read_add(2);
// shi=read_add(3);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
write_nyr(9,day);
write_nyr(6,month);
write_nyr(3,year);
write_week(week);
TMOD=0x01; //设置定时器0工作模式1
TH0=(65536-50000)/256; //定时器装初值
TL0=(65536-50000)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
}
void keyscan() //按键扫描函数
{
// rd=0; //前面已定义
if(s1==0)
{
delay(5);
if(s1==0) //确认功能键被按下
{ s1num++; //功能键按下次数记录
while(!s1); //释放确认
di(); //每当有按键释放蜂鸣器发出滴声
if(s1num==1) //第一次被按下时
{
TR0=0; //关闭定时器
write_com(0x80+0x40+10); //光标定位到秒位置
write_com(0x0f); //光标开始闪烁
}
if(s1num==2) //第二次按下光标闪烁定位到分钟位置
{
write_com(0x80+0x40+7);
}
if(s1num==3) //第三次按下光标闪烁定位到小时位置
{
write_com(0x80+0x40+4);
}
if(s1num==4) //第四次按下光标闪烁定位到日期位置
{
write_com(0x80+9);
}
if(s1num==5) //第五次按下光标闪烁定位到月份位置
{
write_com(0x80+6);
}
if(s1num==6) //第六次按下光标闪烁定位到年份位置
{
write_com(0x80+3);
}
if(s1num==7) //第七次按下光标闪烁定位到年份位置
{
write_com(0x80+12);
}
if(s1num==8) //第八次按下
{
s1num=0; //记录按键数清0
write_com(0x0c); //取消光标闪烁
TR0=1; //启动定时器使时钟走
}
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
write_ds(6,week);
write_ds(7,day);
write_ds(8,month);
write_ds(9,year);
// break;
}
}
if(s1num!=0) //只有功能键被按下后,增大和减小键才有效
{
if(s2==0)
{
delay(5);
if(s2==0) //增大键确认被按下
{
while(!s2); //按键释放
di(); //每当有按键释放蜂鸣器发出滴声
if(s1num==1) //若功能键第一次按下
{
miao++; //则调整秒加1
if(miao==60) //若满60后将清0
miao=0;
write_sfm(10,miao); //每调节一次送液晶显示一下
write_com(0x80+0x40+10); //显示位置重新回到调节处
// write_add(1,miao); //数据改变立即存入24C02
}
if(s1num==2) //若功能键第二次按下
{
fen++; //则调整分钟加1
if(fen==60) //若满60后将清0
fen=0;
write_sfm(7,fen); //每调节一次送液晶显示一下
write_com(0x80+0x40+7); //显示位置重新回到调节处
// write_add(2,fen);
}
if(s1num==3) //若功能键第三次按下
{
shi++; //则调整小时加1
if(shi==24) //若满24后将清0
shi=0;
write_sfm(4,shi);//每调节一次送液晶显示一下
write_com(0x80+0x40+4); //显示位置重新回到调节处
// write_add(3,shi); //数据改变立即存入24C02
}
if(s1num==4) //若功能键第四次按下
{
day++; //则调整日期加1
if(day==32) //若满31后将清0
day=1;
write_nyr(9,day);//每调节一次送液晶显示一下
write_com(0x80+9); //显示位置重新回到调节处
// write_add(9,day); //数据改变立即存入24C02
}
if(s1num==5) //若功能键第五次按下
{
month++; //则调整月份加1
if(month==13) //若满12后将清0
month=1;
write_nyr(6,month);//每调节一次送液晶显示一下
write_com(0x80+6); //显示位置重新回到调节处
// write_add(6,month); //数据改变立即存入24C02
}
if(s1num==6) //若功能键第六次按下
{
year++; //则调整年份加1
if(year==33) //若满32后将返回初始年份
year=12;
write_nyr(3,year);//每调节一次送液晶显示一下
write_com(0x80+3); //显示位置重新回到调节处
// write_add(3,year); //数据改变立即存入24C02
}
if(s1num==7) //若功能键第七次按下
{
week++; //则调整年份加1
if(week==8) //若满32后将返回初始年份
week=1;
write_week(week);//每调节一次送液晶显示一下
write_com(0x80+12); //显示位置重新回到调节处
// write_add(week); //数据改变立即存入24C02
}
}
}
if(s3==0)
{
delay(5);
if(s3==0) //确认减小按键按下
{
while(!s3); //按键释放
di(); //每当有按键释放蜂鸣器发出滴声
if(s1num==1) //若功能键第一次按下
{
miao--; //则调整秒减1
if(miao==-1) //若减到负数则将其重新设置为59
miao=59;
write_sfm(10,miao); //每调节一次送液晶显示一下
write_com(0x80+0x40+10); //显示位置重新回到调节处
// write_add(1,miao); //数据改变立即存入24C02
}
if(s1num==2) //若功能键第二次按下
{
fen--; //则调整分钟减1
if(fen==-1) //若减到负数则将其重新设置为59
fen=59;
write_sfm(7,fen); //每调节一次送液晶显示一下
write_com(0x80+0x40+7); //显示位置重新回到调节处
// write_add(2,fen); //数据改变立即存入24C02
}
if(s1num==3) //若功能键第三次按下
{
shi--; //则调整小时减1
if(shi==-1) //若减到负数则将其重新设置为23
shi=23;
write_sfm(4,shi); //每调节一次送液晶显示一下
write_com(0x80+0x40+4); //显示位置重新回到调节处
// write_add(3,shi); //数据改变立即存入24C02
}
if(s1num==4) //若功能键第四次按下
{
day--; //则调整日期减1
if(day==0) //若减到0则将其重新设置为31
day=31;
write_nyr(9,day); //每调节一次送液晶显示一下
write_com(0x80+9); //显示位置重新回到调节处
// write_add(9,day); //数据改变立即存入24C02
}
if(s1num==5) //若功能键第五次按下
{
month--; //则调整月份减1
if(month==0) //若减到0则将其重新设置为12
month=12;
write_nyr(6,month); //每调节一次送液晶显示一下
write_com(0x80+6); //显示位置重新回到调节处
// write_add(6,month); //数据改变立即存入24C02
}
if(s1num==6) //若功能键第六次按下
{
year--; //则调整月份减1
if(year==11) //若减到初始值则将其重新设置为32
year=32;
write_nyr(3,year); //每调节一次送液晶显示一下
write_com(0x80+3); //显示位置重新回到调节处
// write_add(3,year); //数据改变立即存入24C02
}
if(s1num==7) //若功能键第七次按下
{
week--; //则调整月份减1
if(week==0) //若减到初始值则将其重新设置为32
week=7;
write_week(week); //每调节一次送液晶显示一下
write_com(0x80+12); //显示位置重新回到调节处
// write_add(week); //数据改变立即存入24C02
}
}
}
}
}
void write_ds(uchar add,uchar date)
{ //写12C887函数
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add; //先写地址
dsas=0;
dsrw=0;
P0=date; //再写数据
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add)
{ //读12C887函数
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add; //先写地址
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0; //再读数据
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
void set_time()
{ //首次上电初始化时间函数
write_ds(0,0);
write_ds(1,0);
write_ds(2,0);
write_ds(3,0);
write_ds(4,0);
write_ds(5,0);
write_ds(6,0);
write_ds(7,0);
write_ds(8,0);
write_ds(9,0);
}
void main() //主函数
{
init(); //首先初始化各函数
while(1) //进入主程序大循环
{
keyscan(); //不停地检测按键是否被按下
if(flag==0flag1==0) //正常工作时进入这里
{
keyscan(); //按键扫描
year=read_ds(9); //读取12C887数据
month=read_ds(8);
day=read_ds(7);
week=read_ds(6);
shi=read_ds(4);
fen=read_ds(2);
miao=read_ds(0);
write_sfm(10,miao); //送液晶显示
write_sfm(7,fen);
write_sfm(4,shi);
write_week(week);
write_nyr(3,year);
write_nyr(6,month);
write_nyr(9,day);
}
}
// while(1);
}
void timer0() interrupt 1 //定时器0中断服务程序
{
TH0=(65536-50000)/256; //再次装定时器初值
TL0=(65536-50000)%256;
count++; //中断次数累加
if(count==20) //20次50毫秒为1秒
{
count=0;
miao++;
if(miao==60) //秒加到60则进位分钟
{
miao=0; //同时秒数清0
fen++;
if(fen==60) //分钟加到60则进位小时
{
fen=0; //同时分钟数清0
shi++;
if(shi==24) //小时加到24则进位日期
{
shi=0; //同时小时数清0
day++;
if(day==31) //日期加到31则进位月份
{
day=0; //同时日期数清0
month++;
if(month==12) //月份加到12则进位年份
{
month=0; //同时月份数清0
year++;
if(year==99) //年份加到32则将年份返回初始值
{
year=0;
}
write_nyr(3,year);
// write_add(3,year); //数据改变立即存入24C02
}
write_nyr(6,month);
// write_add(6,month); //数据改变立即存入24C02
}
write_nyr(9,day);
// write_add(9,day); //数据改变立即存入24C02
}
write_sfm(4,shi); //小时若变化则重新写入
// write_add(3,shi); //数据改变立即存入24C02
}
write_sfm(7,fen); //分钟若变化则重新写入
// write_add(2,fen); //数据改变立即存入24C02
}
write_sfm(10,miao); //秒若变化则重新写入
// write_add(1,miao); //数据改变立即存入24C02
}
}
这都是我调试好用过的程序,不知道硬件连接的是不是一样,希望对你有帮助。
#includereg52.h
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;
#define yh 0x80
#define er 0x80+0x40//液晶屏的与 C51 之间的引脚连接定义
sbit rs=P2^5;
sbit en=P2^7;
sbit rw=P2^6;//如果硬件上 rw 接地,就不用写这句和后面的 rw=0
//DS1302 时钟芯片与 C51 之间的引脚连接定义
sbit IO=P3^6;
sbit SCLK=P3^5;
sbit RST=P3^7;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;//校时按键与 C51 的引脚连接定义
sbit key1=P3^2;//设置键
sbit key2=P3^3;//加键
sbit key3=P3^4;//减键
uchar code tab1[]={"20//////////"};//年显示的固定字符
uchar code tab2[]={"LOVE ::::::"};//时间显示的固定字符
//延时函数,后面经常调用
void delay(uint xms)//延时函数,有参函数
{
uint x,y;
for(x=xms;x0;x--)
for(y=110;y0;y--);
}
/********液晶写入指令函数与写入数据函数,以后可调用**************/
write_1602com(uchar com) //****液晶写入指令函数****
{
rs=0; //数据/指令选择置为指令
rw=0; //读写选择 置为写
P0=com; //送入数据
delay(1);
en=1; //拉高使能端,为制造有效的下降沿做准备
delay(1);
en=0;
//en 由高变低,产生下降沿,液晶执行命令
}
write_1602dat(uchar dat) //***液晶写入数据函数****
{
rs=1; //数据/指令选择置为数据
rw=0; //读写选择置为写
P0=dat; //送入数据
delay(1);
en=1; //en 置高电平,为制造下降沿做准备
delay(1);
en=0; //en 由高变低,产生下降沿,液晶执行命令
}
lcd_init() //***液晶初始化函数****//
{
write_1602com(0x38); //设置液晶工作模式,意思:16*2 行显示,5*7 点阵,8 位数据
write_1602com(0x0c); //开显示不显示光标
write_1602com(0x06); //整屏不移动,光标自动右移
write_1602com(0x01); //清显示
write_1602com(yh+1); //日历显示固定符号从第一行第 1 个位置之后开始显示
for(a=0;a14;a++)
{
write_1602dat(tab1[a]); //向液晶屏写日历显示的固定符号部分
}
write_1602com(er+1);//时间显示固定符号写入位置,从第 2 个位置后开始显示
for(a=0;a12;a++)
{
write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号
}
}
/***************DS1302 有关子函数********************/
void write_byte(uchar dat)//写一个字节
{
ACC=dat;
RST=1;
for(a=8;a0;a--)
{
IO=ACC0;//相当于汇编中的 RRC
SCLK=0;
SCLK=1;
ACC=ACC1;
}
}
uchar read_byte() //读一个字节
{
RST=1;
for(a=8;a0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC1;
}
return (ACC);
}
//----------------------------------------//
void write_1302(uchar add,uchar dat) //向 1302 芯片写函数,指定写入地址,数据
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
uchar read_1302(uchar add) //从 1302 读数据函数,指定读取数据来源地址
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd)//BCD 码转十进制函数,输入 BCD,返回十进制
{
uchar Decimal;
Decimal=bcd4;
return(Decimal=Decimal*10+(bcd=0x0F));
}
//--------------------------------------//
void ds1302_init()//1302 芯片初始化子函数(2010-01-07,12:00:00,week4)
{
RST=0;
SCLK=0;
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x8e,0x80);//打开写保护
}
//时分秒显示子函数
void write_sfm(uchar add,uchar dat)//向 LCD 写时分秒,有显示位置加、现示数据,两个参数
{
uchar gw,sw;
gw=dat%10;//取得个位数字
sw=dat/10;//取得十位数字
write_1602com(er+add);//er 是头文件规定的值 0x80+0x40
write_1602dat(0x30+sw);//数字+30 得到该数字的 LCD1602 显示码
write_1602dat(0x30+gw);//数字+30 得到该数字的 LCD1602 显示码
}
//年月日显示子函数
void write_nyr(uchar add,uchar dat)//向 LCD 写年月日,有显示位置加数、显示数据,两个参数
{
uchar gw,sw;
gw=dat%10;//取得个位数字
sw=dat/10;//取得十位数字
write_1602com(yh+add);//设定显示位置为第一个位置+add
write_1602dat(0x30+sw);//数字+30 得到该数字的 LCD1602 显示码
write_1602dat(0x30+gw);//数字+30 得到该数字的 LCD1602 显示码
}
void write_week(uchar week)//写星期函数
{
write_1602com(yh+0x0c);//星期字符的显示位置
switch(week)
{
case 1:write_1602dat('M');//星期数为一时,显示
write_1602dat('o');
write_1602dat('n');break;
case 2:write_1602dat('T');//星期数据为二时显示
write_1602dat('u');
write_1602dat('e');break;
case 3:write_1602dat('W');//星期数据为三时显示
write_1602dat('e');
write_1602dat('d');break;
case 4:write_1602dat('T');//星期数据为四是显示
write_1602dat('h');
write_1602dat('u');break;
case 5:write_1602dat('F');//星期数据为五时显示
write_1602dat('r');
write_1602dat('i');break;
case 6:write_1602dat('S');//星期数据为六时显示
write_1602dat('t');
write_1602dat('a');break;
case 7:write_1602dat('S');//星期数据为日时显示
write_1602dat('u');
write_1602dat('n');break;
}
}
//****************键盘扫描有关函数**********************
void keyscan()
{
if(key1==0)//key1 为功能键(设置键)
{
delay(9);//延时,用于消抖动
if(key1==0)//延时后再次确认按键按下
{
delay(20);
while(!key1);
key1n++;
if(key1n==9)
key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8 个功能循环
switch(key1n)
{
case 1:TR0=0;//关闭定时器
write_1602com(er+0x0E);//设置按键按动一次,秒位置显示光标
write_1602com(0x0f);//设置光标为闪烁
temp=(miao)/10*16+(miao)%10;//秒数据写入 DS1302
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);//miao
write_1302(0x8e,0x80);break;
case 2:write_1602com(er+11);//按 2 次 fen 位置显示光标
break;
case 3:write_1602com(er+8);//按动 3 次,shi
break;
case 4:write_1602com(yh+0x0e);//按动 4 次,week
break;
case 5:write_1602com(yh+0x0a);//按动 5 次,ri
break;
case 6:write_1602com(yh+0x07);//按动 6 次,yue
break;
case 7:write_1602com(yh+0x04);//按动 7 次,nian
break;
case 8:write_1602com(0x0c);//按动到第 8 次,设置光标不闪烁
TR0=1;//打开定时器
TR0=1;
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp);//miao 数据写入 DS1302
write_1302(0x8e,0x80);break;
}
}
}
//------------------------------加键 key2----------------------------//
if(key1n!=0)//当 key1 按下以下。再按以下键才有效(按键次数不等于零)
{
if(key2==0)//上调键
{
delay(10);
if(key2==0)
{
delay(20);
while(!key2);
switch(key1n)
{
case 1:miao++;//设置键按动 1 次,调秒
if(miao==60)
miao=0;
write_sfm(0x0D,miao);
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,temp);
write_1302(0x8e,0x80);
write_1602com(er+0x0E);
break;
case 2:fen++;
if(fen==60)
fen=0;
write_sfm(0x0A,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+11);
break;
case 3:shi++;
if(shi==24)
shi=0;
write_sfm(7,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
break;
case 4:week++;
if(week==8)
week=1;
write_1602com(yh+0x0C) ;
write_week(week);
temp=(week)/10*16+(week)%10;
write_1302(0x8e,0x00);
write_1302(0x8a,temp);
write_1302(0x8e,0x80);
write_1602com(yh+0x0e);
break;
case 5:ri++;
if(ri==32)
ri=1;
write_nyr(9,ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
write_1602com(yh+10);
break;
case 6:yue++;
if(yue==13)
yue=1;
write_nyr(6,yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
write_1602com(yh+7);
break;
case 7:nian++;
if(nian==100)
nian=0;
write_nyr(3,nian);
temp=(nian)/10*16+(nian)%10;
write_1302(0x8e,0x00);
write_1302(0x8c,temp);
write_1302(0x8e,0x80);
write_1602com(yh+4);
break;
}
}
}
//------------------减键 key3,各句功能参照'加键'注释---------------
if(key3==0)
{
delay(10);
//调延时,消抖动
if(key3==0)
{
delay(20);
while(!key3);
switch(key1n)
{
case 1:miao--;
if(miao==-1)
miao=59;
write_sfm(0x0D,miao);
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,temp);
write_1302(0x8e,0x80);
write_1602com(er+0x0E);
break;
case 2:fen--;
if(fen==-1)
fen=59;
write_sfm(10,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+11);
break;
case 3:shi--;
if(shi==-1)
shi=23;
write_sfm(7,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
break;
case 4:week--;
if(week==0)
week=7;
write_1602com(yh+0x0C);
write_week(week);
temp=(week)/10*16+(week)%10;
write_1302(0x8e,0x00);
write_1302(0x8a,temp);
write_1302(0x8e,0x80);
write_1602com(yh+0x0e);
break;
case 5:ri--;
if(ri==0)
ri=31;
write_nyr(9,ri);
temp=(ri)/10*16+(ri)%10;//十进制转换成 DS1302 要求的 DCB 码
write_1302(0x8e,0x00);//允许写,禁止写保护
write_1302(0x86,temp);//向 DS1302 内写日期寄存器 86H 写入调整后的日期数据 BCD 码
write_1302(0x8e,0x80);//打开写保护
write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 6:yue--;
if(yue==0)
yue=12;
write_nyr(6,yue);
temp=(yue)/10*16+(yue)%10; //十进制转换成 DS1302 要求的 DCB 码
write_1302(0x8e,0x00); //允许写,禁止写保护
write_1302(0x88,temp); //向 DS1302 内写月份寄存器 88H 写入调整后的月份数据 BCD 码
write_1302(0x8e,0x80); //打开写保护
write_1602com(yh+7); //因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
case 7:nian--;
if(nian==-1)
nian=99;
write_nyr(3,nian);
temp=(nian)/10*16+(nian)%10; //十进制转换成 DS1302 要求的 DCB 码
write_1302(0x8e,0x00); //允许写,禁止写保护
write_1302(0x8c,temp); //向 DS1302 内写年份寄存器 8cH 写入调整后的年份数据 BCD 码
write_1302(0x8e,0x80); //打开写保护
write_1602com(yh+4); //因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位
break;
}
}
}
}
}
void init()
//定时器、计数器设置函数
{
TMOD=0x11;
//指定定时/计数器的工作方式为 3
TH0=0;
//定时器 T0 的高四位=0
TL0=0;
//定时器 T0 的低四位=0
EA=1;
//系统允许有开放的中断
ET0=1;
//允许 T0 中断
TR0=1;
//开启中断,启动定时器
}
//*******************主函数**************************
void main()
{
lcd_init(); //调用液晶屏初始化子函数
ds1302_init(); //调用 DS1302 时钟的初始化子函数
init(); //调用定时计数器的设置子函数
delay(80);
while(1)
//无限循环下面的语句:
{
keyscan();
//调用键盘扫描子函数
}
}
void timer0() interrupt 1 //取得并显示日历和时间
{ //读取秒时分周日月年七个数据(DS1302 的读寄存器与写寄存器不一样)
miao = BCD_Decimal(read_1302(0x81));
fen = BCD_Decimal(read_1302(0x83));
shi = BCD_Decimal(read_1302(0x85));
ri = BCD_Decimal(read_1302(0x87));
yue = BCD_Decimal(read_1302(0x89));
nian=BCD_Decimal(read_1302(0x8d));
week=BCD_Decimal(read_1302(0x8b));
//显示秒、时、分数据:
write_sfm(13,miao); //秒,从第二行第 8 个字后开始显示(调用时分秒显示子函数)
write_sfm(10,fen); //分,从第二行第 5 个字符后开始显示
write_sfm(7,shi); //小时,从第二行第 2 个字符后开始显示
//显示日、月、年数据:
write_nyr(9,ri); //日期,从第二行第 9 个字符后开始显示
write_nyr(6,yue); //月份,从第二行第 6 个字符后开始显示
write_nyr(3,nian); //年,从第二行第 3 个字符后开始显示
write_week(week);
}
单片机显示冒号的介绍就聊到这里吧,感谢您花时间阅读,谢谢。
本文标签:单片机显示冒号