DS1302时钟
1 /********************************************************************************* 2 * 【编写时间】: 2016年02月15日 3 * 【作 者】: 清翔电子:03 4 * 【版 本】: 1.0 5 * 【网 站】: http://www.qxmcu.com/ 6 * 【淘宝店铺】: http://qxmcu.taobao.com/ 7 * 【实验平台】: QX-MCS51 单片机开发板 8 * 【外部晶振】: 11.0592mhz 9 * 【主控芯片】: STC89C52 10 * 【编译环境】: Keil μVisio3 11 * 【程序功能】: LCD1602液晶显示DS1302时钟日历 12 * 【使用说明】: 试验前请用杜邦线分别把j5排针根据背面丝印相应接到P10、P11、P12 13 并接上LCD1602液晶调节好对比度再下载此程序 14 15 * 说明:免费开源,不提供源代码分析. 16 **********************************************************************************/ 17 18 //调用1602显示驱动,在此文件内已包含51头文件和定义数据类型 19 #include "LCD1602.h" 20 /*==================================== 21 IO接口定义 22 ====================================*/ 23 sbit TSCLK = P1^0; //时钟 24 sbit TIO = P1^1; //数据 25 sbit TRST = P1^2; //使能 26 27 #define MAIN_Fosc 11059200UL //宏定义主时钟HZ 28 #define DS1302_W_ADDR 0x80 //写时钟日历寄存器起始地址 29 #define DS1302_R_ADDR 0x81 //读时钟日历寄存器起始地址 30 31 //时钟日历暂存数组,秒、分、时、日、月、周、年 初值为= 16年2月15日 周1 23:58:50 32 uchar TimeData[7]={50, 58, 23, 15, 2, 1, 16}; 33 34 /*================================================= 35 *函数名称:Delay_Ms 36 *函数功能:12T 51单片机自适应主时钟毫秒级延时函数 37 *说明:需定义MAIN_Fosc(晶振主频单位HZ) 38 *输入:ms:要延时的毫秒 39 =================================================*/ 40 void Delay_Ms(INT16U ms) 41 { 42 INT16U i; 43 do{ 44 i = MAIN_Fosc / 96000; 45 while(--i); //96T per loop 46 }while(--ms); 47 } 48 /*================================================= 49 *函数名称:DS1302_W_Byte 50 *函数功能:DS1302写一字节数据 51 *输入:dat:要写入的数据 52 =================================================*/ 53 void DS1302_W_Byte(uchar dat) 54 { 55 uchar i; 56 for(i = 0; i < 8; i++) //每次写1bit,写8次 57 { 58 TSCLK = 0; //拉低时钟总线 59 TIO = dat & 0x01; //从一字节最低位开始写 60 TSCLK = 1; //拉高时钟总线,DS1302把数据读走 61 dat >>= 1; //数据右移一位 62 } 63 } 64 /*================================================= 65 *函数名称:DS1302_R_Byte 66 *函数功能:DS1302读一字节 67 *输出:dat:读取的数据 68 =================================================*/ 69 uchar DS1302_R_Byte() 70 { 71 uchar i, dat; 72 for(i = 0; i < 8; i++) //每次写1bit,写8次 73 { 74 TSCLK = 0; //拉低时钟总线,DS1302把数据放到数据总线上 75 dat >>= 1; //数据右移一位,数据从最低位开始读 76 if(TIO) dat |= 0x80;//读取数据 77 TSCLK = 1; //拉高时钟总线 78 } 79 return dat; //返回读取的数据 80 } 81 /*================================================= 82 *函数名称:DS1302_W_DAT 83 *函数功能:写DS1302数据一次写2个字节 84 *说明:先写命令后写数据 85 *调用:DS1302_W_Byte() 86 *输入:cmd:需要写的命令 ,dat:需要些的数据 87 =================================================*/ 88 void DS1302_W_DAT(uchar cmd, uchar dat) 89 { 90 TRST = 0; //拉低使能端 91 TSCLK = 0; //拉低数据总线 92 TRST = 1; //拉高使能端,开始写数据 93 DS1302_W_Byte(cmd); //写命令 94 DS1302_W_Byte(dat); //写数据 95 } 96 /*================================================= 97 *函数名称:DS1302_R_DAT 98 *函数功能:读DS1302数据 99 *说明:先写入命令字节后读出对应数据 100 *调用: DS1302_W_Byte();DS1302_R_Byte(); 101 *输入: cmd:需要写的命令 102 *输出: dat:读出的数据 103 =================================================*/ 104 uchar DS1302_R_DAT(uchar cmd) 105 { 106 uchar dat; 107 TRST = 0; //拉低使能端 108 TSCLK = 0; //拉低数据总线 109 TRST = 1; //拉高使能端,开始写数据 110 DS1302_W_Byte(cmd); //写命令 111 dat = DS1302_R_Byte(); //读出数据 112 return dat; //返回读出数据 113 } 114 115 /*================================================= 116 *函数名称:DS1302_Clear_WP 117 *函数功能:清除DS1302写保护 118 *说明:先写入命令0x8e(写控制寄存器)接着向该寄存器写0 119 *调用:DS1302_W_DAT() 120 =================================================*/ 121 void DS1302_Clear_WP() 122 { 123 DS1302_W_DAT(0x8e,0x00); //把控制寄存器WP位置0 124 } 125 /*================================================= 126 *函数名称:DS1302_Clear_WP 127 *函数功能:设置DS1302写保护 128 *说明:先写入命令0x8e(写控制寄存器)接着向该寄存器写0x80 129 *调用:DS1302_W_DAT() 130 =================================================*/ 131 void DS1302_Set_WP() 132 { 133 DS1302_W_DAT(0x8e,0x80); //把控制寄存器WP位置1 134 TRST = 0; //拉低使能端 135 TSCLK = 0; //拉低数据总线 136 } 137 /*================================================= 138 *函数名称:Set_DS1302_Time 139 *函数功能:设置DS1302时钟日历数据 140 *说明:把时钟日历暂存数组TimeData数据转换为BCD码并 141 写入到DS1302时钟日历寄存器中 142 *调用:DS1302_Clear_WP();DS1302_W_DAT();DS1302_Set_WP(); 143 *输入:addr:需要写入寄存器的地址 ,TimeData数组:时钟日历初始值 144 =================================================*/ 145 void Set_DS1302_Time(uchar addr) 146 { 147 uchar i, j; 148 DS1302_Clear_WP(); //清除写保护 149 for(i = 0; i < 7; i++) //写入7个字节的时钟初始值 150 { 151 j = TimeData[i]/10; //BCD码转换 152 TimeData[i] %= 10; //BCD码转换 153 TimeData[i] += j*16; //BCD码转换 154 DS1302_W_DAT(addr, TimeData[i]); //先写DS1302时钟日历起始地址,再写数据 155 addr += 2; //时钟日历寄存器地址+2转向下一个寄存器 156 } 157 DS1302_Set_WP(); //开起写保护 158 } 159 /*================================================= 160 *函数名称:Read_DS1302_Time 161 *函数功能:读取DS1302时钟数据 162 *说明: 读取DS1302时钟数据 返回数据存入时钟日历暂存 163 数组TimeData(数据格式BCD码) 164 *调用:DS1302_Clear_WP();DS1302_R_DAT();DS1302_Set_WP(); 165 *输入: addr:需要读取时钟日历寄存器的起始地址 166 =================================================*/ 167 void Read_DS1302_Time(uchar addr) 168 { 169 uchar i; 170 DS1302_Clear_WP(); //清楚些保护 171 for(i = 0; i < 7; i++) //从DS1302读取7个字节的时钟日历数据 172 { 173 TimeData[i] = DS1302_R_DAT(addr);//先写入要读取数据的寄存器起始地址,再读出数据存入TimeData数组 174 addr += 2; //时钟日历寄存器地址+2转向下一个寄存器 175 } 176 DS1302_Set_WP(); //开起写保护 177 } 178 /*================================================= 179 *函数名称:main 180 *函数功能:主函数 1602液晶显示DS1302数据 181 Date:年-月-日-星期 182 Time:时:分:秒 183 =================================================*/ 184 void main() 185 { 186 InitLcd1602(); //1602初始化 187 Set_DS1302_Time(DS1302_W_ADDR); //先写入时钟日历寄存器起始地址再设置时钟日历初值 188 LcdShowStr(0,0,"Date:"); //1602显示字符串 189 LcdShowStr(0,1,"Time:"); //1602显示字符串 190 while(1) 191 { 192 Read_DS1302_Time(DS1302_R_ADDR); //先写入时钟日历寄存器起始地址再读出时钟日历写入到TimeData数组中 193 DisplayOneStr (5,0,TimeData[6]); //年 194 DisplayOneChar (7,0,'-'); //- 195 DisplayOneStr (8,0,TimeData[4]); //月 196 DisplayOneChar (10,0,'-'); //- 197 DisplayOneStr (11,0,TimeData[3]);//日 198 DisplayOneChar (13,0,'-'); //- 199 DisplayOneStr (14,0,TimeData[5]);//星期 200 201 DisplayOneStr (6,1,TimeData[2]); //时 202 DisplayOneChar (8,1,':'); //: 203 DisplayOneStr (9,1,TimeData[1]); //分 204 DisplayOneChar (11,1,':'); //: 205 DisplayOneStr (12,1,TimeData[0]);//秒 206 Delay_Ms(1000); //延时1秒 207 } 208 }
一个二次元的生物