找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1763|回复: 1
收起左侧

51单片机DS1302简要记录

[复制链接]
ID:825513 发表于 2021-5-16 20:40 | 显示全部楼层 |阅读模式
写了一个DS1302的程序,在开发板上成功运行,通过LCD1602显示时间,现在分享出来,给像我这样的单片机萌新一个参考吧。

从2021年5月11日0时0分0秒开始计时并在LCD1602上显示,源码如下:

  1. #include<reg52.h>
  2. #include<intrins.h>

  3. sbit RST=P2^4;
  4. sbit CLK=P2^1;
  5. sbit IO=P2^0;
  6. sbit RS=P1^0;
  7. sbit RW=P1^1;
  8. sbit E=P2^5;
  9. sbit DU=P2^6;

  10. unsigned char num[]={"0123456789"};                //LCD1602显示的数字字符

  11. void X()                //关闭数码管
  12. {
  13.         DU=1;
  14.         P0=0x00;
  15.         DU=0;
  16. }

  17. void Delay()
  18. {
  19.         _nop_();
  20. }

  21. void Write_Bit_DS1302(unsigned char DAT)                //向DS1302写入一字节的数据
  22. {
  23.         unsigned char i;
  24.         CLK=0;
  25.         Delay();
  26.         for(i=0;i<8;i++)
  27.         {
  28.                 IO=DAT&0x01;                //低位在前,高位在后
  29.                 Delay();
  30.                 CLK=1;                //时钟信号上升沿,写入数据
  31.                 Delay();
  32.                 CLK=0;                //重新拉低CLK,形成脉冲
  33.                 DAT>>=1;                //将DAT的各数据位右移1位,准备写入下一数据位
  34.         }
  35. }

  36. void Write_DS1302(unsigned char CMD,unsigned char DAT)                //向DS1302写入命令和数据
  37. {
  38.         RST=0;                //禁止数据传输
  39.         CLK=0;                //在写入数据前确保CLK置低电平
  40.         RST=1;                //开始数据传输
  41.         Delay();
  42.         Write_Bit_DS1302(CMD);                //写入命令
  43.         Write_Bit_DS1302(DAT);                //写入数据
  44.         CLK=1;
  45.         RST=0;
  46. }

  47. unsigned char Read_Bit_DS1302()                //从DS1302读出一字节的数据
  48. {
  49.         unsigned char i,DAT;
  50.         Delay();
  51.         for(i=0;i<8;i++)
  52.         {
  53.                 DAT>>=1;
  54.                 if(IO==1)
  55.                 {
  56.                         DAT|=0x80;
  57.                 }
  58.                 CLK=1;
  59.                 Delay();
  60.                 CLK=0;                //时钟信号下降沿,读出数据
  61.                 Delay();
  62.         }
  63.         return DAT;
  64. }

  65. unsigned char Read_DS1302(unsigned char CMD)                //向DS1302写入命令后再从DS1302读出数据
  66. {
  67.         unsigned char DAT;
  68.         RST=0;
  69.         CLK=0;
  70.         RST=1;
  71.         Write_Bit_DS1302(CMD);                //写入命令
  72.         DAT=Read_Bit_DS1302();                //读出数据
  73.         CLK=1;
  74.         RST=0;
  75.         return DAT;
  76. }

  77. void Init_DS1302()                //DS1302初始化
  78. {
  79.         unsigned char X;
  80.         X=Read_DS1302(0x81);
  81.         if(X&0x80)                //判断DS1302是否处于运行状态
  82.         {
  83.                 Write_DS1302(0x8e,0x00);                //允许将数据写入DS1302的寄存器
  84.                 Write_DS1302(0x80,((00/10)<<4|(00%10)));                //写入“秒”的初始值,需要将LCD1602显示的数字的ASCII值转换成BCD码
  85.                 Write_DS1302(0x82,((00/10)<<4|(00%10)));                //写入“分”的初始值
  86.                 Write_DS1302(0x84,((00/10)<<4|(00%10)));                //写入“时”的初始值
  87.                 Write_DS1302(0x86,((11/10)<<4|(11%10)));                //写入“日”的初始值
  88.                 Write_DS1302(0x88,((5/10)<<4|(5%10)));                //写入“月”的初始值
  89.                 Write_DS1302(0x8c,((21/10)<<4|(21%10)));                //写入“年”的初始值
  90.                 Write_DS1302(0x8e,0x80);                //禁止将数据写入DS1302的寄存器
  91.         }
  92. }

  93. void Delay5ms()
  94. {
  95.         unsigned char i,j;
  96.         _nop_();
  97.         i=9;
  98.         j=244;
  99.         do
  100.         {
  101.                 while(--j);
  102.         }
  103.         while(--i);
  104. }

  105. int ReadBusy()                //LCD1602“读忙”操作
  106. {
  107.         int temp;
  108.         RS=0;
  109.         RW=1;
  110.         _nop_();
  111.         P0=0xff;
  112.         _nop_();
  113.         E=1;
  114.         _nop_();
  115.         temp=P0;
  116.         _nop_();
  117.         E=0;
  118.         return(temp&0x80);
  119. }

  120. void Write_Com(char com)                //LCD1602“写命令”操作
  121. {
  122.         while(ReadBusy());
  123.         RS=0;
  124.         RW=0;
  125.         E=0;
  126.         _nop_();
  127.         P0=com;
  128.         _nop_();
  129.         E=1;
  130.         Delay5ms();
  131.         E=0;
  132.         Delay5ms();
  133. }

  134. void Write_Dat(char dat)                //LCD1602“写数据”操作
  135. {
  136.         while(ReadBusy());
  137.         RS=1;
  138.         RW=0;
  139.         E=0;
  140.         _nop_();
  141.         P0=dat;
  142.         _nop_();
  143.         E=1;
  144.         Delay5ms();
  145.         E=0;
  146.         Delay5ms();
  147. }

  148. void LCD1602_Init()                //LCD1602初始化
  149. {
  150.         Delay5ms();                //延时15ms,首次写入LCD1602时应给LCD1602一段较长的响应时间
  151.         Delay5ms();
  152.         Delay5ms();
  153.         Write_Com(0x38);                //显示模式设置:16*2显示、5*7点阵,连续写入3次,确保LCD1602初始化成功
  154.         Delay5ms();
  155.         Write_Com(0x38);
  156.         Delay5ms();
  157.         Write_Com(0x38);
  158.         Delay5ms();
  159.         Write_Com(0x0c);                //显示模式设置:开显示、光标不显示、光标不闪烁
  160.         Delay5ms();
  161.         Write_Com(0x06);                //显示模式设置:光标右移,字符不右移
  162.         Delay5ms();
  163.         Write_Com(0x01);                //清除屏幕
  164.         Delay5ms();
  165. }

  166. void Display_Second(unsigned char x)                //LCD1602显示“秒”的数值
  167. {
  168.         unsigned char i,j;
  169.         i=x/10;                //取数值的十位
  170.         j=x%10;                //取数值的个位
  171.         Write_Com(0x80+0x49);                //写入在LCD1602上显示的位置
  172.         Write_Dat(num[i]);
  173.         Write_Dat(num[j]);
  174.         Delay5ms();
  175. }

  176. void Display_Minute(unsigned char x)                //LCD1602显示“分”的数值
  177. {
  178.         unsigned char i,j;
  179.         i=x/10;
  180.         j=x%10;
  181.         Write_Com(0x80+0x46);
  182.         Write_Dat(num[i]);
  183.         Write_Dat(num[j]);
  184.         Delay5ms();
  185. }

  186. void Display_Hour(unsigned char x)                //LCD1602显示“时”的数值
  187. {
  188.         unsigned char i,j;
  189.         i=x/10;
  190.         j=x%10;
  191.         Write_Com(0x80+0x43);
  192.         Write_Dat(num[i]);
  193.         Write_Dat(num[j]);
  194.         Delay5ms();
  195. }

  196. void Display_Day(unsigned char x)                //LCD1602显示“日”的数值
  197. {
  198.         unsigned char i,j;
  199.         i=x/10;
  200.         j=x%10;
  201.         Write_Com(0x80+0x0c);
  202.         Write_Dat(num[i]);
  203.         Write_Dat(num[j]);
  204.         Delay5ms();
  205. }

  206. void Display_Month(unsigned char x)                //LCD1602显示“月”的数值
  207. {
  208.         unsigned char i,j;
  209.         i=x/10;
  210.         j=x%10;
  211.         Write_Com(0x80+0x09);
  212.         Write_Dat(num[i]);
  213.         Write_Dat(num[j]);
  214.         Delay5ms();
  215. }

  216. void Display_Year(unsigned char x)                //LCD1602显示“年”的数值
  217. {
  218.         unsigned char i,j;
  219.         i=x/10;
  220.         j=x%10;
  221.         Write_Com(0x80+0x06);
  222.         Write_Dat(num[i]);
  223.         Write_Dat(num[j]);
  224.         Delay5ms();
  225. }

  226. void main()
  227. {
  228.         unsigned char second,minute,hour,day,month,year;
  229.         unsigned char temp;                //暂存从DS1302读出的数据
  230.         X();
  231.         LCD1602_Init();
  232.         Write_Com(0x80+0x01);
  233.         Write_Dat('D');
  234.         Write_Dat('A');
  235.         Write_Dat('T');
  236.         Write_Dat('E');
  237.         Write_Dat(':');
  238.         Delay5ms();
  239.         Write_Com(0x80+0x08);
  240.         Write_Dat('-');
  241.         Delay5ms();
  242.         Write_Com(0x80+0x0b);
  243.         Write_Dat('-');
  244.         Delay5ms();
  245.         Write_Com(0x80+0x45);
  246.         Write_Dat(':');
  247.         Delay5ms();
  248.         Write_Com(0x80+0x48);
  249.         Write_Dat(':');
  250.         Delay5ms();
  251.         Init_DS1302();
  252.         
  253.         while(1)
  254.         {
  255.                 temp=Read_DS1302(0x81);
  256.                 second=((temp&0x70)>>4)*10+(temp&0x0f);                //将“秒”的BCD码转换成对应的ASCII值
  257.                 Display_Second(second);
  258.                 temp=Read_DS1302(0x83);
  259.                 minute=((temp&0x70)>>4)*10+(temp&0x0f);                //将“分”的BCD码转换成对应的ASCII值
  260.                 Display_Minute(minute);
  261.                 temp=Read_DS1302(0x85);
  262.                 hour=((temp&0x70)>>4)*10+(temp&0x0f);                //将“时”的BCD码转换成对应的ASCII值
  263.                 Display_Hour(hour);
  264.                 temp=Read_DS1302(0x87);
  265.                 day=((temp&0x70)>>4)*10+(temp&0x0f);                //将“日”的BCD码转换成对应的ASCII值
  266.                 Display_Day(day);
  267.                 temp=Read_DS1302(0x89);
  268.                 month=((temp&0x70)>>4)*10+(temp&0x0f);                //将“月”的BCD码转换成对应的ASCII值
  269.                 Display_Month(month);
  270.                 temp=Read_DS1302(0x8d);
  271.                 year=((temp&0x70)>>4)*10+(temp&0x0f);                //将“年”的BCD码转换成对应的ASCII值
  272.                 Display_Year(year);
  273.         }
  274. }
复制代码

以下为原理图
LCD1602模块.png
DS1302时钟模块.png

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:924117 发表于 2021-5-20 22:05 | 显示全部楼层
感谢分享,有个疑问,I/O接口的输出方式是什么?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表