找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机万年历 LCD12864串行模式显示,DS1302读取时间年月份

[复制链接]
ID:234206 发表于 2019-6-28 18:01 | 显示全部楼层 |阅读模式
  1. /***************************************************************
  2. 系统名称:电子万年历
  3. 功能描述:LCD12864串行模式显示,DS1302读取时间年月份,
  4. 18B20 读取温度
  5. ****************************************************************/
  6. #include <reg51.h>
  7. #include <intrins.h>
  8. #include <stdio.h>
  9. #define uchar unsigned char
  10. #define uint unsigned int
  11. /*------------LCD12864相关声明-----------------------------*/
  12. #define com 0
  13. #define dat 1
  14. sbit cs =P1^6;
  15. sbit sid=P1^4;
  16. sbit sck=P1^2;
  17. uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.
  18. uchar code TAB2[]={"20 年 月 日"}; //第二行
  19. uchar code TAB3[]={"星期 : : "}; //第三行
  20. uchar code TAB4[]={"室温: ℃"}; //第四行
  21. /*----------------------DS1302相关声明-------------------------*/
  22. char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.
  23.                   0x18,0x06,0x06,0x08}; //日:月:星期:年.
  24. uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符.
  25. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/
  26. sbit T_IO=P2^5; /* 实时时钟的数据线*/
  27. sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/
  28. uchar bdata datbyte;
  29. sbit datbyte0=datbyte^0;
  30. sbit datbyte7=datbyte^7;
  31. /*--------------18B20相关声明-------------------------------*/
  32. uchar dis1[16];
  33. sbit DQ=P1^0; /*DS18B20温度检测*/
  34. /*----------键盘相关声明-------------------------------------*/
  35. sbit key=P3^2; //功能键
  36. sbit key1=P3^3; //只有加1键
  37. uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志.
  38. /*--------------以下为LCD12864相关函数--------------------------*/
  39. /**************************************************************
  40. 函数名称:void delay1ms(uint x)
  41. 函数功能: 延时1MS
  42. ***************************************************************/
  43. void delay1ms(uint x)
  44. {
  45.     uint i,j;
  46.     for(i=0;i<x;i++)
  47.        for(j=0;j<120;j++);
  48. }
  49. /**************************************************************
  50. 函数名称:void w_12864byte(uchar byte)
  51. 函数功能: 写字节
  52. **************************************************************/
  53. void w_12864byte(uchar byte)
  54. {
  55.    uchar i;
  56.    for(i=0;i<8;i++)
  57.    {
  58.        sck=0;
  59.        byte<<=1;
  60.        sid=CY;
  61.        sck=1;
  62.    }
  63. }
  64. /**************************************************************
  65. 函数名称:uchar r_12864byte(void)
  66. 函数功能: 读字节
  67. ***************************************************************/
  68. uchar r_12864byte(void)
  69. {
  70.       uchar i,temp1,temp2;
  71.       temp1 = 0;
  72.       temp2 = 0;
  73.       for(i=0;i<8;i++)
  74.       {
  75.            temp1=temp1<<1;
  76.            sck = 0;
  77.            sck = 1;
  78.            sck = 0;
  79.            if(sid)
  80.                temp1++;
  81.       }
  82.       for(i=0;i<8;i++)
  83.       {
  84.            temp2=temp2<<1;
  85.            sck = 0;
  86.            sck = 1;
  87.            sck = 0;
  88.            if(sid)
  89.                       temp2++;
  90.       }
  91.       return ((0xf0&temp1)+(0x0f&temp2));
  92. }
  93. /**************************************************************
  94. 函数名称:void c_12864busy( void )
  95. 函数功能: 检测忙函数
  96. **************************************************************/
  97. void c_12864busy( void )
  98. {
  99.     do
  100.        w_12864byte(0xfc); //11111,RW(1),RS(0),0
  101.     while(0x80&r_12864byte());
  102. }
  103. /**************************************************************
  104. 函数名称:void w_12864(bit dat_com,uchar byt)
  105. 函数功能: 写入函数
  106. ***************************************************************/
  107. void w_12864(bit dat_com,uchar byt)
  108. {
  109.       uchar temp;
  110.       if(dat_com==0) //为零,写入指令
  111.           temp=0xf8; //11111,RS(0),RW(0),0
  112.       else //否则,写入数据
  113.           temp=0xfa; //11111,RS(1),RW(0),0
  114.       cs=1;
  115.       c_12864busy();
  116.       w_12864byte(temp);
  117.       w_12864byte(byt&0xf0); //写入高四位
  118.       w_12864byte(byt<<4); //写入低四位
  119.       cs=0;
  120. }
  121. /**************************************************************
  122. 函数名称:void init_12864(void)
  123. 函数功能:初始化12864
  124. ***************************************************************/
  125. void init_12864(void)
  126. {
  127.      w_12864(com,0x30); //基本指令功能.
  128.      w_12864(com,0x0c); //显示打开,关光标,反白关.
  129.      w_12864(com,0x01); //清屏指令.
  130.      w_12864(com,0x06); //AC自动加一
  131. }
  132. /*----------------以下为DS1302相关函数-------------------------*/
  133. /**************************************************************
  134. 函数名称:void w_1302byte(uchar date)
  135. 函数功能:写一个字节(上升沿)
  136. ***************************************************************/
  137. void w_1302byte(uchar date)
  138. {
  139.      uchar i;
  140.      datbyte=date;
  141.      for(i=0;i<8;i++)
  142.      {
  143.          T_IO=datbyte0; //写最低位
  144.          T_CLK=0;
  145.          T_CLK=1;
  146.          datbyte>>=1;
  147.      }
  148. }
  149. /**************************************************************
  150. 函数名称:uchar r_1302byte(void)
  151. 函数功能:读一个字节(下降沿)
  152. ***************************************************************/
  153. uchar r_1302byte(void)
  154. {
  155.      uchar i;
  156.      datbyte=0;
  157.      for(i=0;i<8;i++)
  158.      {
  159.          datbyte7=T_IO; //读最低位
  160.          T_CLK=1;
  161.          T_CLK=0;
  162.          datbyte>>=1;
  163.      }
  164.      return(datbyte);
  165. }
  166. /***************************************************************
  167. 函数名称:void write_1302(uchar addr,uchar date)
  168. 函数功能: 指定位置写数据
  169. ****************************************************************/
  170. void write_1302(uchar addr,uchar date)
  171. {
  172.      T_RST=0;
  173.      T_CLK=0;
  174.      T_RST=1;
  175.      w_1302byte(addr);
  176.      w_1302byte(date);
  177.      T_CLK=0;
  178.      T_RST=0;
  179. }
  180. /**************************************************************
  181. 函数名称:uchar read_1302(uchar addr)
  182. 函数功能: 指定位置读数据
  183. ****************************************************************/
  184. uchar read_1302(uchar addr)
  185. {
  186.       uchar dat1,dat2,temp;
  187.       T_RST=0;
  188.       T_CLK=0;
  189.       T_RST=1;
  190.       w_1302byte(addr);
  191.       temp=r_1302byte();
  192.       T_RST=0;
  193.       T_CLK=0;
  194.       dat1=temp/16;
  195.       dat2=temp%16;
  196.       temp=dat1*10+dat2;
  197.       return(temp);
  198. }
  199. /***************************************************************
  200. 函数名称:void init_1302(void)
  201. 函数功能: 初始化
  202. *****************************************************************/
  203. void init_1302(void)
  204. {
  205.      uchar i;
  206.      uchar addr=0x80;
  207.      write_1302(0x8e,0x00);
  208.      for(i=0;i<7;i++)
  209.      {
  210.          write_1302(addr,TAB_1302[i]);
  211.          addr+=2;
  212.      }
  213.      write_1302(0x8e,0x80);
  214. }
  215. /****************************************************************
  216. 函数名称:void get_1302(void)
  217. 功能说明:读取DS1302时钟信息.
  218. *****************************************************************/
  219. void get_1302(void)
  220. {
  221.      uchar i,addr=0x81;
  222.      for(i=0;i<7;i++)
  223.      {
  224.           TAB_1302[i]=read_1302(addr);
  225.           addr+=2;
  226.      }
  227. }
  228. /*---------------以下为18B20相关函数-----------------------------*/
  229. /******************************************************************
  230. 函数名称:void delay (uint x)
  231. 功能说明:若机器周期为1us,则本延时程序为延时 4*x(us)
  232. ******************************************************************/
  233. void delay (uint x) //本板延时8us
  234. {
  235.      while (--x);
  236. }

  237. /*****************************************************************
  238. 函数名称:uchar bus_rest(void)
  239. 功能说明:产生单总线系统信号的总线复位信号,并返回
  240. 总线上是否存在单总线器件信息
  241. ******************************************************************/
  242. uchar bus_rest(void)
  243. {
  244.      uchar presence;
  245.      DQ=0; //将DQ信号线拉低
  246.      delay(29); //持续48US
  247.      DQ=1; //释放总线
  248.      delay(3); //等待从设备将总线拉低
  249.      presence=DQ; //保存当前总线状态
  250.      delay(25); //等待总线初始化过程结束
  251.      return presence;//返回是否有从设备将总线拉低

  252. }

  253. /****************************************************************
  254. 函数名称:uchar r_1820BYTE(void)
  255. 功能说明:向单总线读取一个数据字节
  256. *****************************************************************/
  257. uchar r_1820BYTE(void)
  258. {
  259.       uchar i=0;
  260.       uchar date = 0;
  261.       for (i=8;i>0;i--)
  262.       {
  263.           DQ = 0; // 将DQ信号线拉低启动读时隙
  264.           DQ=1;// 释放总线,等待从机动车辆返回数据位
  265.           delay(1); //越接近15us越好; 准备采样总线上的信号
  266.           date>>=1 ;
  267.           if (DQ)
  268.                date=date|0x80;
  269.           delay(6);
  270.        }
  271.        return(date);
  272. }

  273. /*****************************************************************
  274. 函数名称:void w_1280Byte(uchar bytevalue)
  275. 功能说明:向单总线写一个数据字节
  276. ******************************************************************/
  277. void w_1280Byte(uchar bytevalue)
  278. {
  279.      uchar i;
  280.      for(i=0;i<8;i++)
  281.      {
  282.          DQ=0; // 将DQ信号线拉低启动读时隙
  283.          DQ=bytevalue&0x01; //
  284.          delay(5);//等待写时隙结束
  285.          DQ=1; //释放
  286.          bytevalue>>=1;
  287.      }
  288.      delay(5); ////等待写时隙结束
  289. }
  290. /*****************************************************************
  291. 函数名称:uint read_T(void)
  292. 功能说明:读取1820温度
  293. *******************************************************************/
  294. uint read_T(void)
  295. {
  296.      uchar a=0;
  297.      uchar b=0;
  298.      uint t=0;
  299.      bus_rest();
  300.      w_1280Byte(0xCC); // 跳过读序号列号的操作 ;
  301.      w_1280Byte(0x44); // 启动温度转换,模数转化;
  302.      bus_rest();
  303.      w_1280Byte(0xCC); //跳过读序号列号的操作 ;
  304.      w_1280Byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 ;
  305.      a=r_1820BYTE();// 低8位
  306.      b=r_1820BYTE();// 高8位
  307.      t=(b*256)+a;
  308.      return(t);
  309. }
  310. /**************************************************************
  311. 函数名称:void show_T(uint temp)
  312. 函数功能:显示温度
  313. **************************************************************/
  314. void show_T(uint temp)
  315. {
  316.      int i;
  317.      float ftemp;
  318.      ftemp = temp* 0.0625;
  319.      sprintf(dis1,"%f",ftemp);//把温度值写入数组内存
  320.      w_12864(com,0x98+3);
  321.      for(i=0;i<5;i++)
  322.      w_12864(dat,dis1[i]); //写入温度
  323. }
  324. /*---------------以下为显示相关函数--------------------------*/
  325. /******************************
  326. 函数名称: void fenli(uchar x,uchar y,uchar val)
  327. 功能描述: 指定位置写入数据
  328. ********************************/
  329. void fenli(uchar x,uchar y,uchar val)
  330. {
  331.      uchar ge,shi,addr,i=0;
  332.      if(val==5)//这里把星期数字显示的转换为中文
  333.      {
  334.            w_12864(com,0x88+2);
  335.            for(i=0;i<2;i++)                           //一个汉字写两次
  336.            {
  337.                          if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);
  338.                  if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]); //
  339.                  if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]); //!!??星期三显示没规律,不知咋回事.
  340.                  if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);
  341.                  if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);
  342.                  if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);
  343.                  if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);
  344.            }
  345.      }
  346.      else
  347.      {
  348.             shi=TAB_1302[val]/10;//分离十位
  349.             ge=TAB_1302[val]%10;
  350.             if(x==1)x=0x80;
  351.             if(x==2)x=0x90;
  352.             if(x==3)x=0x88;
  353.             if(x==4)x=0x98;
  354.             addr=x+y;
  355.             w_12864(com,addr);//指定位置
  356.             w_12864(dat,0x30+shi);//写入
  357.             w_12864(dat,0x30+ge);
  358.      }
  359. }
  360. /*************************************************************
  361. 函数名称:void display(void)
  362. 功能描述: 显示函数
  363. **************************************************************/
  364. void display(void)
  365. {
  366.         get_1302(); //读1302
  367.         fenli(3,7,0); //读秒
  368.         fenli(3,5,1); //读分
  369.         fenli(3,3,2); //读时
  370.         fenli(2,5,3); //读日
  371.         fenli(2,3,4); //读月
  372.         fenli(3,2,5); //读星期
  373.         fenli(2,1,6); //读年
  374. }
  375. /*---------------按键处理相关函数--------------------------*/
  376. /************************************************************
  377. 函数名称:void scanner()
  378. 功能描述: 按键函数
  379. *************************************************************/
  380. void scanner()
  381. {
  382.       uchar i,j;
  383.       if(!key) //功能键按下
  384.       {
  385.            delay1ms(500); //延时500MS
  386.            if(!key) //还按下,退出时间调整
  387.            {
  388.                keyflag=0; //标志位为0
  389.                sum=0; //清0
  390.                w_12864(com,0x0c);//清闪烁
  391.                for(i=0;i<7;i++)//十进制转十六进制
  392.                {
  393.                      j=TAB_1302[i]/10;
  394.                      TAB_1302[i]=TAB_1302[i]%10;
  395.                      TAB_1302[i]=TAB_1302[i]+16*j;
  396.                }
  397.                init_1302(); //写入1302
  398.                while(!key); //等待释放
  399.                delay1ms(10); //延时消抖
  400.            }
  401.            else //500MS内放开
  402.            {
  403.                keyflag=1; //标志为1,进行时间调整
  404.                sum++; //功能键加1
  405.                if(sum==8)
  406.                    sum=0;
  407.                switch(sum)
  408.                {
  409.                      case 1: //
  410.                      {
  411.                              w_12864(com,0x98+7);
  412.                              w_12864(com,0x0f);
  413.                              break;
  414.                      }
  415.                      case 2: //为2,年闪烁
  416.                              w_12864(com,0x90+1);
  417.                              break;
  418.                      case 3: //月闪烁
  419.                              w_12864(com,0x90+3);
  420.                              break;
  421.                      case 4: //日闪烁
  422.                              w_12864(com,0x90+5);
  423.                              break;
  424.                      case 5: //星期闪烁
  425.                              w_12864(com,0x88+2);
  426.                              break;
  427.                      case 6: //分闪烁
  428.                              w_12864(com,0x88+5);
  429.                              break;
  430.                      case 7: //时闪烁
  431.                              w_12864(com,0x88+3);
  432.                              break;
  433.                }
  434.          }
  435.      }
  436.      if(sum) //功能键按下
  437.      {
  438.           if(!key1)
  439.           {
  440.                delay1ms(10);
  441.                if(!key1)
  442.                {
  443.                        while(!key1);//等待加1键释放
  444.                        delay1ms(10);
  445.                        if(sum==1)
  446.                        { //备用
  447.                        }
  448.                        if(sum==2)
  449.                        {
  450.                              TAB_1302[6]++;
  451.                              if(TAB_1302[6]==100)
  452.                              TAB_1302[6]=0;
  453.                              fenli(2,1,6);
  454.                              w_12864(com,0x90+1);//闪烁归位
  455.                        }
  456.                        if(sum==3)
  457.                        {
  458.                             TAB_1302[4]++;
  459.                             if(TAB_1302[4]==13)
  460.                                  TAB_1302[4]=1;
  461.                             fenli(2,3,4);
  462.                             w_12864(com,0x90+3);
  463.                        }
  464.                        if(sum==4)
  465.                        {
  466.                             TAB_1302[3]++;
  467.                             if(TAB_1302[3]==32)
  468.                                  TAB_1302[3]=1;
  469.                             fenli(2,5,3);
  470.                             w_12864(com,0x90+5);
  471.                        }
  472.                        if(sum==5)
  473.                        {
  474.                             TAB_1302[5]++;
  475.                             if(TAB_1302[5]==7)
  476.                                 TAB_1302[5]=0;
  477.                             fenli(3,2,5);
  478.                             w_12864(com,0x88+2);
  479.                        }
  480.                        if(sum==6)
  481.                        {
  482.                             TAB_1302[1]++;
  483.                             if(TAB_1302[1]==60)
  484.                                  TAB_1302[1]=0;
  485.                             fenli(3,5,1);
  486.                             w_12864(com,0x88+5);
  487.                        }
  488.                        if(sum==7)
  489.                        {
  490.                             TAB_1302[2]++;
  491.                             if(TAB_1302[2]==24)
  492.                             TAB_1302[2]=0;
  493.                             fenli(3,3,2);
  494.                             w_12864(com,0x88+3);
  495.                        }
  496.                }
  497.          }
  498.     }
  499. }
  500. //=============================================================
  501. void init(void)
  502. {
  503.       uchar i;
  504.       init_12864();
  505.       init_1302();
  506.       while(TAB1[i]!='\0')
  507.       {
  508.            w_12864(dat,TAB1[i]);
  509.            i++;
  510.       }
  511.       i=0;
  512.       w_12864(com,0x90);
  513.       while(TAB2[i]!='\0')
  514.       {
  515.            w_12864(dat,TAB2[i]);
  516.            i++;
  517.       }
  518.       i=0;
  519.       w_12864(com,0x88);
  520.       while(TAB3[i]!='\0')
  521.       {
  522.            w_12864(dat,TAB3[i]);
  523.            i++;
  524.       }
  525.       i=0;
  526.       w_12864(com,0x98);
  527.       while(TAB4[i]!='\0')
  528.       {
  529.            w_12864(dat,TAB4[i]);
  530.            i++;
  531.       }
  532. }
  533. /*************************************************************
  534. 函数名称:主函数
  535. 函数功能:
  536. **************************************************************/
  537. main()
  538. {
  539.        init();
  540.        while(1)
  541.        {
  542.             scanner(); //检测键盘
  543.             if(!keyflag) //标志为0
  544.             {
  545.                    display(); //调用显示
  546.                    show_T(read_T()); //显示温度
  547.                    delay1ms(500);
  548.             }
  549.        }
  550. }
复制代码

万年历.zip

50.78 KB, 下载次数: 93, 下载积分: 黑币 -5

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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