时钟DS1302LCD
/********************************************************************
 * 描述 ? ?: ?该文件实现用DS1302来实现日历和时钟功能,液晶1602上显示出来。
 ***********************************************************************/
 #include<reg52.h>
 #include<intrins.h>
#define uchar unsigned char
 #define uint ?unsigned int
sbit ACC0 = ACC^0;
 sbit ACC7 = ACC^7;
sbit T_CLK = P1^6; /*实时时钟时钟线引脚 */
 sbit T_IO = P3^5; /*实时时钟数据线引脚 */
 sbit T_RST = P1^7; /*实时时钟复位线引脚 */
//这三个引脚参考资料
 sbit E=P2^7;?? ??? ?//1602使能引脚
 sbit RW=P2^6;?? ??? ?//1602读写引脚?? ?
 sbit RS=P2^5;?? ??? ?//1602数据/命令选择引脚
/********************************************************************
 * 名称 : delay()
 * 功能 : 延时,延时时间大概为140US。
 * 输入 : 无
 * 输出 : 无
 ***********************************************************************/
void delay()
 {
 ?? ?int i,j;
 ?? ?for(i=0; i<=10; i++)
 ?? ?for(j=0; j<=2; j++)
 ;
 }
 /********************************************************************
 * 名称 : enable(uchar del)
 * 功能 : 1602命令函数
 * 输入 : 输入的命令值
 * 输出 : 无
 ***********************************************************************/
void enable(uchar del)
 {
 ?? ?P0 = del;
 ?? ?RS = 0;
 ?? ?RW = 0;
 ?? ?E = 0;
 ?? ?delay();
 ?? ?E = 1;
 ?? ?delay();
 }
/********************************************************************
 * 名称 : write(uchar del)
 * 功能 : 1602写数据函数
 * 输入 : 需要写入1602的数据
 * 输出 : 无
 ***********************************************************************/
void write(uchar del)
 {
 ?? ?P0 = del;
 ?? ?RS = 1;
 ?? ?RW = 0;
 ?? ?E = 0;
 ?? ?delay();
 ?? ?E = 1;
 ?? ?delay();
 }
/********************************************************************
 * 名称 : L1602_init()
 * 功能 : 1602初始化,请参考1602的资料
 * 输入 : 无
 * 输出 : 无
 ***********************************************************************/
 void L1602_init(void)
 {
 ?? ?enable(0x01);
 ?? ?enable(0x38);
 ?? ?enable(0x0c);
 ?? ?enable(0x06);
 ?? ?enable(0xd0);
 }
/********************************************************************
 * 名称 : L1602_char(uchar hang,uchar lie,char sign)
 * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
 ?? ??? ? L1602_char(1,5,'b')
 * 输入 : 行,列,需要输入1602的数据
 * 输出 : 无
 ***********************************************************************/
 void L1602_char(uchar hang,uchar lie,char sign)
 {
 ?? ?uchar a;
 ?? ?if(hang == 1) a = 0x80;
 ?? ?if(hang == 2) a = 0xc0;
 ?? ?a = a + lie - 1;
 ?? ?enable(a);
 ?? ?write(sign);
 }
/********************************************************************
 * 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
 * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
 ?? ? ?? ? L1602_string(1,5,"ab cd ef;")
 * 输入 : 行,列,需要输入1602的数据
 * 输出 : 无
 ***********************************************************************/
 void L1602_string(uchar hang,uchar lie,uchar *p)
 {
 ?? ?uchar a;
 ?? ?if(hang == 1) a = 0x80;
 ?? ?if(hang == 2) a = 0xc0;
 ?? ?a = a + lie - 1;
 ?? ?enable(a);
 ?? ?while(1)
 ?? ?{
 ?? ??? ?if(*p == '\0') break;
 ?? ??? ?write(*p);
 ?? ??? ?p++;
 ?? ?}
 }
/********************************************************************
 * 名称 : ?v_RTInputByte()
 * 功能 : ?往DS1302写入1Byte数据
 * 输入 : ?ucDa 写入的数据
 * 输出 : ?无
 ***********************************************************************/
 void v_RTInputByte(uchar ucDa)
 {
 ?? ?uchar i;
 ?? ?ACC = ucDa;
 ?? ?T_RST = 1;
 ?? ?for(i=8; i>0; i--)
 ?? ?{
 ?? ??? ?T_IO = ACC0;
 ?? ??? ?T_CLK = 1;
 ?? ??? ?T_CLK = 0;
 ?? ??? ?ACC = ACC >> 1;
 ?? ?}
 }
/********************************************************************
 * 名称 ?: ? uc_RTOutputByte()
 * 功能 ?: ? 从DS1302读取1Byte数据
 * 输入 ?:?? ?无
 * 返回值: ? ACC
 ***********************************************************************/
 uchar uc_RTOutputByte(void)?
 {
 ?? ?uchar i;
 ?? ?T_RST = 1;
 ?? ?for(i=8; i>0; i--)
 ?? ?{
 ?? ??? ?ACC = ACC >>1;
 ?? ??? ?T_IO=1;
 ?? ??? ?ACC7 = T_IO;
 ?? ??? ?T_CLK = 1;
 ?? ??? ?T_CLK = 0;
 ?? ?}
 ?? ?return(ACC);
 }
/********************************************************************
 * 名称 ? : ? v_W1302(uchar ucAddr, uchar ucDa)
 * 功能 ? : ? 往DS1302写入数据
 * 输入 ? : ? ucAddr: DS1302地址, ucDa: 要写的数据
 * 返回值 : ? 无
 ***********************************************************************/
 void v_W1302(uchar ucAddr, uchar ucDa)
 {
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(ucAddr); ? // 写地址?
 ?? ?_nop_();
 ?? ?_nop_();
 ?? ?v_RTInputByte(ucDa); ? ? // 写1Byte数据
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 }
/********************************************************************
 * 名称 ? : ?uc_R1302(uchar ucAddr)
 * 功能 ? : ?读取DS1302某地址的数据
 * 输入 ? : ?ucAddr: DS1302地址
 * 返回值 : ?ucDa :读取的数据
 ***********************************************************************/
 uchar uc_R1302(uchar ucAddr)
 {
 ?? ?uchar ucDa;
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(ucAddr); ? ?//写地址,命令
 ?? ?_nop_();
 ?? ?_nop_();
 ?? ?ucDa = uc_RTOutputByte(); //读1Byte数据
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 ?? ?return(ucDa);
 }
/********************************************************************
 * 名称 ? : ?v_BurstW1302T
 * 功能 ? : ?往DS1302写入时钟数据(多字节方式)
 * 输入 ? : ?pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
 * ?? ??? ??? ??? ??? ??? ? ? 8Byte (BCD码) 1B 1B 1B 1B 1B 1B ?1B ?1B
 * 返回值 : ?无
 ***********************************************************************/
 void v_BurstW1302T(uchar *pSecDa)
 {
 ?? ?uchar i;
 ?? ?v_W1302(0x8e, 0x00); ? ? ? ? ?//控制命令,WP=0,写操作
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(0xbe); ? ? ? ? ?//0xbe:时钟多字节写命令
 ?? ?for(i=8; i>0; i--) ? ? ? ? ? ?//8Byte = 7Byte 时钟数据 + 1Byte 控制
 ?? ?{
 ?? ??? ?v_RTInputByte(*pSecDa); ? //写1Byte数据
 ?? ??? ?pSecDa++;
 ?? ?}
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 }
/********************************************************************
 * 名称 ? : ?v_BurstR1302T(uchar *pSecDa)
 * 功能 ? : ?读取DS1302时钟数据
 * 输入 ? : ?pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年
 * ?? ??? ??? ??? ??? ? ? ? ? 7Byte (BCD码) 1B 1B 1B 1B 1B 1B ? 1B
 * 返回值 : ?ucDa :读取的数据
 ***********************************************************************/
 void v_BurstR1302T(uchar *pSecDa)
 {
 ?? ?uchar i;
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(0xbf); ? ? ? ? ? ? ? //0xbf:时钟多字节读命令
 ?? ?for(i=8; i>0; i--)
 ?? ?{
 ?? ??? ?*pSecDa = uc_RTOutputByte(); ? //读1Byte数据
 ?? ??? ?pSecDa++;
 ?? ?}
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 }
/********************************************************************
 * 名称 ? : ?v_BurstW1302R(uchar *pReDa)
 * 功能 ? : ?往DS1302寄存器数写入数据(多字节方式)
 * 输入 ? : ?pReDa: 寄存器数据地址
 * 返回值 : ?无
 ***********************************************************************/
 void v_BurstW1302R(uchar *pReDa)
 {
 ?? ?uchar i;
 ?? ?v_W1302(0x8e,0x00); ? ? ? ? //控制命令,WP=0,写操作
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(0xfe); ? ? ? //0xbe:时钟多字节写命令
 ?? ?for(i=31; i>0; i--) ? ? ? ?//31Byte 寄存器数据
 ?? ?{
 ?? ??? ?v_RTInputByte(*pReDa); //写1Byte数据
 ?? ??? ?pReDa++;
 ?? ?}
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 }
/********************************************************************
 * 名称 ? : ?v_BurstR1302R(uchar *pReDa)
 * 功能 ? : ?读取DS1302寄存器数据
 * 输入 ? : ?pReDa: 寄存器数据地址
 * 返回值 : ?无
 ***********************************************************************/
 void v_BurstR1302R(uchar *pReDa)
 {
 ?? ?uchar i;
 ?? ?T_RST = 0;
 ?? ?T_CLK = 0;
 ?? ?T_RST = 1;
 ?? ?v_RTInputByte(0xff); ? ? ? ? ? ?//0xbf:时钟多字节读命令
 ?? ?for(i=31; i>0; i--) ? ? ? ? ? ? //31Byte 寄存器数据
 ?? ?{
 ?? ??? ?*pReDa = uc_RTOutputByte(); //读1Byte数据
 ?? ??? ?pReDa++;
 ?? ?}
 ?? ?T_CLK = 1;
 ?? ?T_RST = 0;
 }
/********************************************************************
 * 名称 ?: ?v_Set1302(uchar *pSecDa)
 * 功能 ?: ?设置初始时间
 * 输入 ?: ?pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年
 * ?? ??? ??? ??? ??? ??? ??? ??? ? ? 7Byte (BCD码) 1B 1B 1B 1B 1B 1B ?1B
 * 返回值: 无
 ***********************************************************************/
 void v_Set1302(uchar *pSecDa)
 {
 ?? ?uchar i;
 ?? ?uchar ucAddr = 0x80;
 ?? ?v_W1302(0x8e, 0x00); ? ? ? ? ? ?//控制命令,WP=0,写操作
 ?? ?for(i=7; i>0; i--)
 ?? ?{
 ?? ??? ?v_W1302(ucAddr, *pSecDa); ? // 秒 分 时 日 月 星期 年
 ?? ??? ?pSecDa++;
 ?? ??? ?ucAddr += 2;
 ?? ?}
 ?? ?v_W1302(0x8e, 0x80); ? ? ? ? ? ?//控制命令,WP=1,写保护
 }
/********************************************************************
 * 名称 ? : v_Get1302(uchar ucCurtime[])
 * 功能 ? : 读取DS1302当前时间
 * 输入 ? : ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
 * ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 7Byte (BCD码) 1B 1B 1B 1B 1B ?1B ?1B
 * 返回值 : 无
 ***********************************************************************/
 void v_Get1302(uchar ucCurtime[])
 {
 ?? ?uchar i;
 ?? ?uchar ucAddr = 0x81;
 ?? ?for(i=0; i<7; i++)
 ?? ?{
 ?? ??? ?ucCurtime[i] = uc_R1302(ucAddr); ? ?//格式为: 秒 分 时 日 月 星期 年
 ?? ??? ?ucAddr += 2;
 ?? ?}
 }
/********************************************************************
 * 名称 : dectobcd(uchar dec)
 * 功能 : DEC码转换为BCD码
 * 输入 : dec码
 * 输出 : bcd码
 ***********************************************************************/
 uchar dectobcd(uchar dec)
 {
 ?? ?uchar bcd;
 ?? ?bcd = 0;
 ?? ?while(dec >= 10)
 ?? ?{ ? ? ? ? ? ? ?
 ?? ??? ?dec -= 10; ? ? ? ? ? ? ? ? ? ? ? ??
 ?? ??? ?bcd++;
 ?? ?}?
 ?? ?bcd <<= 4;
 ?? ?bcd |= dec;
 ?? ?return bcd;
 }
/********************************************************************
 * 名称 : bcdtodec(uchar bcd)
 * 功能 : BCD码转换为DEC码
 * 输入 : bcd码
 * 输出 : dec码
 ***********************************************************************/
 uchar bcdtodec(uchar bcd)
 {
 ?? ?uchar data1;
 ?? ?data1 = bcd & 0x0f; ? ? //取BCD低4位
 ?? ?bcd = bcd & 0x70; ? ? ? //剔除BCD的最高位和低4位。
 ?? ?data1 += bcd >> 1;
 ?? ?data1 += bcd >> 3; ? ? ?//用位移代替乘法运算
 ?? ?return data1;
 }
/********************************************************************
 * 名称 : Write_DS1302Init()
 * 功能 : 往DS1302中写入数据。最开始显示的数据就是在这里设置的。
 * 输入 : 无
 * 输出 : 无
 ***********************************************************************/
 void Write_DS1302Init(void)
 {
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x80,0x50);?? ?//写入秒
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x82,0x59);?? ?//写入分
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x84,0x07);?? ?//写入小时
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x86,0x08);?? ?//写入日
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x88,0x08);?? ?//写入月
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x8a,0x05);?? ?//写入星期
 ?? ?v_W1302(0x8e,0);
 ?? ?v_W1302(0x8c,0x08);?? ?//写入年?? ?
 }
/********************************************************************
 * 名称 : Run_DS1302(void)
 * 功能 : 读出DS1302中的数据,并在液晶1602上进行显示
 * 输入 : 无
 * 输出 : 无
 ***********************************************************************/
 void Run_DS1302(void)
 {
 ?? ?uchar sec, min, hour, day, month, year;
 ?? ?while(1)
 ?? ?{
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?sec = bcdtodec(uc_R1302(0x81));?? ? ? //读出DS1302中的秒
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?min = bcdtodec(uc_R1302(0x83));?? ? ? //读出DS1302中的分
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?hour = bcdtodec(uc_R1302(0x85)); ? //读出DS1302中的小时
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?day = bcdtodec(uc_R1302(0x87));?? ? ? //读出DS1302中的日
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?month = bcdtodec(uc_R1302(0x89)); ?//读出DS1302中的月
 ?? ??? ?v_W1302(0x8f, 0);
 ?? ??? ?year = bcdtodec(uc_R1302(0x8d)); ? //读出DS1302中的年
?? ??? ?L1602_char(2, 6, hour / 10 % 10 + 48);
 ?? ??? ?L1602_char(2, 7, hour % 10 + 48);
 ?? ??? ?L1602_char(2, 8, '-');
 ?? ??? ?L1602_char(2, 9, min / 10 % 10 + 48);
 ?? ??? ?L1602_char(2, 10, min % 10 + 48);
 ?? ??? ?L1602_char(2, 11, '-');
 ?? ??? ?L1602_char(2, 12, sec / 10 % 10 + 48);
 ?? ??? ?L1602_char(2, 13, sec % 10 + 48);
 ?? ??? ?L1602_char(1, 8, year / 10 % 10 + 48);
 ?? ??? ?L1602_char(1, 9, year % 10 + 48);
 ?? ??? ?L1602_char(1, 10, '-');
 ?? ??? ?L1602_char(1, 11, month / 10 % 10 + 48);
 ?? ??? ?L1602_char(1, 12, month % 10 + 48);
 ?? ??? ?L1602_char(1, 13, '-');
 ?? ??? ?L1602_char(1, 14, day / 10 % 10 + 48);
 ?? ??? ?L1602_char(1, 15, day % 10 + 48);
 ?? ?}
}?
/********************************************************************
 * 名称 : Main(void)
 * 功能 : 主函数
 * 输入 : 无
 * 输出 : 无
 ***********************************************************************/?
 void Main(void)
 {
 ?? ?L1602_init();
 ?? ?L1602_string(1,1,"DAYS 20");
 ?? ?L1602_string(2,1,"TIME");
 ?? ?Write_DS1302Init();
 ?? ?Run_DS1302();
 }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!