找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3067|回复: 2
打印 上一主题 下一主题
收起左侧

51单片机5110液晶显示屏实现时间温度串口发送(附Proteus仿真程序)

[复制链接]
跳转到指定楼层
楼主
制作出来的实物图如下:


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

单片机源程序如下:
  1. /**
  2. P2.7置低电平时,开机接入串口,自动进入时间设置界面
  3. 每秒钟自动检测温度一次,并在LCD上显示
  4. 每分钟自动刷新日期、时间、温度,在LCD上显示,并在串口中输出(方便电脑读取)

  5. */


  6. #include <stdio.h>
  7. //#include <AT89X51.H>
  8. #include<reg51.h>
  9. #include"ds1302.h"
  10. #include"temp.h"
  11. #include <nokia_5110.h>


  12. //***********************************
  13. #define                delay_time        25767

  14. sbit SETTIME = P2^7;        //为0时,开机进入设置时间界面
  15. uchar TIME[7];
  16. char word2[10];

  17. //毫秒级延时函数
  18. void delay(unsigned int x)
  19. {
  20.         unsigned char i;
  21.         while(x--)
  22.         {
  23.                 for(i = 0;i < 120;i++);
  24.         }
  25. }

  26. char* tempDisplay(int temp)          //lcd显示
  27. {
  28.    
  29.          unsigned char datas[5]; //定义数组
  30.         float tp;
  31.         unsigned char ReturnTemp[9],x;  
  32.         if(temp< 0)                                //当温度值为负数
  33.           {

  34.                 ReturnTemp[0]='-';
  35.                 //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
  36.                 temp=temp-1;
  37.                 temp=~temp;
  38.                 tp=temp;
  39.                 temp=tp*0.0625*100+0.5;        
  40.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  41.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  42.                 //算由?.5,还是在小数点后面。

  43.           }
  44.          else
  45.           {                        
  46. //                  LcdWriteCom(0x80);                //写地址 80表示初始地址
  47. //            LcdWriteData('+');                 //显示正
  48.                 ReturnTemp[0]='+';
  49.                 tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  50.                 //如果温度是正的那么,那么正数的原码就是补码它本身
  51.                 temp=tp*0.0625*100+0.5;        
  52.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  53.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  54.                 //算加上0.5,还是在小数点后面。
  55.         }
  56.         datas[0] = temp / 10000;
  57.         datas[1] = temp % 10000 / 1000;
  58.         datas[2] = temp % 1000 / 100;
  59.         datas[3] = temp % 100 / 10;
  60.         datas[4] = temp % 10;           

  61. //        LcdWriteCom(0x82);                  //写地址 80表示初始地址
  62. //        LcdWriteData('0'+datas[0]); //百位
  63. //        ReturnTemp[1]=datas[0]+48;
  64.         if(datas[0]!=0)
  65.         {
  66.         ReturnTemp[1]=48+datas[0];
  67.         x=1;
  68.         } else {
  69.         x=0;
  70.         }
  71.         //putchar(ReturnTemp[1]);
  72. //        LcdWriteCom(0x83);                 //写地址 80表示初始地址
  73. //        LcdWriteData('0'+datas[1]); //十位
  74.         if(( datas[1])!=0)
  75.         {
  76.         ReturnTemp[1+x]=datas[1]+48;
  77.         x=x+1;
  78.         } else {
  79.                 if(x!=0)
  80.                 {
  81.                         ReturnTemp[1+x]='0';
  82.                         x=x+1;
  83.                 }
  84.         }        

  85. //        LcdWriteCom(0x84);                //写地址 80表示初始地址
  86. //        LcdWriteData('0'+datas[2]); //个位
  87.         ReturnTemp[1+x]='0'+datas[2];
  88. //        putchar(ReturnTemp[1+x]);
  89. //        LcdWriteCom(0x85);                //写地址 80表示初始地址
  90. //        LcdWriteData('.');                 //显示 ‘.’
  91.         ReturnTemp[2+x]='.';

  92. //        LcdWriteCom(0x86);                 //写地址 80表示初始地址
  93. //        LcdWriteData('0'+datas[3]); //显示小数点
  94.         ReturnTemp[3+x]=48+datas[3];
  95. //        putchar(ReturnTemp[3+x]);
  96. //        LcdWriteCom(0x87);                 //写地址 80表示初始地址
  97. //        LcdWriteData('0'+datas[4]); //显示小数点
  98.         ReturnTemp[4+x]=datas[4]+48;
  99.         ReturnTemp[5+x]='C';
  100.         ReturnTemp[6+x]='\0';
  101. //        printf("\n xx %s\n",ReturnTemp);
  102.         return ReturnTemp;

  103. }


  104. //设置日期,格式为: setdate 2015-2-21, 可以省略0
  105. int setdate()
  106. {
  107.         char year[5],month[3],day[3],i,
  108.                  y,m,d;                                                                   //y存放年,m存放月, d存放日
  109.         for(i=0;i<4;i++)        
  110.                  year[i]=word2[i];
  111.                
  112.         for(i=0; i<10; i++)                                                //检查WORD2中字符的合法性,只能有数字或者-
  113.         {
  114.                 if((word2[i]-48)<0 | word2[i]-48>9)
  115.                 {
  116.                         if(word2[i] == '\0')
  117.                                 break;
  118.                         if(word2[i] != '-')
  119.                         {
  120.                                 return 0;
  121.                         }
  122.                 }
  123.         }        

  124.         if(word2[7]!='-' & word2[6] != '-')
  125.         {
  126.                 return 0;
  127.         }

  128.         if(word2[7] == '-')
  129.         {
  130.                 month[0]=word2[5];
  131.                 month[1]=word2[6];
  132.                 m = 1;         //m=1的话,表示月份是2位,否则是1位,节约内存,借变量用一下
  133.         }

  134.         if(word2[6] == '-')
  135.         {
  136.                 month[0] = '0';
  137.                 month[1] = word2[5];
  138.                 m = 0;
  139.         }

  140.         if(word2[9+m]!='\0' & word2[8+m] != '\0')
  141.         {
  142.                 return 0;
  143.         }

  144.         if(word2[9+m] == '\0')                        //处理日期,因为要考虑1位的情况,使情况复杂多了
  145.         {
  146.                 day[0] = word2[7+m];
  147.                 day[1] = word2[8+m];
  148.         }

  149.         if(word2[8+m]=='\0')
  150.         {
  151.                 day[0] = '0';
  152.                 day[1] = word2[7+m];
  153.         }

  154.         year[4]='\0',month[2]='\0',day[2]='\0';
  155.         y = (year[2]-48)*10 + (year[3]-48);
  156.         m = (month[0]-48)*10 + (month[1]-48);
  157.         d = (day[0]-48)*10 + day[1]-48;                 //先获取年月日的值,再判断合法性

  158.         if(year[0] != (2+48) | year[1] != (0+48) |        //这个简单,必须是20XX年
  159.         y > 100 | y < 1 | m > 12 | m <1)                //年与月都简单,日最麻烦
  160.         {
  161.                 return 0;
  162.         }

  163.         if(!(m==1|m==3|m==5|m==7|m==8|m==10|m==12) & (d>=31)) //除了大月外都不能有31号
  164.         {
  165.                 return 0;
  166.         }

  167.         if(d>31)
  168.         {
  169.                 return 0;
  170.         }

  171.         if(m==2 & d>28)
  172.         {
  173.                 if(!(((y%4)==0) & (d==29)))        //2月是很蛋痛的,好在只是100年内
  174.                 {
  175.                         return 0;
  176.                 }
  177.         }

  178.         TIME[6]=(year[2]-48)*16+(year[3]-48);
  179.         TIME[4]=(month[0]-48)*16+(month[1]-48);
  180.         TIME[3]=(day[0]-48)*16+(day[1]-48);

  181.         
  182.         //下面这段把设置的日期写入到DS1302中
  183.         Ds1302Write(0x8E,0X00);                 //禁止写保护,就是关闭写保护功能
  184.         for (i=0; i<7; i++)//写入7个字节的时钟信号:分秒时日月周年
  185.         {
  186.                 Ds1302Write(WRITE_RTC_ADDR[i],TIME[i]);        
  187.         }
  188.         Ds1302Write(0x8E,0x80);                 //打开写保护功能
  189. /*
  190.         putstring(year);
  191.         putstring(month);
  192.         putstring(day);
  193.         putstring("\r\n");
  194. */
  195.         Ds1302ReadTime();
  196.         return 1;
  197. }

  198. //设置时间,格式为settimer 02:22, 不支持省略0
  199. int settime()
  200. {
  201.         char minutes[3],hour[3],i,
  202.                  h,m;                                                                   //h存放小时,m存放分
  203.                                                    
  204.         for(i=0; i<6; i++)                                                //检查WORD2中字符的合法性,只能有数字或者:
  205.         {
  206.                 if((word2[i]-48)<0 | word2[i]-48>9)
  207.                 {
  208.                         if(word2[i] == '\0')
  209.                                 break;
  210.                         if(word2[i] != ':')
  211.                         {
  212.                                 return 0;
  213.                         }
  214.                 }
  215.         }        
  216.         


  217.         if(word2[2]!=':' & word2[1] != ':')
  218.         {
  219.                 return 0;
  220.         }

  221.         if(word2[2] == ':')
  222.         {
  223.                 hour[0]=word2[0];
  224.                 hour[1]=word2[1];
  225.                 m = 1;         //m=1的话,表示小时是2位,=0是1位
  226.         }

  227.         if(word2[1] == ':')
  228.         {
  229.                 hour[0] = '0';
  230.                 hour[1] = word2[0];
  231.                 m = 0;
  232.         }

  233.         if(word2[4+m]!='\0' & word2[3+m] != '\0')
  234.         {
  235.                 return 0;
  236.         }

  237.         if(word2[4+m] == '\0')                        //要考虑小时1位的情况
  238.         {
  239.                 minutes[0] = word2[2+m];
  240.                 minutes[1] = word2[3+m];
  241.         }

  242.         if(word2[3+m]=='\0')
  243.         {
  244.                 minutes[0] = '0';
  245.                 minutes[1] = word2[2+m];
  246.         }


  247.         minutes[2]='\0',hour[2]='\0';
  248.         h = (hour[0]-48)*10 + (hour[1]-48);
  249.         m = (minutes[0]-48)*10 + (minutes[1]-48);


  250.         if(h > 23 | h <= 0 | m > 59 | m < 0)                //这个比日期简单多了
  251.         {
  252.                 return 0;
  253.         }


  254.         Ds1302ReadTime();
  255.         TIME[2]=(hour[0]-48)*16+(hour[1]-48);                 //BCD码
  256.         TIME[1]=(minutes[0]-48)*16+(minutes[1]-48);
  257.         TIME[0]=0;
  258.         Ds1302Write(0x8E,0X00);                 //禁止写保护,就是关闭写保护功能
  259.         for (i=0; i<7; i++)//写入7个字节的时钟信号:分秒时日月周年
  260.         {
  261.                 Ds1302Write(WRITE_RTC_ADDR[i],TIME[i]);        
  262.         }
  263.         Ds1302Write(0x8E,0x80);                 //打开写保护功能
  264.         Ds1302ReadTime();
  265. //        printf("\nThe current time: ");
  266.         return 1;
  267. }        

  268. void main()
  269. {
  270.         char         Secondcheck,           //检查秒有没有改变
  271.                           Mincheck,                    //检查分有没有改变
  272.                         date[11];                           

  273.         SCON = 0x50; //串口方式1,允许接收
  274.         TMOD = 0x20; //定时器1定时方式2
  275.         TCON = 0x40; //设定时器1开始计数
  276.         TH1 = 0xFD;        //11.0592MHz 1200波特率 只有9600能用未找原因
  277.         TL1 = 0xFD;
  278.         TI = 1;
  279.         TR1 = 1; //启动定时器
  280.         printf ("Initing.... \n");
  281.         tempDisplay(Ds18b20ReadTemp());
  282.         LCD_init(); //初始化液晶   
  283.         LCD_clear();
  284.         LCD_write_english_string(0,1," Initing.... ");
  285.         delay(1000);  
  286.         Mincheck=11;        //解决分钟为0时初始化过久的问题
  287.         if(SETTIME==0)
  288.         {
  289.                 for(Mincheck=3;Mincheck>0;Mincheck--)
  290.                 {
  291.                         printf("\nPlease Set Date:");
  292.                         scanf("%s",word2);
  293.                         //printf("%s",word2);
  294.                         if(setdate())
  295.                                 break;
  296.                 }
  297.                 for(Mincheck=3;Mincheck>0;Mincheck--)
  298.                 {
  299.                         printf("\nPlease Set Time:");
  300.                         scanf("%s",word2);
  301.                         //printf("%s\n",word2);
  302.                         if(settime())
  303.                                 break;
  304.                 }
  305.         }
  306.         LCD_clear();//清除LCD
  307.         while(1)
  308.                 {
  309.                         Ds1302ReadTime();//读取时间1302
  310.                                                 
  311.                 delay(500);//多给点时间发送,但是影响秒的同步看来要改定时器发送        
  312.                         
  313.                         
  314.                                        
  315.                         if(Mincheck!=TIME[0])////如果时间秒变化就发送一次串口数据               
  316.                         
  317.                         {
  318.                                 
  319.                                 Mincheck=TIME[0];//让Mincheck等于秒,用于下次发送检测
  320.                                 
  321.                                 date[0]='2',//发送年
  322.                                 date[1]='0',
  323.                                 date[2]=TIME[6]/16+48,//发送年
  324.                                 date[3]=TIME[6]%16+48;
  325.                                 date[4]='-',
  326.                                 date[5]=(TIME[4]/16+48),//发送月
  327.                                 date[6]=(TIME[4]%16+48),
  328.                                 date[7]='-',
  329.                                 date[8]=(TIME[3]/16+48),//发送日
  330.                                 date[9]=TIME[3]%16+48;               
  331.                                 printf("%s",date);//发送以上全部的 date               
  332.                                 
  333.                                 printf("  Time: ");
  334.                                 putchar(TIME[2]/16+48);//发送时
  335.                                 putchar(TIME[2]%16+48);
  336.                                 putchar(':');//发送“ :”
  337.                                 putchar(TIME[1]/16+48);//发送分
  338.                                 putchar(TIME[1]%16+48);
  339.                                 putchar(':');//发送“ :”
  340.                                 putchar(TIME[0]/16+48);//发送秒
  341.                                 putchar(TIME[0]%16+48);

  342.                                 printf("  WD: ");
  343.                                 printf(tempDisplay(Ds18b20ReadTemp()));
  344.                                 putchar('\n');//结束串口开始符号
  345.                                 
  346.                                 
  347.         LCD_write_english_string(25,1," bbjj  ");
  348.                                 LCD_write_english_string(8,0,date);
  349.                                 LCD_write_chinese_string(0,3,12,1,TIME[2]/16,5);//显示时
  350.                                 LCD_write_chinese_string(10,3,12,1,TIME[2]%16,5);
  351.                                 LCD_write_chinese_string(20,3,12,1,11,5);
  352.                                 LCD_write_chinese_string(30,3,12,1,TIME[1]/16,5);//显示分
  353.                                 LCD_write_chinese_string(40,3,12,1,TIME[1]%16,5);
  354.                                 LCD_write_chinese_string(50,3,12,1,11,5);
  355.                                 LCD_write_chinese_string(60,3,12,1,TIME[0]/16,5);//显示秒
  356.                                 LCD_write_chinese_string(70,3,12,1,TIME[0]%16,5);
  357.                                 
  358.                                          
  359.                         }
  360.                         
  361.                           
  362.                         if(Secondcheck!=TIME[0])//如果温度变化就显示一下
  363.                         {
  364.                                 Secondcheck=TIME[0];
  365.                                 LCD_write_english_string(10,5,"WD:");
  366.                                 LCD_write_english_string(30,5,tempDisplay(Ds18b20ReadTemp()));//读取温度显示18B20
  367.                         }
  368.                         
  369.                 }                                                                                                        

  370. }
复制代码

所有资料51hei提供下载:
51单片机&amp;5110液晶显示屏实现时间温度串口发送(附仿真截图).7z (544.03 KB, 下载次数: 60)

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:853104 发表于 2020-12-22 23:36 | 只看该作者
大佬有LCD1602的程序和仿真吗
回复

使用道具 举报

板凳
ID:832201 发表于 2020-12-23 22:33 | 只看该作者
很棒,写的真棒
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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