DS1302时序和C语言程序
DS1302++1602时钟例程C语言版
/////////////////////////////////////////////////////////////*********************1602时钟****************************//***********2010年09月22日10:10至次日00:09做**************/ ////////////////////////////////////////////////////////////#include <reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define SECOND 0x81#define MINUTE 0x83#define HOUR 0x85sbit rs=P2^0;sbit rw=P2^1;sbit ep=P2^2;sbit DS1302_SCLK = P1^0;sbit DS1302_IO= P1^1;sbit DS1302_RST = P1^2;sbit M=P3^2;sbit U=P3^3;sbit D=P3^4;unsigned char sel=0;uchar code DIS1[]={"Centrineer"};uchar code DIS2[]={"QQ:778341220"};/////////////////////////延时////////////////////////////////void delay(uint ms){unsigned int a,b;for(a=0;a<ms;a++)for(b=0;b<120;b++);}/////////////////////////////////////////////////////////////***************DS1302驱动************************/////////////////////////////////////////////////////////////void DS1302_Write(uchar D){uchar i;for(i=0;i<8;i++){DS1302_IO=D&0x01;DS1302_SCLK=1;DS1302_SCLK=0;D=D>>1;}}////////////////////////////////////////////////////////////uchar DS1302_Read(){uchar TempDat=0,i;for(i=0;i<8;i++){TempDat>>=1;if(DS1302_IO) TempDat=TempDat|0x80;DS1302_SCLK=1;DS1302_SCLK=0;}return TempDat;}////////////////////////////////////////////////////////////void WDS1302(uchar ucAddr, uchar ucDat){DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;DS1302_Write(ucAddr);DS1302_Write(ucDat);DS1302_SCLK = 1;DS1302_RST = 0;}////////////////////////////////////////////////////////////uchar RDS1302(uchar ucAddr){uchar ucDat;DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;DS1302_Write(ucAddr);ucDat=DS1302_Read();DS1302_SCLK = 1;DS1302_RST = 0;return ucDat;}//////////////////////////////////////////////////////////void init_1302(){WDS1302(0x8e,0x00);//开保护寄存器WDS1302(0x80,0x55);//秒WDS1302(0x82,0x59);//分WDS1302(0x84,0x23);//时WDS1302(0x8A,0x07);//星期WDS1302(0x86,0x02);//日WDS1302(0x88,0x08);//月WDS1302(0x8C,0x09);//年WDS1302(0x90,0xab);//卷电流充电WDS1302(0x8e,0x80);//关保护寄存器}///////////////////////////////////////////////////////////************************1602驱动************************/ //////////////////////////////////////////////////////////bit lcd_bz(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result = (bit)(P0 & 0x80);ep = 0;return result;}////////////////////////////////////////////////////////void lcd_wcmd(unsigned char cmd){while(lcd_bz());rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep= 0;}/////////////////////////////////////////////////////////void lcd_pos(unsigned char pos){lcd_wcmd(pos | 0x80);}/////////////////////////////////////////////////////////void lcd_wdat(unsigned char dat){while(lcd_bz());rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//////////////////////////////////////////////////////////void lcd_init(){lcd_wcmd(0x38);delay(1);lcd_wcmd(0x0c);delay(1);lcd_wcmd(0x06);delay(1);lcd_wcmd(0x01);delay(1);}//////////////////////////////////////////////////////////*********************调时函数*************************//////////////////////////////////////////////////////////void set_time(){signed char address,item;signed char max,mini;if(M==0){sel++;delay(300);if(sel==6) sel=0;if(sel==2) {address=0x82; max=59;mini=0; }if(sel==1) {address=0x84; max=23;mini=0; }if(sel==3) {address=0x8c; max=99;mini=9;}if(sel==4) {address=0x88; max=12;mini=1; }if(sel==5) {address=0x86; max=31;mini=1; }M=1;}item=((RDS1302(address+1))/16)*10 + (RDS1302(address+1))%16; if(U == 0){delay(200);U=1;item++;}if(D == 0){delay(200);D=1;item--;}if(item>max) item=mini;if(item<mini) item=max;WDS1302(0x8e,0x00);//允许写操作WDS1302(address,(item/10)*16+item%10);WDS1302(0x8e,0x80);//写保护,禁止写操作}//////////////////////////////////////////////////////////*********************显示子函数************************/ /////////////////////////////////////////////////////////uchar lcdshow_u(uchar i,uchar y){lcd_wcmd(0x80+0x00+i);lcd_wdat(y);}uchar lcdshow_d(uchar i,uchar y){lcd_wcmd(0x80+0x40+i);lcd_wdat(y);}//////////////////////////////////////////////////////////*******************显示函数****************************/ /////////////////////////////////////////////////////////void display(void){uchar x,y;x=RDS1302(HOUR);y=x;x=x>>4; lcdshow_u(6,0x30+x);y=y&0x0f; lcdshow_u(7,0x30+y);lcdshow_u(8,':');x=RDS1302(MINUTE);y=x;x=x>>4; lcdshow_u(9,0x30+x);y=y&0x0f; lcdshow_u(0x0a,0x30+y);lcdshow_u(0x0b,':');x=RDS1302(SECOND);y=x;x=x>>4; lcdshow_u(0x0c,0x30+x);y=y&0x0f; lcdshow_u(0x0d,0x30+y);x=RDS1302(0x8d);y=x;x=x>>4; lcdshow_d(8,0x30+x);y=y&0x0f; lcdshow_d(9,0x30+y);lcdshow_d(0x0a,'-');x=RDS1302(0x89);y=x;x=x>>4; lcdshow_d(0x0b,0x30+x);y=y&0x0f; lcdshow_d(0x0c,0x30+y);lcdshow_d(0x0d,'-');x=RDS1302(0x87);y=x;x=x>>4; lcdshow_d(0x0e,0x30+x);y=y&0x0f; lcdshow_d(0x0f,0x30+y);for(x=45;x>0;x--){set_time();delay(10);}}/////////////////////////////////////////////////////////////////**************************主函数******************************/ ////////////////////////////////////////////////////////////////void main(){uchar i;lcd_init();delay(10);lcd_pos(0x03);i = 0;while(DIS1[i] != '\0'){lcd_wdat(DIS1[i]);i++;}lcd_pos(0x42);i = 0;while(DIS2[i] != '\0'){lcd_wdat(DIS2[i]);i++;}//init_1302();delay(1000);for(i=0;i<17;i++){lcdshow_u(i,'>');delay(90) ;}for(i=0;i<17;i++){lcdshow_d(i,'>');delay(90) ;}lcd_init();delay(10);lcdshow_u(0,'T');lcdshow_u(1,'i');lcdshow_u(2,'m');lcdshow_u(3,'e');lcdshow_d(0,'D');lcdshow_d(1,'a');lcdshow_d(2,'t');lcdshow_d(3,'a');lcdshow_d(6,'2');lcdshow_d(7,'0'); //LCD框架描绘while(1){set_time();if(sel==2) {lcdshow_u(9,' ');lcdshow_u(0x0a,' ');delay(500); }if(sel==1) {lcdshow_u(6,' ');lcdshow_u(7,' ');delay(500); }if(sel==4) {lcdshow_d(0x0b,' ');lcdshow_d(0x0c,' ');delay(500); }if(sel==5) {lcdshow_d(0x0e,' ');lcdshow_d(0x0f,' ');delay(500); } //调时LCD闪烁显示display();}}。
DS1302时钟芯片 C语言程序设计
unsigned char i,tmp; time_buf[1]=ds1302_read_byte(ds1302_year_add); //年 time_buf[2]=ds1302_read_byte(ds1302_month_add); //月 time_buf[3]=ds1302_read_byte(ds1302_date_add); //日 time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时 time_buf[5]=ds1302_read_byte(ds1302_min_add); //分 time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒 time_buf[7]=ds1302_read_byte(ds1302_day_add); //周 for(i=0;i<8;i++){ //BCD处理 tmp=time_buf[i]/16; time_buf1[i]=time_buf[i]%16; time_buf1[i]=time_buf1[i]+tmp*10; } } /*DS302初始化函数*/ void ds1302_init(void) { RST_CLR; /*RST脚置低*/ SCK_CLR; /*SCK脚置低*/ }
} else { temp &= 0x7F; } SCK_SET; SCK_CLR; } RST_CLR; /*停止DS1302总线*/ return temp; } /*向DS302写入时钟数据*/ void ds1302_write_time(void) { unsigned char i,tmp; for(i=0;i<8;i++){ //BCD处理 tmp=time_buf1[i]/10; time_buf[i]=time_buf1[i]%10; time_buf[i]=time_buf[i]+tmp*16; } ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护 ds1302_write_byte(ds1302_sec_add,0x80); //暂停 ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电 ds1302_write_byte(ds1302_year_add,time_buf[1]); //年 ds1302_write_byte(ds1302_month_add,time_buf[2]); //月 ds1302_write_byte(ds1302_date_add,time_buf[3]); //日 ds1302_write_byte(ds1302_day_add,time_buf[7]); //周 ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时 ds1302_write_byte(ds1302_min_add,time_buf[5]); //分 ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒 ds1302_write_byte(ds1302_day_add,time_buf[7]); //周 ds1302_write_byte(ds1302_control_add,0x80); //打开写保护 } /*从DS302读出时钟数据*/ void ds1302_read_time(void) {
DS1302原理及程序说明
DS1302原理及程序说明DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM ,通过简单的串行接口与单片机进行通信。
实时时钟/日历电路提供秒、分、时、日、日期、月、年的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。
DS1302 与单片机之间能简单地采用同步串行的方式进行,DS1302的引脚命名如图1-1所示。
通信仅需用到三根信号线:(1)CE 片选,(2)I/O 数据线,(3)SCLK 串行时钟,DS1302与CPU 的连接如图1-2所示。
时钟/RAM 的读/写数据以一个字节或多字节的字符组方式通信,DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW 。
DS1302具有双电源管脚,用于主电源和备份电源供应Vcc1,为可编程涓流充电电源附加七个字节存储器,它广泛应用于电话传真便携式仪器以及电池供电的仪器仪表等产品领域。
DS1302主要的性能指标如下:实时时钟具有能计算2100 年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力31× 8 位暂存数据存储RAM 串行I/O 口方式,使得管脚数量最少宽范围工作电压2.0~ 5.5V工作电流2.0V 时,小于300nA读/写时钟或RAM 数据时有两种传送方式:单字节传送和多字节传送字符组方式8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配简单3 线接口与TTL 兼容Vcc=5V 。
DS1302的读写模式工作时序如图1-3和图1-4所示。
图1-3 单字节读模式图1-4 单字节写模式注:在多字节模式下,SCLK 发出同步脉冲,CS 须持续保持高电平直到多字节操作结束,图1-1 DS1302引脚图1-2 DS1302与CPU 接口DS1302内部寄存器的地址定义如表1-1所示。
表1-1 寄存器的地址及定义实验说明1. DS1302与51单片机的连接IO ——P2.7:串行数据输入/输出引脚SCLK ——P2.6:串行时钟引脚CE ——P2.4:片选CE2. LCD 与单片机连接;************************************************************************* ; LCD Module LMB1602 与单片机连接:;************************************************************************* ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ;Vss Vdd V o RS R/W E D0 D1 D2 D3 D4 D5 D6 D7 BLA BLK ; 0V +5V 0V P32 P33 P34 ---------------- P1[0..7] ---------------- +5V 0V;*************************************************************************3. LCD 显示功能说明LCD1602显示格式如图1-5所示。
51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)
时钟电路图:*■11PCB板:酱时井務ft是用诵m-pdfMerisi 口叵因Fjr 齐舱 C :s ® 工细理沖缶皿ndm - * TfS ' 4' 包田U i > 'ir ft ZS:MZ fH钟些fl是用说町-Pdf Wirrcf闻礒雜sbit dis_ bitlsbit dis_ bit2sbit dis_ bit3sbit dis_ bit4sbit dis_ bit5sbit dis_ bit6sbit ledl _bitsbit led2 ! bit=P2A7; II定义数码管控制口=P2A6; II定义数码管控制口=卩2八4; II定义数码管控制口=卩2八3; II定义数码管控制口=P2A1; II定义数码管控制口=P2A0; II定义数码管控制口=P2A2; II定时LED勺控制口=P2A5; II定时LED勺控制口单片机程序:/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>訂开始 LJ-雲匕®务如1痒3月计ttVl. •呈T』d"吐拠席射■ w耳pg文宇■[豹…SS时軽件思冃说#define uehar #define uint unsigned char unsigned intsbit s1_bit =P1A 0; // 定义S1 控制口 sbit s2_bit =P01; // 定义 S2控制口 sbit s3_bit =P02; // 定义 S3控制口 sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据 sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t);//8US 延时基准程序void delay_50us(ui nt t); //void display1(uchar dis_data); void display2(uchar dis_data); void display3(uchar dis_data); void display4(uchar dis_data); void display5(uchar dis_data); void display6(uchar dis_data);void init_t0(); //定时器0初始化函数 void dis_led(); //LED 处理函数 void judge_s1(); //S1 按键处理函数void judge_s2(); //S2 按键处理函数 void judge_s3(); //S3 按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1); 示子程序 void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchar s1,uchar san); 〃闪烁显示子程序 void judge_dis(); //显示处理函数 void judge_clock(); // 显示处理函数 void set_ds1302(); // 设置时间void get_ds1302();// 读取当前时间void w_1byte_ds1302(uchar t); // 向 DS130写一个字节的数据 uchar r_1byte_ds1302(); // 从DS130读一个字节的数据//DS18B20测温函数定义延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序 //数码管4显示子程序 //数码管5显示子程序 //数码管6显示子程序//显 s2,ucharvoid w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};// 上电时默认的时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TRO =1;//// set_ds1302();〃设置DS1302勺初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timerO() interrupt 1{TH0=(65536-50000)/256;TL0=(65536 - 50000)%256; t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒{ _msec on d_co unt =0;sec on d_flag =1;}}}//**************************************************//显示处理函数void judge_dis(){if (flag1 ==0){if (second_flag ==1){ _zancun7 ++;sec on d_flag =0;} _if (zancun7 <1){if (temp_flag2 ==1){ 一readtemp_ds18b20(); // 读取温度temp_flag2 =0;厂dis_temp(); //温度显示函数}if (zancun7 >=1){temp_flag2 =1;zancun4 =hour_count &0xf0;zancun4 >>=4;zancun5 =minute_count&0xf0;zancun5 >>=4;zancun6 =sec on d_co unt&0xf0;zancun6 >>=4;dis(za ncun4 ,hour_co unt &0x0f,za ncun5,minu te_co unt &0x0f,za ncun 6,sec ond_ cou nt &0x0f);dis_led();if (zancun7 ==5)zancun7 =0;}}if (flag1 !=0){switch (flag1){case 1:dis(5,10,11,1,12,12); // 显示SET1led1_bit =1;led2_bit =1;break;case 2:dis(5,10,11,2,12,12); // 显示SET2break;case 3:dis(5,10,11,3,12,12); // 显示SET3break;case 4:dis(5,10,11,4,12,12); // 显示SET4break;case 5:dis(5,10,11,5,12,12); // 显示SET5break;case 6:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,1); break;case 7:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,2); break;case 8:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,3); break;case 9: //进入修改时间,时间分位个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,4); break;case 10: //进入修改闹钟,闹钟小时十位闪烁dis_san(zancunl / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,zancun3,1); break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,12,zancun3,2); break;case 12: //进入修改闹钟,闹钟小时十位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,3);break;case 13: //进入修改闹钟,闹钟小时个位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,4);break;case 14: //进入修改闹钟的开关dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,6);break;case 15:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,1);break;case 16:dis_san(zancun1 / 10,zancunl %10,zancun2/10,zancun2%0,zancun3/ 10,zancun3%10,2);break;case 17:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,zancun3/ 10,zancun 3%10,3);break;case 18:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,4);break;case 19:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,5);break;case 20:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,6);break;case 21:if (second_flag ==1){ _sec on d_flag =0;countdown_second --;if (countdown_second ==255){ _coun tdow n_sec ond =59;countdown_minute --;if (countdown_minute ==255){ _coun tdow n_min ute =59;countdown_hour --;if (countdown_hour ==255){flag1 =22;coun tdow n_min ute =0;coun tdow n_hour =0;coun tdow n_sec ond =0;coun tdow n_flag=1;_ } } } }dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 22:{ speak =1;}dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 23: dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break; case 24:if (msecond_flag ==1) { _msec on d_flag =0; msec on d_msec ond ++;if (msecond_msecon (==10){msec on d_msec ond =0; msec on d_sec ond ++;if (msecond_second==60) { _msecond_second =0; msec ond_minute ++;if (countdown_flag { _speak=0;if (second_flag { _sec on d_flag coun tdow n_flag} _ } else>0 &&countdown_flag <7)==1) =0; ++;if (msecond_minute==1OO) { _msec ond_minute =99;flagl =23;}}}}dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break;case 25:dis(zancun3 / 10,zancun3 %0,zancun2 / 10,zancun2 %10,zancun1 /10,zancun1 %0 );break;default :break;}}}//**************************************************〃S1按键处理函数void judge_s1(){ _s1_bit =1;//置IO为1,准备读入收据if (s1_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s1_bit ==0){switch (flag1){case 0:case 1:case 2:case 3:case 4:case 6:case 7:case 8:case 10:case 11:case 12:case 13:case 15:case 16:case 17:case 18:case 19: flag1++;break;case 9: flag1=6;break;case 14: flag1=10;break;case 20: flag1=15;break;case 5:case 21:case 22:case 23: //系统从秒表状态复位case 24: //系统从秒表状态复位case 25: //系统从计数器复位flag1 =0;break;default :break;}while (s1_bit ==0){ _judge_dis();}〃等待按键释放}}}〃************************************************** 〃S2按键处理函数void judge_s2(){ _s2_bit =1; //置IO为1,准备读入收据if (s2_bit ==0)//判断是否有按键按下=0;{delay_50us(1); //延时,去除机械抖动 if (s2_bit ==0) { switch (flagl) { flag1 =6; zancun4 =hour_count &0xf0;zancun4 >>=4; zancun6 =hour_count &0x0f;zancun1=zancun4*10+zancun6; //zancun 1=hour_co unt; zancun5 =minute_count &0xf0; zancun5 >>=4; zancun6 =minute_count &0x0f; zancun2 =za ncun5* 10+za ncun6; case 1: //在显示SET 状态下按S2牛,进入修改时间 // zancun2=minu te_co unt; break; case 2: //在显示SET2犬态下按S2,进入设置闹钟 zancunl =clock_hour; zancun2 =clock_m inu te; flagl =10; break; case 6: //修改时钟小时十位状态下按 case 7: //修改时钟小时个位状态下按 case 8: //修改时钟分钟十位状态下按 case 9: //修改时钟分钟个位状态下按 〃zancun4=za ncun 1/10; 测S:SM tab23[2] =zancun1/10* 16+za ncu n1%10; tab23[1] hour_c ount minu te_c ount sec ond_co unt tab23[0]set_ds1302(); flag1//zancun 5=za ncun2&0 xf0; //zancun 5>>=4; =zancun2/10* 16+za ncu n2%10; =tab23[2]; =tab23[1]; =0; //设置DS130的初始时间 =0;break; case 10: //修改闹钟小时十位状态下按S2case 11: //修改闹钟小时个位状态下按S2case 12: //修改闹钟分钟十位状态下按S2 case 13: //修改闹钟分钟个位状态下按S2 case 14: //修改闹钟使能状态下按S2clock_hour clock_m inute clock_e n flag1=zancun1; =zancun2; =zancun3;=0;break;case 3:flagl =15;zancunl =co un tdow n_hour;zancun2 =co un tdow n_minu te;zancun3 =co un tdow n_sec ond;break;case 15:case 16:case 17:case 18:case 19:case 20:coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flag1 =21;coun tdow n_flag =0;break;case 22:flag1 =21;break;case 21:flag1 =22;break;case 4:flag1 =23; //秒表暂停msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 23:flag1 =24;break;case 24:flag1 =23;break;case 5:flagl =25;//进入计数器模式zancunl =0;zancun2 =0;zancun3 =0;break; default :break;}while (s2_bit ==0){ _judge_dis();}//等待按键释放}}}//**************************************************//S3按键处理函数void judge_s3(){ _s3_bit =1;//置IO为1,准备读入收据if (s3_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s3_bit ==0){ _switch (flag1){case 6: //修改时间小时的十位数zancun1 +=10;if (zancun1 >=24)zancun1 =zancun 1%10;break;case 7: //修改时间小时的个位数za ncun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 8: //修改时间分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60;break;case 9: //修改时间分钟的个位数za ncun2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 10: //修改闹钟小时的十位数zancunl +=10;if (zancunl >=24)zancunl =zancun 1%10; break;case 11: //修改闹钟小时的个位数zancunl =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 12: //修改闹钟分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 13: //修改闹钟分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 14:zancun3 A=1;break;case 15: //修改倒计时小时的十位数zancun1 +=10;if (zancun1 >=100)zancun 1 -=100; break;case 16: //修改倒计时小时的个位数zancun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;break;case 17: //修改倒计时分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 18: //修改倒计时分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 19: //修改倒计时秒的十位数zancun3 +=10;if (zancun3 >=60)zancun3-=60; break;case 20: //修改倒计时秒的个位数zan cu n3 =za ncun3/10* 10+(za ncun3 %10+1) %10;break;case 21:case 22: //coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flagl =21;break;case 23:case 24: //秒表复位flag1 =24;msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 25:zancun1 ++;if (zancun1 ==100){zancun1 =0;zancun2 ++;if (zancun2 ==100){zancun2 =0;zancun3 ++;}}break;default : break;}while (s3_bit ==0){ _judge_dis();}〃等待按键释放}}} //显示处理函数void judge_clock() {zancun4 =hour_count &0xf0;zancun4 >>=4;zancun6 =hour_count &0x0f;zancun4 *=10;zancun4 +=za ncun6;zancun5=minute_count &0xf0;if (san ==1){zancun5 >>=4;zancun6 =minute_count &0x0f;zancun5 *=10;zancun5 +=za ncun6;if (msecond_count<=5) {speak =0; speak_co unt ++;}else{speak =1;}}else{speak =1;}}〃****************************************////闪烁显示子程序void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchars1,uchar san){if (clock_hour ==zancun4 &&clock_minute ==zancun5){ 一 一if (clock_en { _ speak_co unt clock_flag speak_co unt} _ } else{clock_flag =0;} _if{ (clock_flag ==1 ==1&&clock_flag ==0)=0; //开启蜂鸣器=1;=0;&&speak_count <400)s2,ucharif (msecond_count<5) { _ display1(s6);}}else{display1(s6);}if (san ==2){if (msecond_count<5) { _ display2(s5);}}else{display2(s5);}if (san ==3){if (msecond_count<5) { _ display3(s4);}}else{display3(s4);}if (san ==4){if (msecond_count<5) { _ display4(s3);}}else{display4(s3);}if (san ==5){if (msecond_count<5){ _ display5(s2);}}else{display5(s2);}if (san ==6){if (msecond_count<5){ _ display6(s1);}}else{ display6(s1);}}〃****************************************//时钟显示程序void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1) { display1(s6);display2(s5);display3(s4);display4(s3);display5(s2);display6(s1);}〃********************************************************************************************void init_tO(){ _TMOD0x01;〃设定定时器工作方式1,定时器定时50毫秒TH0=(65536-50000)/256;TL0=(65536- 50000)%256;EA=1; //开总中断ET0=1; //允许定时器0中断t0_crycle =0; //定时器中断次数计数单元}//LED处理函数void dis_led(){if (msecond_count<5){ _Ied1_bit =1;Ied2_bit =1;}else{led1_bit =0;led2_bit =0;}}〃***************************************************************//功能:把数据1显示在数码管1上void display6(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit6 =0; // 锁存数据delay_50us(40); dis_bit6 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display5(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit5 =0; // 锁存数据delay_50us(40);dis_bit5 =1;} _〃***************************************************************//功能:把数据1显示在数码管1上void display4(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit4 =0; // 锁存数据delay_50us(40);dis_bit4 =1;} 〃***************************************************************//功能:把数据1显示在数码管1上void display3(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit3 =0; // 锁存数据delay_50us(40);dis_bit3 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display1(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit1 =0; // 锁存数据delay_50us(40);dis_bit1 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display2(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit2 =0; // 锁存数据delay_50us(40);dis_bit2 =1;}〃******************************************************************* *******************************// 函数名称:void delay_50US(unsigned int t)//功能:延时50*t(us)void delay_50us(uint t){ _unsigned char j;for (;t >0;t --){for (j =19;j >0;j --);}}〃******************************************************************* ************〃8微秒延时基准程序void delay_8us(uint t){while (-- t);}************〃3微秒延时程序void delay_3us() {}〃******************************************************************* ************//子程序功能:向DS18B2写一字节的数据void w_1byte_ds18b20(uchar value){uchar i =0;for (i =0;i <8;i ++){dq_ds18b20 =1;delay_3us();dq_ds18b20 =0; delay_8us(2);if ( value & 0x01) dq_ds18b20 =1; 〃DQ = 1 delay_50us(1); // 延时50us 以上delay_8us(2);value >>=1;}dq_ds18b20 =1; //DQ = 1}//读一个字节uchar r_1byte_ds18b20( void){ 一一uchar i =0;uchar value = 0;for (i =0;i <8;i ++){value >>=1;dq_ds18b20 =0;// DQ_L;delay_3us();dq_ds18b20 =1; 〃DQ_H;delay_8us(2);if (dq_ds18b20==1) value |= 0x80;delay_8us(6); // 延时40us}dq_ds18b20 =1;return value ;}11 ・**************************************************〃ds18b20复位子程序void rest_ds18b20( void){rest:delay_3us(); // 稍做延时delay_3us();dq_ds18b20 =1;delay_3us();dq_ds18b20 =0;// DQ_L; delay_50us(11); 〃480us<T<960usdq_ds18b20 =1; // 拉高总线delay_8us(5);if (dq_ds18b20==1){return ;}delay_50us(2); // 延时90usif (dq_ds18b20==1){return ;}else{goto rest;}}〃****************************************************//读取温度void readtemp_ds18b20( void){ _uchar temp32;rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0x44); // 启动温度转换delay_8us(2);rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0xbe); //读取温度寄存器等(共可读9个寄存器)前两个就是温度templ =r_1byte_ds18b20();temph =r_1byte_ds18b20();if ((temph &0xf0)) //判断温度的正负性{temp_flag =0; //温度为负数标志temph =-temph;tempi =-templ;t_x =tabl3[templ & OxOf]; // 计算温度的小数temp32 =temph & OxOf;temp32 <<=4;tempi >>=4;temp32 =temp32 | tempi;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据5else //为正数{t_x =tabl3[templ & 0x0f]; // 计算温度的小数temp32 =temph & 0x0f;temp32 <<=4;templ >>=4;temp32 =temp32 | templ;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据temp_flag =1;} _}void dis_temp() //温度显示函数{ _if (temp_flag =1){ _if (t_b ==0){dis(12,12,t_s,t_g,13,12);}else{dis(12,t_b,t_s,t_g,13,12);}}else{dis(14,t_b,t_s,t_g,13,12);}}/ / """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ############ //;子程序名:w_1byte_ds1302//;功能:向DS130写一个字节的数据void w_1byte_ds1302(uchar t){uchar i;for (i =0;i <8;i ++){if (t & 0x01){io_ds1302=1;}else{io_ds1302 =0;}clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();delay_3us();t >>=1;}}/ / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ######//;子程序名:r_1byte_ds1302()//;功能:从DS130读一个字节的数据uchar r_1byte_ds1302(){ 一一uchar i,temp11 =0;io_ds1302 =1;//置10为1,准备读入数据for (i =0;i <8;i ++){temp11 >>=1;if (io_ds1302) temp11 |= 0x80;clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();}return (temp11);}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/ / , JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ """""""""""""""ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff//;子程序名:setbds1302//;功能:设置DS130初始时间,并启动计时void set_ds1302(){uchar i,j;rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); // 写控制命令字delay_3us();w_1byte_ds1302(0x00); // 写保护关闭clk_ds1302 =1;delay_3us();for (i =0,j =0x80;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(j);delay_3us();w_1byte_ds1302(tab23[i]);delay_3us();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();delay_3us();} _rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); delay_3us();w_1byte_ds1302(0x80); clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff //;子程序名:get1302void get_ds1302(){ _uchar temp11[7],i,j;for (i =0;i <7;i ++){temp11[i] =0;}for (i =0,j =0x81;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();delay_3us();w_1byte_ds1302(j);temp11[i] =r_1byte_ds1302();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();} _if (temp11[0] != 0xff){second_count =temp11[0]; }if (temp11[1] != 0xff) // 数据验证{minute_count =temp11[1]; }if (temp11[2] != 0xff) // 数据验证{hour_count =temp11[2]; }// date=temp[3];//mon th=temp[4];// week=temp[5];//year=temp[6];}/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>sbit dis_bit1 =P2A 7; //定义数码管控制口sbit dis_bit2 =卩2八6;//定义数码管控制口sbit dis_bit3 =卩2八4;//定义数码管控制口sbit dis_bit4 =卩2八3;//定义数码管控制口sbit dis_bit5 =卩2八1; //定义数码管控制口sbit dis_bit6 =P2A0; //定义数码管控制口sbit led1_bit =卩2八2; // 定时 LED 勺控制口sbit led2_bit =卩2八5; // 定时 LED 勺控制口sbit s1_bit =P1A0; // 定义S1 控制口sbit s2_bit =P01; // 定义 S2空制口sbit s3_bit =P02; // 定义 S3控制口sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口 void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t); //8US 延时基准程序void delay_50us(ui nt t); // void display1(uehardis_data); voiddisplay2(uehar dis_data); void display3(uehar dis_data); void display4(uehar dis_data); void display5(uehar dis_data); void display6(uehar dis_data);void init_t0(); //定时器0初始化函数void dis_led(); //LED 处理函数void judge_s1();//S1 按键处理函数 void judge_s2(); //S2 按键处理函数void judge_s3(); //S3 按键处理函数 void dis(uehar s6,uehar s5,uehar s4,uehar s3,uehar s2,uehar s1); 示子程序 void dis_sa n( uchar s6,uehar s5,uehar s4,uehar s3,uehars1,uchar san); 〃闪烁显示子程序void judge_dis(); //显示处理函数void judge_clock(); // 显示处理函数void set_ds1302(); // 设置时间void get_ds1302(); // 读取当前时间#define uehar#define uintunsigned char unsigned int延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序//数码管4显示子程序//数码管5显示子程序//数码管6显示子程序 //显s2,ueharvoid w_1byte_ds1302(uchar t); // 向DS130写一个字节的数据uchar r_1byte_ds1302(); // 从DS130读一个字节的数据〃*******************************************************************//DS18B20测温函数定义void w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位上电时默认的uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};//时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TR0 =1;//// set_ds1302();〃设置DS130的初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536- 50000)%256;t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒。
DS1302八位共阳数码管C语言可调时钟程序
#define DS1302_IO_HIGH io_DS1302_IO = 1 ;
#define DS1302_IO_LOW io_DS1302_IO = 0 ;
sbit key1=P3^1;
sbit key2=P3^2;
sbit key3=P3^3;
sbit key4=P3^4;
int main_flag=0,exit_flag,up_flag,down_flag;
int tab[]={0,0,0,0,0,0};
uchar tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
}
}
break;
case KEY_STATE_UP:
if(keyTemp==KEY_NULL)
{
s_keyState=KEY_STATE_INIT;
}
else
{
if(++keyTime>=KEY_CONTINUE_PERIOD)
uchar table1[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0x80,0x90,0xbf,0xbf};
#define KEY_1 0x0e
#define KEY_2 0x0d
#define KEY_3 0x0b
#define KEY_4 0x07
if(count==500)
{
count=0;
dao1S=1;
}
}
//-------------------------------------常数宏---------------------------------//
ds1302时钟程序详解-ds1302程序流程图(C程序)
ds1302时钟程序详解,ds1302程序流程图(C程序)ds1302时钟程序详解DS1302 的控制字如图2所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
2.3 数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
2.4 DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
ds1302程序流程图3.2 DS1302实时时间流程图4示出DS1302的实时时间流程。
根据此流程框图,不难采集实时时间。
下面结合流程图对DS1302的基本操作进行编程:根据本人在调试中遇到的问题,特作如下说明: DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位LSB(D 0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出)。
ds1302c程序
花了两天的时间,才用C把1302做成时钟!在做的过程中,最主要的就是1302的读和写!所以现在把读写子程序拿出来和大家共享!程序不一定是最优化的,但是保证能用,因为我已经用过,效果蛮好的!所以希望那位朋友能够更优化一下程序的!请赐教!谢谢!我的硬件是这样的:P0口给四个共阴的数码管送数据!P2口用NPN的三极管驱动数码管共阴极。
1302的接口如下定义。
sbit clk=p1^2;sbit I_O=p1^3;sbit rst=p1^4;void reset1302(void) //$$$//1302初始化,写入秒,分,时,日,月,星期,年的数据{rst=0;clk=0;rst=1;write1302(0x8e);write1302(0);clk=1;rst=0;writedata(0x80,second);writedata(0x82,minute);writedata(0x84,hour);writedata(0x86,day);writedata(0x88,month);writedata(0x8a,week);writedata(0x8c,year);rst=0;clk=0;rst=1;write1302(0x8e);write1302(0x80);clk=1;rst=0;}void writedata(uchar wdataaddr,uchar waddr)//写入数据$$${rst=0;clk=0;rst=1;write1302(wdataaddr);write1302(waddr);clk=1;rst=0;}uchar readdata(uchar rdataaddr)//1302读出数据子程序$$$//rdataaddr为1302数据的读地址,如81H{rst=0;clk=0;rst=1;write1302(rdataaddr);I_O=1;read1302();clk=1;rst=0;return(rdata);}void read1302(void)//向1302读出1 个字节的数据$$${uchar ri;rdata=0;clk=0;for(ri=0;ri<8;ri++){if (I_O==1) rdata=rdata|0x80;clk=1;clk=0;if (ri<7) rdata=rdata>>1;}}void write1302(uchar command1)//向1302写入1 个字节的数据$$$ {uchar wi,sj;sj=command1;clk=0;for(wi=0;wi<8;wi++){// if((sj&0x01)==0x01) cc=1;else cc=0;// I_O=cc;if((sj&0x01)==0x01) I_O=1;else I_O=0;clk=1;clk=0;sj=sj>>1;}}void hex_bin(uchar zhsj)//十六进制转换成十进制$$${led1=zhsj;led1=led1>>4;led2=zhsj;led2=led2&0x0f;}void deplay(uchar led43,uchar led21)//显示子程序$$$ {hex_bin(led43);p0=a[led1];p2=0x08;ds();p0=a[led2];p2=0x04;ds();hex_bin(led21);p0=a[led1];p2=0x02;ds();p0=a[led2];p2=0x01;ds();}。
ds1302时钟程序详解,ds1302程序流程图
ds1302时钟程序详解,ds1302程序流程图(C程序)ds1302时钟程序详解DS1302 的控制字如图2所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见表1。
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。
DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
ds1302程序流程图DS1302实时时间流程图4示出DS1302的实时时间流程。
根据此流程框图,不难采集实时时间。
下面结合流程图对DS1302的基本操作进行编程:根据本人在调试中遇到的问题,特作如下说明:DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位L SB(D0)为逻辑0,指定写操作(输入), D0=1,指定读操作(输出)。
ds1302实时时钟c程序加仿真原理图
#ifndef _1602_yejing_#define _1602_yejing_#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4;sbit lcdrs=P3^5;void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com) {lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void write_lcd(uchar x,char *cha){ uchar length,i=0;write_com(x);for(length=0;cha[length]!=0;length++);for(i=0;i<length;i++){write_data(cha[i]);delay(5);}}void write_bcd(uchar cha){uchar ch1,ch2;ch1=(cha&0x0f)+'0';ch2=((cha>>4)&0x0f)+'0';write_data(ch2);write_data(ch1);}void write_fd(float t)//显示float型函数{ uchar s1,s2,s3,s4;uint tt;tt=t*100;s1=tt/1000;s1+=0x30;s2=tt%1000/100;s2+=0x30;s3=tt%1000%100/10;s3+=0x30;s4=tt%10;s4+=0x30;write_data(s1);write_data(s2);write_data(46);write_data(s3);write_data(s4);}void init(){lcden=0;write_com(0x38);//设置16*2显示write_com(0x0c);//设置开显示,不显示光标write_com(0x06);//写一个字符后地址指针加1write_com(0x01);//显示清0,数据指针清0}#endif/**************************************************************************THE REAL TIMER DS1302 DRIVER LIBCOPYRIGHT (c) 2010 BY ZYK.-- ALL RIGHTS RESERVED --File Name: DS1302.hAuthor: ZHANG YUAN KECreated: 2010/06/21Modified: NORevision: 1.0***************************************************************************/ #ifndef _DS1302_2010_06_21_#define _DS1302_2010_06_21_sbit SCLK = P1^6; //实时时钟时钟线引脚sbit DIO = P1^7; //实时时钟数据线引脚sbit CE = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char sec,min,hour,day,mon,week,year;char *tab[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat",};void write_1302(uchar add,uchar dat){uchar i;ACC=add;CE=0;SCLK=0;CE=1;for(i=0;i<8;i++){DIO=ACC0;SCLK=1;SCLK=0;ACC>>=1;}ACC=dat;for(i=0;i<8;i++){DIO=ACC0;SCLK=1;SCLK=0;ACC>>=1;}CE=0;}uchar read_1302(uchar add){uchar i;ACC=add;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) // 为什么不能for(i=0;i<8;i++) 又为什么用我写的函数不能改时间!!!!!!!!!!!!{DIO=ACC0;SCLK=1;ACC>>=1;SCLK=0;}for(i=8;i>0;i--){ ACC>>=1;ACC7=DIO;SCLK=1;SCLK=0;}return(ACC);CE=0;}void inputbyte(uchar d) //实时时钟写入一字节(内部函数){uchar i;ACC=d;for(i=8;i>0;i--){DIO=ACC0; //相当于汇编中的RRCSCLK=1;SCLK=0;ACC>>=1;}}uchar outputbyte() //实时时钟读取一字节(内部函数){uchar i;for(i=8; i>0; i--){ACC=ACC>>1; //相当于汇编中的RRCACC7=DIO;SCLK=1;SCLK=0;}return(ACC);}void write_1302(uchar add,uchar dat) //ucAddr: DS1302地址, ucData: 要写的数据{CE=0;SCLK=0;CE=1;inputbyte(add); // 地址,命令inputbyte(dat); // 写1Byte数据CE=0;}uchar read_1302(uchar add) //读取DS1302某地址的数据{uchar dat;CE=0;SCLK=0;CE=1;inputbyte(add); // 地址,命令dat=outputbyte(); // 读1Byte数据CE=0;return(dat);}void setprotect(bit flag){if(flag)write_1302(0x8e,0x80);elsewrite_1302(0x8e,0x00);}void gettime_1302(){sec=read_1302(0x81);min=read_1302(0x83);hour=read_1302(0x85);day=read_1302(0x87);mon=read_1302(0x89);week=read_1302(0x8b);year=read_1302(0x8d);}void stop_time(bit flag) // 是否将时钟停止{unsigned char dat;dat=read_1302(0x81);setprotect(0);if(flag)write_1302(0x80, dat|0x80);elsewrite_1302(0x80, dat&0x7F);}void init_1302(){uchar second=read_1302(0x81);if(second&0x80)write_1302(0x80,0);}/****************************************************************************** **void BurstWrite1302(unsigned char *pWClock) //往DS1302写入时钟数据(多字节方式) {unsigned char i;Write1302(0x8e,0x00); // 控制命令,WP=0,写操作?DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbe); // 0xbe:时钟多字节写命令for (i = 8; i>0; i--) //8Byte = 7Byte 时钟数据+ 1Byte 控制{DS1302InputByte(*pWClock); // 写1Byte数据pWClock++;}DS1302_CLK = 1;DS1302_RST = 0;}void BurstRead1302(unsigned char *pRClock) //读取DS1302时钟数据(时钟多字节方式) {unsigned char i;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(0xbf); // 0xbf:时钟多字节读命令for (i=8; i>0; i--){*pRClock = DS1302OutputByte(); // 读1Byte数据pRClock++;}DS1302_CLK = 1;DS1302_RST = 0;}******************************************************************************* */#endif#include "1602.h"#include "DS1302.h"sbit set=P3^2;sbit jia1=P3^0;sbit jian1=P3^1;uchar bcdtoasc(uchar cha){return ((cha/16)*10+(cha%16));}uchar asctobcd(uchar cha){return ((cha/10)*16+(cha%10));}void disp_week(){ switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;}}}void disp_time(){write_com(0x87);write_bcd(year);write_com(0x8a);write_bcd(mon);write_com(0x8d);write_bcd(day);write_com(0xc5);write_bcd(hour);write_com(0xc8);write_bcd(min);write_com(0xcb);write_bcd(sec);disp_week();}void keyscan(){jia1=1;jian1=1;stop_time(1);if(set==0){delay(10);if(set==0) {delay(200); slect++;}if(slect==8) {slect=0; stop_time(0);write_com(0x0c);} }if(slect){switch(slect){ case 1:{write_com(0xcb);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);sec=read_1302(0x81);sec=sec&0x7f;sec=bcdtoasc(sec);sec+=1;if(sec==60)sec=0;sec=asctobcd(sec);write_1302(0x80,sec);write_com(0x0c);write_bcd(sec);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);sec=read_1302(0x81);sec=sec&0x7f;sec=bcdtoasc(sec);sec-=1;if(sec<0)sec=59;sec=asctobcd(sec);write_1302(0x80,sec);write_com(0x0c);write_bcd(sec);}}break;}case 2:{write_com(0xc8);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);min=read_1302(0x83);min=bcdtoasc(min);min+=1;if(min==60)min=0;min=asctobcd(min);write_1302(0x82,min);write_com(0x0c);write_bcd(min);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);min=read_1302(0x83);min=bcdtoasc(min);min-=1;if(min<0)min=59;min=asctobcd(min);write_1302(0x82,min);write_com(0x0c);write_bcd(min);}}break;}case 3:{write_com(0xc5);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);hour=read_1302(0x85);hour=bcdtoasc(hour);hour+=1;if(hour==24)hour=0;hour=asctobcd(hour);write_1302(0x84,hour);write_com(0x0c);write_bcd(hour);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);hour=read_1302(0x85);hour=bcdtoasc(hour);hour-=1;if(hour<0)hour=23;hour=asctobcd(hour);write_1302(0x84,hour);write_com(0x0c);write_bcd(hour);}}break;}case 4:{write_com(0x8d);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);mon=read_1302(0x89);year=read_1302(0x8d);day=read_1302(0x87);day=bcdtoasc(day);day+=1;year=bcdtoasc(year);if(year%4==0){if(mon==2){if(day==29)day=1;}else if(day==30)day=1;}else{ switch(mon){case 1:{if(day==32)day=1;break;}case 2:{if(day==30)day=1;break;}case 3:{if(day==32)day=1;break;}case 4:{if(day==31)day=1;break;}case 5:{if(day==32)day=1;break;}case 6:{if(day==31)day=1;break;}case 7:{if(day==32)day=1;break;}case 8:{if(day==32)day=1;break;}case 9:{if(day==31)day=1;break;}case 0x10:{if(day==32)day=1;break;}case 0x11:{if(day==31)day=1;break;}case 0x12:{if(day==32)day=1;break;}}if(mon==1|mon==3|mon==5|mon==7|mon==8|mon==0x10|mon==0x12) if(day==32)day=0; */if(mon==4|mon==6|mon==9|mon==0x11){if(day==31)day=1;}else if(day==32)day=1;}day=asctobcd(day);write_1302(0x86,day);write_com(0x0c);write_bcd(day);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);day=read_1302(0x87);day=bcdtoasc(day);day-=1;if(day<1){ mon=read_1302(0x89);year=read_1302(0x8d);switch(mon){ case 0x01: {day=31; break;}case 0x02: {day=29; break;}case 3: {day=31; break;}case 4: {day=30; break;}case 5: {day=31; break;}case 6: {day=30; break;}case 7: {day=31; break;}case 8: {day=31; break;}case 9: {day=30; break;}case 0x10: {day=31; break;}case 0x11: {day=30; break;}case 0x12: {day=31; break;}}year=bcdtoasc(year);if(year%4==0)if(mon==2)day=28;}day=asctobcd(day);write_1302(0x86,day);write_com(0x0c);write_bcd(day);}}break;}case 5:{write_com(0x8a);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);mon=read_1302(0x89);mon=bcdtoasc(mon);mon+=1;if(mon==13)mon=1;mon=asctobcd(mon);write_1302(0x88,mon);write_com(0x0c);write_bcd(mon);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);mon=bcdtoasc(mon);mon-=1;if(mon<1)mon=12;mon=asctobcd(mon);write_1302(0x88,mon);write_com(0x0c);write_bcd(mon);}}break;}case 6:{write_com(0x87);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);year=read_1302(0x8d);year=bcdtoasc(year);year+=1;if(year==100)year=0;year=asctobcd(year);write_1302(0x8c,year);write_com(0x0c);write_bcd(year);}}if(jian1==0){delay(10);if(jian1==0){ delay(200);year=read_1302(0x8d);year=bcdtoasc(year);year-=1;if(year<0)year=99;year=asctobcd(year);write_com(0x0c);write_bcd(year);}}break;}case 7:{write_com(0xcd);write_com(0x0d);if(jia1==0){delay(10);if(jia1==0){delay(200);week=read_1302(0x8b);week=bcdtoasc(week);week+=1;if(week==8)week=1;week=asctobcd(week);write_1302(0x8a,week);write_com(0x0c);disp_week();/* switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;}} */}}if(jian1==0){delay(10);if(jian1==0){ delay(200);week=read_1302(0x8b);week=bcdtoasc(week);week-=1;if(week<1)week=7;week=asctobcd(week);write_1302(0x8a,week);write_com(0x0c);disp_week();/* switch(week){case 1:{write_lcd(0xcd,tab[0]); break;}case 2:{write_lcd(0xcd,tab[1]); break;}case 3:{write_lcd(0xcd,tab[2]); break;}case 4:{write_lcd(0xcd,tab[3]); break;}case 5:{write_lcd(0xcd,tab[4]); break;}case 6:{write_lcd(0xcd,tab[5]); break;}case 7:{write_lcd(0xcd,tab[6]); break;} } */}}break; }}}}main(){init();init_1302();write_lcd(0x80,"DATE:20 - -");write_lcd(0x80+0x40,"TIME: : :");while(1){gettime_1302();set=1;if(set==0){delay(10);if(set==0){delay(200);slect++;}}while(slect)keyscan();disp_time();delay(30);}}。
DS1302时钟芯片完整C语言应用程序_可直接调用
}
for(i=0;i<8;i++)
{
DS1302_CLK=0;
DS1302_DATA=DDATA&0X01;
DS1302_CLK=1;
DDATA=DDATA>>1; //传送数据。
}
DS1302_CLK=0;
DS1302_RST=0;
//使能端关闭。
}
/************************************************************/
uchar DS1302_Clock[8]={0x01,0x01,0x00,0x06,0x09,0x02,0x11,0}; //时钟缓存。秒、分、时、
日、月、周、年、控制寄存器。
void DS1302_Write(uchar CDATA,uchar DDATA); //写数据。
uchar DS1302_Read(uchar CDATA); //读数据。
#endif
/********DS1302_WriteClock()***********************************
函数名 :DS1302_WriteClock() 突发方式,写入所有时钟数据。
入口参数:无
出口参数:无
**************************************************************/
void DS1302_Write(uchar CDATA,uchar DDATA)
{
uchar i;
DS1302_RST=1;
//使能端有效,开始传送数据。
for(i=0;i<8;i++)
DS1302时钟芯片51单片机c语言程序
DS1302时钟芯片51单片机c语言程序#ifndef __DS1302_H__#define __DS1302_H__#define uchar unsigned char#define uint unsigned int#includesbit SCLK = P3^2;sbit IO = P2^4;sbit RST = P3^3;#define R_Second 0x81#define W_Second 0x80#define R_Minute 0x83#define W_Minute 0x82#define R_Hour 0x85#define W_Hour 0x84#define R_Day 0x87#define W_Day 0x86#define R_Month 0x89#define W_Month 0x88#define R_Week 0x8B#define W_Week 0x8A#define R_Year 0x8D#define W_Year 0x8C#define R_Control 0x8F#define W_Control 0x8Evoid DS1302_Write_Byte(uchar Date); uchar DS1302_Read_Byte();void Write_DS1302(uchar Adr,uchar Date); uchar Read_DS1302(uchar Adr);void Init_DS1302();#endif#include "ds1302.h"/************************************************************** 函數名稱:DS1302_Write_Byte(uchar Date)函數功能:单字节写輸入參數:写的字节輸出參數:无備注:**************************************************************/ void DS1302_Write_Byte(uchar Date){uchar i;for(i = 0;i < 8;i++){if(Date & 0x01)IO = 1;elseIO = 0;SCLK = 1;Date = Date >> 1;SCLK = 0;}}/************************************************************** 函數名稱:uchar DS1302_Read_Byte()函數功能:单字节读輸入參數:无輸出參數:读出的数据備注:uchar DS1302_Read_Byte(){uchar i,Temp = 0;for(i = 0;i < 8;i++){Temp = Temp >> 1;SCLK = 0;if(IO == 1)Temp = Temp | 0x80;SCLK = 1;}return Temp;}/************************************************************** 函數名稱:Write_DS1302(uchar Adr,uchar Date)函數功能:写数据輸入參數:写的寄存器地址和数据輸出參數:无備注:**************************************************************/ void Write_DS1302(uchar Adr,uchar Date){RST = 0;SCLK = 0;RST = 1;DS1302_Write_Byte(Adr);DS1302_Write_Byte(Date);RST = 0;}函數名稱:uchar Read_DS1302(uchar Adr)函數功能:读数据輸入參數:写的寄存器地址輸出參數:读出的数据備注:**************************************************************/ uchar Read_DS1302(uchar Adr){uchar Temp = 0;RST = 0;SCLK = 0;RST = 1;DS1302_Write_Byte(Adr);Temp = DS1302_Read_Byte();RST = 0;Temp = Temp / 16 * 10 + Temp % 16;return Temp;}/************************************************************** 函數名稱:Init_DS1302()函數功能:初始化DS1302輸入參數:无輸出參數:无備注:**************************************************************/ void Init_DS1302(){Write_DS1302(W_Control,0x00);Write_DS1302(W_Year,0x11);Write_DS1302(W_Week,0x06); Write_DS1302(W_Month,0x09); Write_DS1302(W_Day,0x10); Write_DS1302(W_Hour,0x16); Write_DS1302(W_Minute,0x11); Write_DS1302(W_Second,0x23); Write_DS1302(W_Control,0x80); }。
DS1302实时时钟芯片的C语言源程序
T_RST=0;
k=ucDa/16; //在将10进制的数转化为16进制的数。
ucDa=ucDa%16;
ucDa=ucDa+k*10;
return(ucDa);
}
void v_Set1302(uchar *pSecDa) /*设定初试时间*/
/* 时钟程序*/
/************************************/
sbit T_CLK=P3^6; /* 实时时钟的时钟线引脚*/
sbit T_IO=P3^7; /* 实时时钟的数据线*/
sbit T_RST=P3^5; /* 实时时钟的复位线引脚*/
}
void main1(void)
{ v_Get1302();
temp=ucCurtime[3]*10000+ucCurtime[2]*100+ucCurtime[1]; //temp里的值是为了显示到数码管里而设定的值.
display1();
}
void main2(void)
}
/*显示*/
void display1()
{
uchar c;
t2_10();
c=a[0]; //个位
P2=ledk[c]; //显示
gw=0;
unint a[6];//={0,0,0,0,0,0}; /*位段的数字*/
uchar code ledk[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
{
unsigned char ucDa,k;
DS1302芯片C语言程序
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include <intrins.h>sbit SCK=P3^6; //时钟sbit SDA=P3^4; //数据sbit RST = P3^5;// DS1302复位sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;bit ReadRTC_Flag;//定义读DS1302标志unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管0-9 '-' '熄灭‘表/******************************************************************//* 函数声明*//******************************************************************/void Write_Ds1302_byte(unsigned char temp);void Write_Ds1302( unsigned char address,unsigned char dat );unsigned char Read_Ds1302 ( unsigned char address );void Read_RTC(void);//read RTCvoid Set_RTC(void); //set RTCvoid InitTIMER0(void);//inital timer0/******************************************************************//* 主函数*//******************************************************************/void main(void){InitTIMER0(); //初始化定时器0Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽while(1){if(ReadRTC_Flag){ReadRTC_Flag=0;Read_RTC();l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开l_tmpdisplay[1]=l_tmpdate[2]&0x0f;l_tmpdisplay[2]=10; //加入"-"l_tmpdisplay[3]=l_tmpdate[1]/16;l_tmpdisplay[4]=l_tmpdate[1]&0x0f;l_tmpdisplay[5]=10;l_tmpdisplay[6]=l_tmpdate[0]/16;l_tmpdisplay[7]=l_tmpdate[0]&0x0f;}}}/******************************************************************//* 定时器0初始化*//******************************************************************/void InitTIMER0(void){TMOD|=0x01;//定时器设置16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************//* 写一个字节*//******************************************************************/void Write_Ds1302_Byte(unsigned char temp){unsigned char i;for (i=0;i<8;i++) //循环8次写入数据{SCK=0;SDA=temp&0x01; //每次传输低字节temp>>=1; //右移一位SCK=1;}}/******************************************************************/ /* 写入DS1302 */ /******************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ){RST=0;_nop_();SCK=0;_nop_();RST=1;_nop_(); //启动Write_Ds1302_Byte(address); //发送地址Write_Ds1302_Byte(dat); //发送数据RST=0; //恢复}/******************************************************************/ /* 读出DS1302数据*/ /******************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++) //循环8次读取数据{if(SDA)temp|=0x80; //每次传输低字节SCK=0;temp>>=1; //右移一位_nop_();_nop_();_nop_();SCK=1;}RST=0;_nop_(); //以下为DS1302复位的稳定时间_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp); //返回}/******************************************************************/ /* 读时钟数据*/ /******************************************************************/ void Read_RTC(void) //读取日历{unsigned char i,*p;p=read_rtc_address; //地址传递for(i=0;i<7;i++) //分7次读取秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************/ /* 设定时钟数据*/ /******************************************************************/ void Set_RTC(void) //设定日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){ //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}Write_Ds1302(0x8E,0X00);p=write_rtc_address; //传地址for(i=0;i<7;i++) //7次写入秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;}Write_Ds1302(0x8E,0x80);}/******************************************************************/ /* 定时器中断函数*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段switch(i){case 0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num) //隔段时间读取1302的数据。
DS1302 时钟芯片 C程序
sbit ds_sclk=P1^6;//串行时钟,输入,控制数据的输入输出
sbit ds_io =P3^5;//三线接口时的双向数据线
sbit ds_ce =P1^7;//输入信号,在读写数据期间,必须为高。该引脚有两个功能:
//第一,CE开始控制字访问移位寄存器的控制逻辑:其次,CE提供结束单字节或多字节数据传输的方法。
年份寄存器 8CH 8DH 00-99
更新时间:2012年07月17日
更新版本:无
更新日志:
2012年07月17日 文件大小:256字节
2012年07月17日 开始优化代码 将相同的代码写成函数以便调用
2012年07月17日 文件大小:276字节
2012年07月17日 除了突发功能没有编写其他的均已写出
/*DS1302年份寄存器地址*/
#define Read_years 0x8d //读取的年地址
#define Write_years 0x8c //写入的年地址
/*DS1302写保护寄存器地址*/
#define Read_wp 0x8f //读取的写保护地址
20ndef __DS_1302_H__
#define __DS_1302_H__
#include<stc89.h> //包含单片机寄存器的头文件
#define uchar unsigned char
#define uint unsigned int
ds1302_write(Write_years ,Decimal_bcd(12));//写入时间年
ds1302_write(Write_charging,ds_cr6 ); //写入是否涓流充电 不充电
DS1302时钟C语言编程完整实例
1 DS1302 简介:DS1302是美国D ALLAS 公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态R AM,采用S PI 三线接口与C PU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和R AM数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5~5.5V。
采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。
DS1302的外部引脚分配如图1所示及内部结构如图2所示。
DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
图1 DS1302的外部引脚分配图2 DS1302的内部结构各引脚的功能为:V cc1:主电源;Vcc2:备份电源。
当V cc2>Vcc1+0.2V 时,由Vcc2向D S1302供电,当V cc2< Vcc1时,由V cc1向D S1302供电。
SCLK:串行时钟,输入,控制数据的输入与输出;I/O:三线接口时的双向数据线;CE:输入信号,在读、写数据期间,必须为高。
该引脚有两个功能:第一,CE 开始控制字访问移位寄存器的控制逻辑;其次,CE 提供结束单字节或多字节数据传输的方法。
DS1302有下列几组寄存器:① D S1302有关日历、时间的寄存器共有12个,其中有7个寄存器 (读时81h ~8Dh ,写时80h ~8Ch ),存放的数据格式为 BCD 码形式, 如图3所示。
图 3 DS1302有关日历、时间的寄存器 小时寄存器(85h 、84h )的位7用于定义 D S1302是运行于12小时 模式还是24小时模式。
当为高时,选择12小时模式。
在12小时模式时,位5是 ,当为1时,表示 PM 。
在24小时模式时,位5是第二个10小时 位。
秒寄存器(81h 、80h )的位7定义为时钟暂停标志(CH )。
浅谈单片机c语言模块化编程-附ds1302时钟芯片驱动程序
浅谈单片机c语言模块化编程-附ds1302时钟芯片驱动程序在单片机c 语言编程中,模块化编程显得非常重要。
我觉得,模块化恰恰体现了c 语言很好的可移植性。
嵌入式编程中,硬件模块区分非常明显,所以驱动程序用模块化编程显得十分方便简洁。
报错原因,修改了不能修改的变量。
C51 中为了节省ram 资源,数组用code 定义在rom 中,这样定义数组就不能重新赋值。
自己对着例程一条一条的看。
真心表示没有发现错误。
最后把函数一个一个替换成例程中的。
最终确定在ds1302_write_byte 中。
发现了一个很奇特的事情。
错误是因为fou 循环,我用for(i=0;i0;i--)解决了问题。
extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
另外,extern 也可用来进行链接指定。
使用模块化编程的时候,在.h 里声明了数组。
.c 文件直接使用数组,在连接时会出现错误multiple public definition。
在.h 文件用extren 声明数组,在.c 文件声明赋值。
错误解决。
附ds1302 时钟芯片驱动程序void ds1302_write_byte(unsigned char d){unsigned char i;ACC=d;for(i=0;i>1;}}void ds1302_write(uchar ad,uchar dat){rst=0;sck=0;rst=1;//delayus(1);ds1302_write_byte(ad);ds1302_write_byte(dat);s ck=1;rst=0;}unsigned char ds1302_read_byte(){。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 DS130
2 简介:
DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5~5.5V。
采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。
DS1302的外部引脚分配如图1所示及内部结构如图2所示。
DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
图1 DS1302的外部引脚分配
图2 DS1302的内部结构
各引脚的功能为:
Vcc1:主电源;Vcc2:备份电源。
当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2< Vcc1时,由Vcc1向DS1302供电。
SCLK:串行时钟,输入;
I/O:三线接口时的双向数据线;
CE:输入信号,在读、写数据期间,必须为高。
该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。
DS1302有下列几组寄存器:
①DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h~8Dh,写时80h~8Ch),存放的数据格式为BCD码形式,如图3所示。
图 3 DS1302有关日历、时间的寄存器
小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。
当为高时,选择12小时模式。
在12小时模式时,位5是,当为1时,表示PM。
在24小时模式时,位5是第二个10小时位。
秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。
当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为0时,时钟开始运行。
控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。
在任何的对时钟和RAM 的写操作之前,WP位必须为0。
当WP位为1时,写保护位防止对任一寄存器的写操作。
②DS1302有关RAM的地址
DS1302中附加31字节静态RAM的地址如图4所示。
图4
③DS1302的工作模式寄存器
所谓突发模式是指一次传送多个字节的时钟信号和RAM数据。
突发模式寄存器如图5所示。
图5
④此外,DS1302还有充电寄存器等。
2 读写时序说明
DS1302是SPI总线驱动方式。
它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。
要想与DS1302通信,首先要先了解DS1302的控制字。
DS1302的控制字如图6。
图6 控制字(即地址及命令字节)
控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;
位5至位1(A4~A0):指示操作单元的地址;
位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。
控制字总是从最低位开始输出。
在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。
同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
数据读写时序如图7。
图7 数据读写时序
具体操作见驱动程序。
3 电路原理图:
电路原理图如图8,DS1302与单片机的连接也仅需要3条线:CE引脚、SCLK串行时钟引脚、I/O串行数据引脚,Vcc2为备用电源,外接32.768kHz晶振,为芯片提供计时脉冲。
图8
4 驱动程序
//寄存器宏定义
#define WRITE_SECOND 0x80
#define WRITE_MINUTE 0x82
#define WRITE_HOUR 0x84
#define READ_SECOND 0x81
#define READ_MINUTE 0x83
#define READ_HOUR 0x85
#define WRITE_PROTECT 0x8E
//位寻址寄存器定义
sbit ACC_7 = ACC^7;
//管脚定义
sbit SCLK = P3^5; // DS1302时钟信号7脚sbit DIO= P3^6; // DS1302数据信号6脚sbit CE = P3^7; // DS1302片选5脚
Write1302(WRITE_SECOND,0x18);
Write1302(WRITE_MINUTE,0x41);
Write1302(WRITE_HOUR,0x14);//14:41:18
//地址、数据发送子程序
void Write1302 ( unsigned char addr,dat )
{
unsigned char i,temp;
CE=0; //CE引脚为低,数据传送中止
SCLK=0; //清零时钟总线
CE = 1; //CE引脚为高,逻辑控制有效
//发送地址
for ( i=8; i>0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr >>= 1; //右移一位
SCLK = 1;
}
//发送数据
for ( i=8; i>0; i-- )
{
SCLK = 0;
temp = dat;
DIO = (bit)(temp&0x01);
dat >>= 1;
SCLK = 1;
}
CE = 0;
}
Miao=Read1302(0x81);
Feng= Read1302(0x83);
Xiaoshi= Read1302(0x85);
//数据读取子程序
unsigned char Read1302 ( unsigned char addr )
{
unsigned char i,temp,dat1,dat2;
CE=0;
SCLK=0;
CE = 1;
//发送地址
for ( i=8; i>0; i-- ) //循环8次移位
{
SCLK = 0;
temp = addr;
DIO = (bit)(temp&0x01); //每次传输低字节
addr >>= 1; //右移一位
SCLK = 1;
}
//读取数据
for ( i=8; i>0; i-- )
{
ACC_7=DIO;
SCLK = 0;
ACC>>=1;
SCLK = 1;
}
CE=0;
dat1=ACC;
dat2=dat1/16; //数据进制转换
dat1=dat1%16; //十六进制转十进制
dat1=dat1+dat2*10;
return (dat1);
}
//初始化DS1302
void Initial(void)
{
Write1302 (WRITE_PROTECT,0X00); //禁止写保护
Write1302 (WRITE_SECOND,0x56); //秒位初始化
Write1302 (WRITE_MINUTE,0x34); //分钟初始化
Write1302 (WRITE_HOUR,0x12); //小时初始化Write1302 (WRITE_PROTECT,0x80); //允许写保护}。