分享

发个DS3231的简易时钟,1602液晶显示、串口修改时间

 开启美好每一天 2015-11-16
     来极客工坊学习一个多月了,收获很大。以前学过单片机,加上论坛里的各位前辈无私的奉献,现在学arduino很快上手,十分感谢极客工坊这个大家庭。
    最近买了一块DS3231时钟模块,测试了3天,发现走时非常准确,一秒不差。 以前学单片机时用ds1302做过一个简易时钟,一天的误差在5秒左右,需要经常去校时。来上个照片


DS1302 侧面


DS1302桌面时钟

      在论坛里搜索了一下关于DS3231的应用,发现不是很多,就打算将原来ds1302的程序移植到arduino上,但是将时钟芯片换成DS3231。因为DS3231走时比较准确,不需要经常校时,打算程序里去除用按键修改时间的程序部分。改为用串口发送字符串来修改时间。另外,我个人认为桌面时钟就是看时间用的,加上闹钟的功能并不实用。所以程序里也没有闹钟的功能。

简单介绍一下DS3231:
1、I2C接口;
2、实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿;
3、两个日历闹钟;
4、内部集成了一个数字温度传感器
采用4线接法,顺便盗个图

141656ptfhphfbpyl77hbc[1].jpg

UNO  与  1602液晶连接
6      ->     D7
7      ->     D6
8      ->     D5
9      ->     D4
10     ->    EN
11     ->    RW
12     ->    RS


顺便盗个图

160754e8h6wp6wplhzmwma.png

UNO  与  DS3231连接
A4     ->     SDA
A5     ->     SCL

****************************************      程序部分    ********************************************

ARDUINO 代码
  1. #include <DS3231.h>
  2. #include <Wire.h>

  3. DS3231 Clock;
  4. bool Century=false;
  5. bool h12;
  6. bool PM;
  7. byte ADay, AHour, AMinute, ASecond, ABits;
  8. bool ADy, A12h, Apm;

  9. int year, month, date, DoW,week , hour, minute, second,temperature;

  10. String comdata = "";
  11. int numdata[7] = {0},  mark = 0;
  12. /*1602液晶与UNO连接引脚
  13. 6 -> D7
  14. 7 -> D6
  15. 8 -> D5
  16. 9 -> D4
  17. */

  18. int LCD1602_RS=12;   
  19. int LCD1602_RW=11;   
  20. int LCD1602_EN=10;   
  21. int DB[] = { 6, 7, 8, 9};

  22. char dis1[16]={0},dis2[16]={0};

  23. char self_char[]={                               //1602液晶自定义符号   
  24.         0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, //年
  25.         0x0f,0x09,0x0f,0x09,0x0f,0x09,0x13,0x01, //月
  26.         0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00, //日
  27.         0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //温度标志— —摄氏度
  28.         0x00,0x04,0x0E,0x1F,0x0E,0x04,0x00,0x00, //符号◆
  29.         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, //全开
  30.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //
  31.         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00         //
  32.                                            };

  33. void LCD_Command_Write(int command)             //写指令
  34. {
  35. int i,temp;
  36. digitalWrite( LCD1602_RS,LOW);
  37. digitalWrite( LCD1602_RW,LOW);
  38. digitalWrite( LCD1602_EN,LOW);

  39. temp=command & 0xf0;
  40. for (i=DB[0]; i <= 9; i++)
  41. {
  42.    digitalWrite(i,temp & 0x80);
  43.    temp <<= 1;
  44. }

  45. digitalWrite( LCD1602_EN,HIGH);
  46. delayMicroseconds(1);
  47. digitalWrite( LCD1602_EN,LOW);

  48. temp=(command & 0x0f)<<4;
  49. for (i=DB[0]; i <= 9; i++)
  50. {
  51.    digitalWrite(i,temp & 0x80);
  52.    temp <<= 1;
  53. }

  54. digitalWrite( LCD1602_EN,HIGH);
  55. delayMicroseconds(1);
  56. digitalWrite( LCD1602_EN,LOW);
  57. }

  58. void LCD_Data_Write(int dat)                //写数据
  59. {
  60. int i=0,temp;
  61. digitalWrite( LCD1602_RS,HIGH);
  62. digitalWrite( LCD1602_RW,LOW);
  63. digitalWrite( LCD1602_EN,LOW);

  64. temp=dat & 0xf0;
  65. for (i=DB[0]; i <= 9; i++)
  66. {
  67.    digitalWrite(i,temp & 0x80);
  68.    temp <<= 1;
  69. }

  70. digitalWrite( LCD1602_EN,HIGH);
  71. delayMicroseconds(1);
  72. digitalWrite( LCD1602_EN,LOW);

  73. temp=(dat & 0x0f)<<4;
  74. for (i=DB[0]; i <= 9; i++)
  75. {
  76.    digitalWrite(i,temp & 0x80);
  77.    temp <<= 1;
  78. }

  79. digitalWrite( LCD1602_EN,HIGH);
  80. delayMicroseconds(1);
  81. digitalWrite( LCD1602_EN,LOW);
  82. }

  83. void LCD_SET_XY( int x, int y )//指定坐标,x为列,0~15,y为行,0为第一行,1为第二行。
  84. {
  85.   int address;
  86.   if (y ==0)    address = 0x80 + x;
  87.   else          address = 0xC0 + x;
  88.   LCD_Command_Write(address);
  89. }

  90. void LCD_Write_Char( int x,int y,int dat)  //指定位置一个字符
  91. {
  92.   LCD_SET_XY( x, y );
  93.   LCD_Data_Write(dat);
  94. }

  95. void LCD_Write_String(int X,int Y,char *s)  //指定位置字符串
  96. {
  97.     LCD_SET_XY( X, Y );    //设置地址
  98.     while (*s)             //写字符串
  99.     {
  100.       LCD_Data_Write(*s);   
  101.       s ++;
  102.     }
  103. }

  104. void setup (void)
  105. {
  106.   Serial.begin(9600);
  107.   int i = 0;
  108.   for (i=6; i <= 12; i++)
  109.    {
  110.      pinMode(i,OUTPUT);
  111.    }

  112.   delay(100);
  113.   LCD_Command_Write(0x28);//4线 2行 5x7
  114.   delay(50);
  115.   LCD_Command_Write(0x06);
  116.   delay(50);
  117.   LCD_Command_Write(0x0c);
  118.   delay(50);
  119.   LCD_Command_Write(0x80);
  120.   delay(50);
  121.   LCD_Command_Write(0x01);
  122.   delay(50);

  123.     diy();              //开机问候
  124.   //Wire.begin();
  125.   Serial.println("set_time :");
  126.   Serial.println("year mouth day week hour minute second");
  127.   Serial.println();
  128.   Serial.println("week : 1 -> Sunday; 2 -> Monday; 3 -> Tuesday:  ....7 -> Saturday");
  129.   Serial.println();
  130.   Serial.println("for example :2014-5-20 Tue 0:33:30  ");
  131.   Serial.println("set_time :");
  132.   Serial.println("14 5 20 3 0 33 30");
  133.   Serial.println();
  134. }


  135. void diy()
  136. {
  137.      char a;
  138.   LCD_Command_Write(0x40);   
  139.      for(a=0;a<64;a++)
  140.         {
  141.           LCD_Data_Write(self_char[a]);
  142.           delay(1);
  143.         }
  144.     delay(50);
  145.   LCD_Write_String(0,0," Digital Clock  ");
  146.   LCD_Write_String(0,1," Geek-workshop  ");
  147.   delay(2000);
  148.   LCD_Command_Write(0x01);  
  149.   delay(10);
  150.   LCD_Write_String(0,0,"Today is new day");
  151.   LCD_Write_String(0,1,"Dream come true!");
  152.   delay(2000);
  153.   LCD_Command_Write(0x01);
  154. delay(10);           
  155. }

  156. void ReadDS3231()          //读取DS3231 参数
  157. {
  158.   Wire.begin();

  159.   second=Clock.getSecond();
  160.   minute=Clock.getMinute();
  161.   hour=Clock.getHour(h12,PM);
  162.   week=Clock.getDoW();   
  163.   date=Clock.getDate();
  164.   month=Clock.getMonth(Century);
  165.   year=Clock.getYear();
  166.   temperature=Clock.getTemperature();

  167. }

  168. void get_dis()          //1602液晶上每一位上显示的数据
  169. {
  170.   ReadDS3231();
  171.   dis1[0]='2';
  172.   dis1[1]='0';
  173.   dis1[2]=0x30+year/10;
  174.   dis1[3]=0x30+year%10;
  175.   dis1[4]=0;
  176.   dis1[5]=0x30+month/10;
  177.   dis1[6]=0x30+month%10;
  178.   dis1[7]=1;
  179.   dis1[8]=0x30+date/10;
  180.   dis1[9]=0x30+date%10;
  181.   dis1[10]=2;
  182.   dis1[11]=' ';
  183.   dis1[12]=' ';
  184.   switch(week)
  185.   {
  186.         case 2: {
  187.                           dis1[13]='M';
  188.                           dis1[14]='o';
  189.                           dis1[15]='n';
  190.                         }
  191.                         break;
  192.         case 3: {
  193.                           dis1[13]='T';
  194.                           dis1[14]='u';
  195.                           dis1[15]='e';
  196.                         }
  197.                         break;
  198.         case 4: {
  199.                           dis1[13]='W';
  200.                           dis1[14]='e';
  201.                           dis1[15]='d';
  202.                         }
  203.                         break;
  204.         case 5: {
  205.                           dis1[13]='T';
  206.                           dis1[14]='h';
  207.                           dis1[15]='u';
  208.                         }
  209.                         break;
  210.         case 6: {
  211.                           dis1[13]='F';
  212.                           dis1[14]='r';
  213.                           dis1[15]='i';
  214.                         }
  215.                         break;
  216.         case 7: {
  217.                           dis1[13]='S';
  218.                           dis1[14]='a';
  219.                           dis1[15]='t';
  220.                         }
  221.                         break;
  222.         case 1: {
  223.                           dis1[13]='S';
  224.                           dis1[14]='u';
  225.                           dis1[15]='n';
  226.                         }
  227.                         break;
  228.   }
  229.   dis2[0]=' ';
  230.   dis2[1]=0x30+hour/10;
  231.   dis2[2]=0x30+hour%10;
  232.   dis2[3]=':';
  233.   dis2[4]=0x30+minute/10;
  234.   dis2[5]=0x30+minute%10;
  235.   dis2[6]=':';
  236.   dis2[7]=0x30+second/10;
  237.   dis2[8]=0x30+second%10;
  238.   dis2[9]=' ';

  239.         dis2[10]=' ';
  240.   dis2[11]=0x30+temperature/10;
  241.   dis2[12]=0x30+temperature%10;
  242.   dis2[13]='.';
  243.   dis2[14]=0x30+0;
  244.   dis2[15]=3;
  245. }
  246. void play()                  //1602显示完整时间
  247. {
  248.        get_dis();

  249.             int k;      
  250.             LCD_SET_XY( 0,0);
  251.             for(k=0;k<16;k++)
  252.             LCD_Data_Write(dis1[k]);
  253.             LCD_SET_XY( 0,1);
  254.             for(k=0;k<16;k++)
  255.             LCD_Data_Write(dis2[k]);

  256. }

  257. void set_time()               //DS3231设置时间
  258. {
  259. Wire.begin();
  260. Clock.setSecond(numdata[6]); //秒
  261. Clock.setMinute(numdata[5]); //分
  262. Clock.setHour(numdata[4]);   //时
  263. Clock.setDoW(numdata[3]);    //周
  264. Clock.setDate(numdata[2]);   //日
  265. Clock.setMonth(numdata[1]);  //月
  266. Clock.setYear(numdata[0]);   //年
  267. }

  268. void loop (void)
  269. {
  270.      int j = 0;
  271.   while (Serial.available() > 0)    //检测串口是否有数据
  272.   {
  273.     comdata += char(Serial.read());
  274.     delay(2);
  275.     mark = 1;
  276.      play();
  277.   }

  278.   if(mark == 1)  
  279.   {
  280.     Serial.println(comdata);             //串口打印检测到的数据
  281.     for(int i = 0; i < comdata.length() ; i++)
  282.     {
  283.       if(comdata[i] == ' ')
  284.       {
  285.         j++;
  286.       }
  287.       else
  288.       {
  289.         numdata[j] = numdata[j] * 10 + (comdata[i] - '0');
  290.       }
  291.     }

  292.     comdata = String("");
  293.    Serial.print("set_time... ");
  294.     set_time();
  295.     Serial.println(" OK ");
  296.     for(int i = 0; i < 7; i++)
  297.     {
  298.       numdata[i] = 0;
  299.     }
  300.     mark = 0;
  301.   }
  302.     play();
  303. }



其中串口字符串转换部分参考 http://www./thread-260-1-1.html

****************************************      串口校时    ********************************************

打开arduino 串口监视器

QQ图片20140520123454.jpg

输入要设定日期以及时间
格式为(年+空格+月+空格+日+空格+星期+空格+时+空格+分+空格+秒)

设置中星期:01对应星期天;02对应星期一;03对应星期二;……07对应星期六

例如:现在是 2014年5月20日 星期二 13:35:00
那么在串口数据发送栏中输入   : 14 05 20 03 13 35 00

20124353.jpg

********************************       工作照(请无视凌乱的杜邦线)     ********************************

下面的单片机开发板只是为了给1602液晶引线用,方便接线而已

20140520_110027.jpg

1.jpg

2.jpg

工作中。。。。。

20140520_110402.jpg

1602液晶显示的年月日  是不是很有感觉!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多