完整的设计文档下载:
基于STC12C5A60S2系列单片机万年历时钟.doc
(4.54 MB, 下载次数: 26)
- /**************************************************/
- /*基于STC12C5A60S2系列单片机+595驱动五个数码管+165按键输入
- +1302实时时钟+18B20温度传感器的万年历时钟
- 功能键:0xfe:实现温度,时间,年月日,周的转换显示
- 0xdf:实现每按一次可以一次更改小时,分,年,月,日,周的闪烁,而
- 实现加减按键对其改变数值
- 0xfb:加功能键,在0xdf有效的情况下才能生效
- 0xfd:减功能键,在0xdf有效的情况下才能生效
- 数码管亮度有点不一致,还希望高手能帮忙解决,其他功能都是正常的,也可以给各位爱好单片机的新人们一个互相交流的一段小程序,后面付有图片
- */
- #include < 12C5A60S2.h > //头文件
- #include < intrins.h >
- #define uchar unsigned char //宏定义
- #define uint unsigned int
- uchar time_tuf[]={0x14,0x04,0x10,0x12,0x30,0x00,0x5}; //年月日时分秒周
- uchar code weima[]={0x20,0x10,0x08,0x04,0x02,0x01}; //数码管位选
- uchar code duan_ma[]={0xee,0x88,0xd6,0xdc,0xb8,0x7c,0x7e,0xc8,0xfe,0xfc}; //数码管段选信号
- uchar sec,min,hour,day,month,year,week,num,flag,flag1,flag2,flag3,Flicker,di,x,h;
- //时间变量及标志位变量
- uint tt,tvalue; //变量
- void yueri_work(void); //月日显示程序
- void nian_work(void); //年显示程序
- void Show_pass(uchar dss); //不显示程序
- void zhou_work(void); //周显示程序
- void delay_18B20(uint i); //温度延时显示程序
- void wendu_work(void); //温度显示程序
- void show_work(void); //显示程序
- void KEY(void); //按键显示程序
- sbit RCLK=P0^2; //595输出存储器锁存时钟线 /165装载移位控制锁存信号
- sbit SRCLK=P0^0; //595数据输入时钟线
- sbit SER=P0^3; //595数据线
- sbit SO=P0^4; //165数据输出数据线
- sbit CLK=P0^1; //165时钟信号
- sbit RST=P0^5; //1302复位引脚,高电平有效
- sbit IO=P0^6; //1302数据输入输出引脚
- sbit SCL=P0^7; //1302串行时钟输入,控制数据线的输入输出
- sbit DQ=P1^0; //18B20数字温度传感器,输入输出口
- void Delayms(uint z) //1毫秒 1T时钟模式下
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=848;y>0;y--);
- }
- /********************595驱动程序*********************/
- void wr595(uchar date) //595写入一个字节
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- SRCLK=1;
- SER=date&0x80;
- date<<=1;
- SRCLK=0;
- }
- }
- void send2baty(uchar date1,uchar date2) //写入双字节程序
- {
- wr595(date1);
- wr595(date2);
- }
- void out595(void) //595输出锁存程序
- {
- RCLK=0;
- RCLK=1;
- }
- /****************************************************/
- /**************165移位寄存器并转串驱动***************/
- uchar series_165()
- {
- uchar i;
- uchar BYTE=1; //最终接收到得字符
- RCLK=0; //将165外部端口数据装入内部寄存器
- RCLK=1; //抬高为移位准备
- for(i=0;i<8;i++)
- {
- BYTE<<=1; // 1
- CLK=1; //时钟低
- BYTE=BYTE|SO; //先接收高位
- CLK=0; //时钟高,上升沿下一个数据移出
- // 5
- }
- return BYTE; //返回接收字符
- }
- /****************************************************/
- /***************18B20数字传感器驱动程序**************/
- void delay_18B20(uint i) //延时1微秒
- {
- i=i*12; //由于我用的是1T 51单片机 如果用普通51请 把这句话屏蔽
- while(i--);
- }
- void ds1820rst(void) //ds1820初始化
- {
- uchar x=0;
- DQ = 1; //DQ复位
- delay_18B20(4); //延时
- DQ = 0; //DQ拉低
- delay_18B20(100); //精确延时大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd(void) //读数据
- {
- uchar i=0;
- uchar dat = 0;
- for(i=8;i>0;i--)
- {
- DQ = 0; //给脉冲信号
- dat>>=1;
- DQ = 1; //给脉冲信号
- if(DQ) //如果DQ==1,执行下面语句
- {
- dat|=0x80;
- }
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata) //写数据
- {
- uchar i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01;
- delay_18B20(10);
- DQ = 1;
- wdata>>=1;
- }
- }
- read_temp(void) //读取温度值并转换
- {
- uchar a,b;
- ds1820rst();
- ds1820wr(0xcc); //跳过读序列号
- ds1820wr(0x44); //启动温度转换
- ds1820rst();
- ds1820wr(0xcc); //跳过读序列号
- ds1820wr(0xbe); //读取温度
- a=ds1820rd();
- b=ds1820rd();
- tvalue=b*16+a/16; //转换为十进制数
-
- return tvalue;
- }
- /****************1302实时时钟驱动程序****************/
- void write_baty(uchar dat) //1302写入一个字节
- {
- uchar i;
- SCL=0;
- for(i=0;i<8;i++)
- {
- IO=dat&0x01; //先写入低位
- SCL=1;
- SCL=0;
- dat>>=1;
- }
- }
- void write_addbaty(uchar address,uchar dat) //向1302地址写入一个字节的数据
- {
- RST=0;
- SCL=0;
- RST=1;
- write_baty(address);
- write_baty(dat);
- SCL=1;
- RST=0;
- }
- uchar read_baty(void) //1302读取一个字节
- {
- uchar i,temp;
- for(i=0;i<8;i++)
- {
- temp>>=1;
- if(IO)
- {
- temp=temp|0x80;
- }
- else
- {
- temp=temp&0x7f;
- }
- SCL=1;
- SCL=0;
- }
- return temp;
- }
- uchar read_adddaty(uchar address) //向1302地址读取一个字节的数据
- {
- uchar temp;
- RST=0;
- SCL=0;
- RST=1;
- write_baty(address);
- temp=read_baty();
- SCL=1;
- RST=0;
- return temp;
- }
- void Init_1302time(void) //1302初始化
- {
- write_addbaty(0x8e,0x00);
- write_addbaty(0x80,time_tuf[5]);
- write_addbaty(0x82,time_tuf[4]);
- write_addbaty(0x84,time_tuf[3]);
- write_addbaty(0x86,time_tuf[2]);
- write_addbaty(0x88,time_tuf[1]);
- write_addbaty(0x8a,time_tuf[6]);
- write_addbaty(0x8c,time_tuf[0]);
- write_addbaty(0x8e,0x80);
- }
- void read_1302time(void) //读1302时间
- {
- sec=read_adddaty(0x81);
- min=read_adddaty(0x83);
- hour=read_adddaty(0x85);
- day=read_adddaty(0x87);
- month=read_adddaty(0x89);
- week=read_adddaty(0x8b);
- year=read_adddaty(0x8d);
- }
- /****************************************************/
- /********************定时器0程序*********************/
- void Timer0Init(void) //2毫秒@11.0592MHz 1T时钟模式下
- {
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x9A; //设置定时初值
- TH0 = 0xA9; //设置定时初值
- TR0 = 1; //定时器0开始计时
- ET0 = 1; //定时器0中断打开
- EA = 1; //总中断打开
- }
- void timer0() interrupt 1 using 1
- {
- TL0 = 0x9A; //设置定时初值
- TH0 = 0xA9; //设置定时初值
- tt++;
- if(tt==500)
- {
- tt=0;
- x++;
- if(x==10) //20毫秒自动跳会无按键时显示
- {
- x=0;
- di=0;
- }
- }
- if(tt<250)
- {
- Flicker=0;
- }
- else
- {
- Flicker=1;
- }
- }
- /********************时间调整程序********************/
- void set(uchar sel,uchar sal)
- {
- uchar address,time;
- uchar max,min;
- if(sel==7) {address=0x80; max=59;min=0;} //秒
- if(sel==6) {address=0x8a; max=7; min=1;} //星期
- if(sel==2) {address=0x82; max=59;min=0;} //分钟
- if(sel==1) {address=0x84; max=23;min=0;} //小时
- if(sel==5) {address=0x86; max=31;min=1;} //日
- if(sel==4) {address=0x88; max=12;min=1;} //月
- if(sel==3) {address=0x8c; max=99;min=0;} //年
-
- time=read_adddaty(address+1)/16*10+read_adddaty(address+1)%16; //时间BCD转换
- if (sal==0) time++; else time--;
- if(time>max) time=min;
- if(time<min) time=max;
-
- write_addbaty(0x8e,0x00);
- write_addbaty(address,time/10*16+time%10);
- write_addbaty(0x8e,0x80);
- }
- /**********************显示程序**********************/
- void wendu_work(void)
- {
- send2baty(0x10,0x00);
- out595();
- Delayms(2);
- send2baty(0x08,0x00);
- out595();
- Delayms(2);
- if(tvalue/10==0x00)
- {
- Show_pass(0x04);
- }
- else
- {
- send2baty(0x04,duan_ma[tvalue/10]);
- out595();
- Delayms(2);
-
- send2baty(0x02,duan_ma[tvalue%10]);
- out595();
- Delayms(2);
- }
- send2baty(0x01,0x66);
- out595();
- Delayms(2);
- }
- void nian_work(void)
- {
- send2baty(0x10,duan_ma[2]);
- out595();
- Delayms(2);
- send2baty(0x08,duan_ma[0]);
- out595();
- Delayms(2);
- if((Flicker==1)&&(di==3))
- {
- Show_pass(0x04);
- Show_pass(0x02);
- }
- else
- {
- send2baty(0x04,duan_ma[year/16]);
- out595();
- Delayms(2);
- send2baty(0x02,duan_ma[year%16]);
- out595();
- Delayms(2);
- }
- send2baty(0x01,0x10);
- out595();
- Delayms(2);
- }
- void yueri_work(void)
- {
- if((Flicker==1)&&(di==4))
- {
- Show_pass(0x10);
- Show_pass(0x08);
- }
- else
- {
- send2baty(0x10,duan_ma[month/16]);
- out595();
- Delayms(2);
- send2baty(0x08,duan_ma[month%16]);
- out595();
- Delayms(2);
- }
- send2baty(0x04,0x10);
- out595();
- Delayms(2);
- if((Flicker==1)&&(di==5))
- {
- Show_pass(0x02);
- Show_pass(0x01);
- }
- else
- {
- send2baty(0x02,duan_ma[day/16]);
- out595();
- Delayms(2);
- send2baty(0x01,duan_ma[day%16]);
- out595();
- Delayms(2);
- }
- }
- void zhou_work(void)
- {
- send2baty(0x10,0x10);
- out595();
- Delayms(2);
- send2baty(0x08,0x10);
- out595();
- Delayms(2);
- if((Flicker==1)&&(di==6))
- {
- Show_pass(0x04);
- }
- else
- {
- send2baty(0x04,duan_ma[week%16]);
- out595();
- Delayms(2);
- }
- send2baty(0x02,0x10);
- out595();
- Delayms(2);
- send2baty(0x01,0x10);
- out595();
- Delayms(2);
- }
- void show_work(void)
- {
- if((num==0)&&(di==0))
- {
- wendu_work();
- }
- if((num==1)&&(di==0)||(di>=1)&&(di<=2))
- {
- if((Flicker==1)&&(di==1))
- {
- Show_pass(0x10);
- Show_pass(0x08);
- }
- else
- {
- send2baty(0x08,duan_ma[hour%16]);
- out595();
- Delayms(2);
-
- send2baty(0x10,duan_ma[hour/16]);
- out595();
- Delayms(2);
- }
- if((Flicker==1)&&(di==2))
- {
- Show_pass(0x02);
- Show_pass(0x01);
- }
- else
- {
- send2baty(0x02,duan_ma[min/16]);
- out595();
- Delayms(2);
-
- send2baty(0x01,duan_ma[min%16]);
- out595();
- Delayms(2);
- }
-
- send2baty(0x04,0x10);
- out595();
- Delayms(2);
- }
- if((num==2)&&(di==0)||(di==3))
- {
- nian_work();
- }
- if((num==3)&&(di==0)||(di>=4)&&(di<=5))
- {
- yueri_work();
- }
- if((num==4)&&(di==0)||(di==6))
- {
- zhou_work();
- }
- }
- /****************************************************/
- /**********************不显示程序********************/
- void Show_pass(uchar dss)
- {
- send2baty(dss,0x00);
- out595();
- Delayms(1);
- }
- /********************按键处理程序********************/
- void KEY(void)
- {
- uchar key;
- key=series_165();
- if(key==0xdf)
- {
- Delayms(1);
- if(key==0xdf)
- {
- flag1=1;
- }
- }
- else
- {
- if(flag1==1)
- {
- flag1=0;
- di++;
- if(di==7)
- {
- di=0;
- }
- }
- }
- if(di!=0)
- {
- if(key==0xfb)
- {
- Delayms(1);
- if(key==0xfb)
- {
- flag2=1;
- }
- }
- else
- {
- if(flag2==1)
- {
- flag2=0;
- set(di,0);
- }
- }
- if(key==0xfd)
- {
- Delayms(1);
- if(key==0xfd)
- {
- flag3=1;
- }
- }
- else
- {
- if(flag3==1)
- {
- flag3=0;
- set(di,1);
- }
- }
- }
- else
- {
- if(key==0xfe)
- {
- Delayms(1);
- if(key==0xfe)
- {
- flag=1;
- }
- }
- else
- {
- if(flag==1)
- {
- flag=0;
- num++;
- if(num==5)
- {
- num=0;
- }
- }
- }
- }
- }
- /**********************主程序************************/
- void main(void) //主函数
- {
- Timer0Init();
- ds1820rst();
- Init_1302time();
- while(1)
- {
- read_1302time();
- read_temp();
- KEY();
- show_work();
- }
- }
-
-
-
复制代码
|