设为首页收藏本站帮助中心
查看: 44|回复: 0
收起左侧

STC15F104E/W系列单片机 DS1302时钟芯片驱动程序源码+软串口发送日期时间星期

[复制链接]
发表于 2020-7-27 16:21:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?加入我们

x
DS1302.jpg

  1. /*
  2. 单片机型号:STC15F104E 晶振频率:11.0592Mhz 波特率:9600
  3. */
  4. #include "stc15f104e.h"
  5. #include "intrins.h"
  6. #define is_leap_year(year) ((year) %4 == 0 && (year) %100 !=0 || (year) %400 ==0)                //闰年判断

  7. #define U8 unsigned char
  8. #define U16 unsigned int
  9. #define U32 unsigned long
  10. sbit DS1302_SCLK = P3 ^ 2;        //时钟口
  11. sbit DS1302_IO = P3 ^ 3;        //数据口
  12. sbit DS1302_RST = P3 ^ 4;        //片选口
  13. sbit KEY=P3^5;                        //低电平设置指定时间
  14. sbit txd = P3 ^ 1;

  15. void delay_uart() {     //11.0592Mhz 延时1/9600秒
  16.     unsigned char a,b;
  17.     for(b=114;b>0;b--)
  18.         for(a=1;a>0;a--);
  19. }

  20. void delay1s(){
  21.     unsigned char a,b,c;
  22.     for(c=217;c>0;c--)
  23.         for(b=171;b>0;b--)
  24.             for(a=73;a>0;a--);
  25. }

  26. void TXD_Byte(U8 Byte) {   //串口发送1字节
  27.         U8 j = 1;
  28.         delay_uart();
  29.         txd = 0;
  30.         do {
  31.                 delay_uart();
  32.                 txd = Byte & j;
  33.                 j <<= 1;
  34.         } while (j);
  35.         delay_uart();
  36.         txd = 1;
  37. }

  38. void TXD_Text(U8* text) {      //串口发送字符串
  39.         for (; *text; text++) {
  40.                 TXD_Byte(*text);
  41.         }
  42. }

  43. U8 code MonthTable[2][12] = {
  44.         {31,28,31,30,31,30,31,31,30,31,30,31},                //平年月数表
  45.         {31,29,31,30,31,30,31,31,30,31,30,31},                //闰年月数表
  46. };

  47. U32 code WeekText[7] = {                //星期字符串数组
  48.         0x53554E20,                //SUN 周日
  49.         0x4D4F4E20,                //MON 周一
  50.         0x54554520,                //TUE 周二
  51.         0x57454420,                //WED 周三
  52.         0x54485520,                //THU 周四
  53.         0x46524920,                //FRI 周五
  54.         0x53415420,                //SAT 周六
  55. };

  56. U8 dec2bcd(U8 D) {                //将10进制的19转化成16进制的0x19
  57.         return ((D / 10) << 4) + (D % 10);
  58. }               
  59. U8 bcd2dec(U8 H) {                //将16进制的0x19转化成10进制的19
  60.         return (H >> 4) * 10 + (H & 15);
  61. }               

  62. union ds1302_now{        //10进制 DS1302时间 (24小时制)
  63.         struct {
  64.                 U8 sec;                //秒 0~59
  65.                 U8 min;                //分钟 0~59
  66.                 U8 hour;        //小时 0~23
  67.                 U8 day;                //日 1~31
  68.                 U8 month;        //月 1~12
  69.                 U8 week;        //星期 1~7 (星期日为1 星期一为2)
  70.                 U8 year;        //年 0~99
  71.         } now;
  72.         U8 dat[7];
  73. };

  74. union time_text {        //字符串时间 YYYY-MM-DD WWW HH:II:SS (24小时制)
  75.         struct {
  76.                 U8 year[4];                //年4位 前2位固定20
  77.                 U8 sub1;                //减号 固定0x2D
  78.                 U8 month[2];        //月2位
  79.                 U8 sub2;                //减号 固定0x2D
  80.                 U8 day[2];                //日 2位
  81.                 U8 bla1;                //空格 固定0x20
  82.                 U32 week;                //星期代码 4位 SUN MON TUE WED THU FRI SAT (最后1位空格)
  83.                 U8 hour[2];                //小时2位
  84.                 U8 col1;                //冒号 固定0x3A
  85.                 U8 min[2];                //分钟 2位
  86.                 U8 col2;                //冒号 固定0x3A
  87.                 U8 sec[2];                //秒 2位
  88.                 U8 null;                //字符串结束符(空字符) 固定0x00
  89.         } str;
  90.         U8 dat[24];
  91. };

  92. U8 *now2text(U8 *ds1302_now) {                //DS1302时间转字符串
  93.         union ds1302_now *now= ds1302_now;
  94.         static union time_text text;
  95.         if (now->now.week >= 1 && now->now.week <= 7) {
  96.                 text.str.week = WeekText[now->now.week - 1];
  97.         }
  98.         else {
  99.                 text.str.week = 0x45525220;
  100.         }
  101.         text.str.year[0] = 0x32;
  102.         text.str.year[1] = 0x30;
  103.         text.str.sub1 = 0x2D;
  104.         text.str.sub2 = 0x2D;
  105.         text.str.col1 = 0x3A;
  106.         text.str.col2 = 0x3A;
  107.         text.str.bla1 = 0x20;
  108.         text.str.null = 0x00;
  109.         text.str.year[2] = (now->now.year / 10 % 10) | 0x30;
  110.         text.str.year[3] = (now->now.year % 10) | 0x30;
  111.         text.str.month[0] = (now->now.month / 10 % 10) | 0x30;
  112.         text.str.month[1] = (now->now.month % 10) | 0x30;
  113.         text.str.day[0] = (now->now.day / 10 % 10) | 0x30;
  114.         text.str.day[1] = (now->now.day % 10) | 0x30;
  115.         text.str.hour[0] = (now->now.hour / 10 % 10) | 0x30;
  116.         text.str.hour[1] = (now->now.hour % 10) | 0x30;
  117.         text.str.min[0] = (now->now.min / 10 % 10) | 0x30;
  118.         text.str.min[1] = (now->now.min % 10) | 0x30;
  119.         text.str.sec[0] = (now->now.sec / 10 % 10) | 0x30;
  120.         text.str.sec[1] = (now->now.sec % 10) | 0x30;

  121.         return text.dat;
  122. }

  123. void DS1302_Delay() {        //延时X微秒 (STC-Y3&12M)
  124.         _nop_();
  125.         _nop_();
  126.         _nop_();
  127.         _nop_();
  128.         _nop_();
  129.         _nop_();

  130. }

  131. U8 DS1302_RXD() {        //DS1302读1字节
  132.         U8 i = 1, dat = 0;
  133.         do {
  134.                 DS1302_SCLK = 0;
  135.                 DS1302_Delay();
  136.                 if(DS1302_IO) dat |= i;
  137.                 DS1302_SCLK = 1;
  138.                 DS1302_Delay();
  139.                 i <<= 1;
  140.         } while (i);
  141.         return dat;
  142. }

  143. void DS1302_TXD(U8 dat) {        //DS1302写1字节
  144.         U8 i = 1;
  145.         do {
  146.                 DS1302_SCLK = 0;
  147.                 DS1302_Delay();
  148.                 DS1302_IO = dat & i;
  149.                 DS1302_SCLK = 1;
  150.                 DS1302_Delay();
  151.                 i <<= 1;
  152.         } while (i);
  153. }

  154. U8 DS1302_Read(U8 addr) {        //DS1302读地址
  155.         U8 dat;
  156.         DS1302_RST = 0;
  157.         DS1302_Delay();
  158.         DS1302_SCLK = 0;
  159.         DS1302_Delay();
  160.         DS1302_RST = 1;
  161.         DS1302_Delay();
  162.         DS1302_TXD(addr);
  163.         dat = DS1302_RXD();
  164.         DS1302_SCLK = 1;
  165.         DS1302_RST = 0;
  166.         return dat;
  167. }

  168. void DS1302_Write(U8 addr,U8 dat) {                //DS1302写地址
  169.         DS1302_RST = 0;
  170.         DS1302_Delay();
  171.         DS1302_SCLK = 0;
  172.         DS1302_Delay();
  173.         DS1302_RST = 1;
  174.         DS1302_Delay();
  175.         DS1302_TXD(addr);
  176.         DS1302_TXD(dat);
  177.         DS1302_SCLK = 1;
  178.         DS1302_RST = 0;
  179. }

  180. void DS1302(U8 *p) {                        //DS1302读时间 (自动转换BCD码)
  181.         U8 addr = 0x81,n = 7;
  182.         while(n--) {
  183.                 *p++ = bcd2dec(DS1302_Read(addr));
  184.                 addr += 2;
  185.         }

  186. }

  187. void DS1302_Set(U8 *p) {                //DS1302设置时间 (自动转换BCD码)       
  188.         U8 addr = 0x80, n = 7;
  189.         DS1302_Write(0x8e, 0x00);   //关写保护
  190.         while (n--) {
  191.                 DS1302_Write(addr, dec2bcd(*p++));
  192.                 addr += 2;
  193.         }
  194.         DS1302_Write(0x8e, 0x80);        //开写保护
  195. }

  196. void DS1302_Init() {        //DS1302初始化
  197.         DS1302_RST = 0;
  198.         DS1302_SCLK = 0;
  199.         DS1302_Write(0x8e, 0x00);   //允许写操作
  200.         DS1302_Write(0x90, 0xa6);   //一个二极管+4K电阻充电
  201.         DS1302_Write(0x8e, 0x80);   //写保护
  202. }
  203.                                                           
  204. bit DS1302_now_check(U8* ds1302_now) {                //DS1302时间合法校验
  205.         union ds1302_now* now = ds1302_now;
  206.         if (now->now.year > 99) {
  207.                 return 0;
  208.         }else if (now->now.month > 12) {
  209.                 return 0;
  210.         }else if (now->now.day > MonthTable[is_leap_year(2000+now->now.year)][now->now.month-1]) {
  211.                 return 0;
  212.         }else if (now->now.hour > 23) {
  213.                 return 0;
  214.         }else if (now->now.min > 59) {
  215.                 return 0;
  216.         }else if (now->now.sec > 59) {                         
  217.                 return 0;
  218.         }
  219.         return 1;
  220. }



  221. void main(){
  222. union ds1302_now now;
  223.         P3 = 0xFF;
  224.         DS1302_Init();
  225.         if(!KEY){        //2020年7月27日星期一 16时10分0秒 (修改成当前日期时间)
  226.                 now.now.year=20;
  227.                 now.now.month=7;
  228.                 now.now.day=27;
  229.                 now.now.hour=16;
  230.                 now.now.min=10;
  231.                 now.now.sec=0;
  232.                 now.now.week=2;
  233.                 DS1302_Set(&now.dat);
  234.         }
  235.         while (1){
  236.                 WDT_CONTR = 0x37;
  237.                 delay1s();
  238.                 DS1302(&now.dat);
  239.                 if (DS1302_now_check(&now.dat)) {
  240.                         TXD_Text(now2text(now.dat));
  241.                 }
  242.                 else {
  243.                         TXD_Text("DS1302 Time Error!");
  244.                 }
  245.                 TXD_Text("\r\n");

  246.         }
  247. }

复制代码

相关帖子

这个小可爱很神秘,什么都没留下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则