找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机LCD1602温度计实验 Proteus仿真加源程序

  [复制链接]
跳转到指定楼层
楼主
51单片机LCD1602液晶显示的温度计的仿真原理图(proteus工程文件可到本帖附件下载):



单片机源程序:

  1. //--------------------------------------------------------------------------------------------
  2. //程序名:  LCD_TEMP09-1.c
  3. //程序功能:LCD温度计
  4. //--------------------------------------------------------------------------------------------
  5. #include <reg51.h>   
  6. #include<intrins.h>                             //包含_nop_()函数定义的头文件
  7. sbit RS=P2^5;                                   // 引脚定义  
  8. sbit RW=P2^6;                                                           
  9. sbit EN=P2^7;      
  10. sbit busy=P0^7;                                 // "忙"标志位      
  11. #define LCD P0                                  //命令或数据线
  12. sbit DQ=P2^0;
  13.   
  14. //代码表
  15. unsigned char code TAB1[]={ 0x0c,0x12,0x12,0x0c,
  16.                             0x00,0x00,0x00,0x00,
  17.                           };
  18. //字符表
  19. unsigned char code TAB2[]={"DS18B20  OK"};  
  20. unsigned char code Error[]={"Error!Check!"};     //说明没有检测到DS18B20
  21. unsigned char code digit[10]={"0123456789"};     //定义字符数组显示数字
  22. unsigned char code TEMP[]={"TEMP:"};             //说明显示的是温度
  23. unsigned char fuhao;

  24. //------------------------------------  延时函数  -------------------------------------------

  25. void delay(unsigned int t)                      //延时若干微秒
  26. {
  27.    while(t--);
  28. }

  29. //---------------------------------- 判断液晶显示器是否忙函数 ----------------------------------

  30. CHECK_BF()                                      //判断是否忙碌
  31. {
  32.   do
  33.    {
  34.     LCD=0xff;   
  35.     RS=0;                                       // RS=0,选择指令寄存器
  36.     RW=1;                                       // RW=1,选择读模式
  37.     EN=0;                                       // 执行显示命令
  38.     EN=1;                                       // 允许读/写
  39.    }  
  40.   while(busy);                                  //busy为高电平表示忙,循环等待
  41. }

  42. //--------------------------------------  写命令函数  -----------------------------------

  43. WR_COMM()                                       //写命令
  44. {
  45.   RS=0;                                         // RS=0,选择指令寄存器
  46.   RW=0;                                         // RW=0,选择写模式
  47.   EN=0;                                         // 执行显示命令
  48.   CHECK_BF();                                   // 等待
  49.   EN=1;                                         // E=1,允许读/写LCD
  50. }

  51. //-------------------------------------- 写数据函数 -------------------------------------

  52. WR_DATA()                                       //写数据
  53. {
  54.   RS=1;                                         // RS=1,选择数据寄存器
  55.   RW=0;                                         //准备写入数据
  56.   EN=0;                                         //执行显示命令
  57.   CHECK_BF();                                   //判断液晶模块是否忙
  58.   EN=1;                                         // E=1,允许读/写LCD
  59. }

  60. //--------------------------------------- 初始化函数   ----------------------------------

  61. INIT_LCD()                                       //初始化
  62. {
  63.    unsigned char i=200;
  64.     {
  65.       while(--i);
  66.       LCD=0x01;                                 //清屏并光标复位
  67.       WR_COMM();                                //写入命令
  68.       LCD=0x38;                                 //设置显示模式:8位2行5x7点阵
  69.       WR_COMM();
  70.       LCD=0x0c;                                 //开显示屏
  71.           WR_COMM();
  72.       LCD=0x06;                                 //文字不动,光标自动右移
  73.       WR_COMM();                                //写入命令
  74.     }
  75. }

  76.        
  77. //--------------------------------  显示温度标记字符C函数 ----------------------------

  78. TEMP_BJ()                                       //显示字符C
  79.      {          
  80.            LCD=0xce;                                  //写入显示起始地址                 
  81.        WR_COMM();                                 //写入命令
  82.        LCD=('C' );
  83.            WR_DATA();                                 //送出                        
  84.         }       
  85.       
  86. //----------------------------------- 自定义温度标志符函数 --------------------------------
  87.   STORE_DATA()
  88.     {
  89.        unsigned char i;
  90.            LCD=0x40;                                      // 指定CG RAM起始地址                 
  91.        WR_COMM();                                     //写入命令                  
  92.        for(i=0;i<9;i++)                                
  93.         {
  94.           LCD=TAB1[i];                                //提取字符
  95.           WR_DATA();                                  //送出
  96.         }         
  97.            LCD=0xcd;                                      //写入显示起始地址
  98.            WR_COMM();                                     //写入命令
  99.        LCD=0x00;                                      //CGRAM内第0号图形
  100.        WR_DATA();                                           //写入数据                          
  101.      
  102.            TEMP_BJ();
  103.           
  104.   }
  105.                

  106. //------------------------------------------- DS18B20初始化函数 --------------------------------------

  107. bit INIT_1820(void)
  108. {
  109.    bit flag;                                         //flag为标志符
  110.    DQ = 1;                                           //DQ复位
  111.    delay(3);                                         //稍作延时
  112.    DQ = 0;                                           //将数据线从高拉低,保持480~960us
  113.    delay(80);
  114.    DQ = 1;                                           //释放数据线
  115.    delay(10);
  116.    flag=DQ;                                          //DQ=0表示存在      
  117.    delay(25);
  118.    return (flag);                                    //返回检测标志
  119. }

  120. //------------------------------------------  读出DS18B20函数 ----------------------------------------

  121. unsigned char READ_1820(void)
  122. {
  123.    unsigned char i=0;
  124.    unsigned char dat;                               //储存读出的一个字节数据
  125.    for (i=0;i<8;i++)
  126.    {
  127.      DQ =1;                                          //将数据线拉高
  128.      DQ = 0;                                         //将数据线从高拉低,启动读时序
  129.      dat>>=1;  
  130.      DQ = 1;                                         //将数据线拉高,为输出电平作准备
  131.      _nop_();
  132.          if(DQ==1)
  133.      dat|=0x80;                                      //读数据,存入dat
  134.      else
  135.      dat|=0x00;                                      //读数据,存入dat
  136.      delay(3);
  137.         }                     
  138.    return(dat);                                       //返回读出的十进制数据
  139. }

  140. //--------------------------------------------- 写入DS18B20函数 ---------------------------------------------

  141. WRITE_1820(unsigned char dat)
  142. {
  143.    unsigned char i=0;
  144.    for (i=0; i<8; i++)
  145.     {
  146.       DQ =1;                                       // 先将数据线拉高
  147.       DQ=0;                                        //数据线从高拉低,开始写入      
  148.       DQ=dat&0x01;                                 //利用与运算取出要写的某位二进制数据,                  
  149.       delay(3);
  150.       DQ=1;                                        //释放数据线      
  151.       _nop_();         
  152.       dat>>=1;                                     //将dat中的各二进制位数据右移1位
  153.    }
  154.       delay(3);
  155. }
  156. //---------------------------------------- 显示错误信息函数 ------------------------------------------

  157. void DISP_ERR(void)
  158.   {
  159.       unsigned char i;
  160.   
  161.       LCD=0x80;                                    //写显示地在第1行第1列
  162.       WR_COMM();
  163.       i = 0;                                       //从第一个字符开始显示
  164.      while(Error[i] != '\0')                       //写到结束标志
  165.       {      
  166.         LCD=(Error[i]);                            //将字符常量写入LCD
  167.         WR_DATA();
  168.             i++;                                       //指向下一个字符
  169.         delay(1000);                               //延时
  170.           }
  171.      while(1);                                      //循环,等待查明原因   
  172.   }

  173. //-------------------------------------- 显示温度的小数点 ------------------------------------------
  174.   
  175. void DISP_D(void)
  176. {         
  177.    
  178.   LCD=0xc9;                                       //写显示地址在第2行第10列
  179.   WR_COMM();
  180.   LCD=('.');
  181.   WR_DATA();   
  182.   delay(200);                                     //延时一点时间
  183. }

  184. //------------------------------------------ 显示TEMP字符函数 ------------------------------------------------

  185.    void DISP_TEMP(void)  
  186.   
  187.     {
  188.            unsigned char i;
  189.            LCD=0xc0;                                  //写入显示起始地址                 
  190.        WR_COMM();                                 //写入命令
  191.        for(i=0;i<5;i++)                                
  192.         {
  193.          LCD=TEMP[i];                             //提取字符
  194.          WR_DATA();                               //送出
  195.         }                                                        
  196.     }
  197.    
  198. //------------------------------------------- 显示菜单函数 --------------------------------------------
  199. DISP_EXP( )
  200.      {
  201.            unsigned char i;
  202.            LCD=0x83;                                    //写入显示起始地址                 
  203.        WR_COMM();                                   //写入命令
  204.        for(i=0;i<11;i++)                                
  205.         {
  206.          LCD=TAB2[i];                                //提取字符
  207.          WR_DATA();                                  //送出
  208.         }                          
  209.           DISP_TEMP();
  210.           DISP_D();
  211.         }
  212.    
  213. //---------------------------------------------- 读温度函数 -----------------------------------------

  214. RE_TEMP()
  215. {
  216.    unsigned char time;
  217.    INIT_1820();                                      //将DS18B20初始化
  218.    WRITE_1820(0xCC);                                 // 跳过读序号列号的操作
  219.    WRITE_1820(0x44);                                 // 启动温度转换   
  220.    for(time=0;time<100;time++);         
  221.    INIT_1820();                                      //将DS18B20初始化
  222.    WRITE_1820(0xCC);                                 //跳过读序号列号的操作
  223.    WRITE_1820(0xBE);                                 //读取温度的低位和高位
  224. }

  225. //------------------------------------------ 显示温度正负的符号 ---------------------------------------
  226.    
  227. void DISP_ZF(unsigned char fuhao)
  228. {
  229.   unsigned char show;   
  230. show=fuhao;      
  231.   LCD=0xc5;                                         //写显示地址在第2行第10列
  232.   WR_COMM();
  233.   LCD=(show);                                       //将小数点的字符常量写入LCD
  234.   WR_DATA();
  235.   delay(200);                                       //延时一点时间
  236. }

  237. //---------------------------------------- 显示温度的整数部分函数 ----------------------------------------

  238. void DISP_TEMP1(unsigned char x)
  239. {
  240.   unsigned char j,k,l;                              //j,k,l分别储存温度的百位、十位和个位
  241.   j=x/100;                                          //取百位
  242.   k=(x%100)/10;                                     //取十位
  243.   l=x%10;                                           //取个位
  244.   LCD=0xc6;                                         //写显示地址在第2行第7列
  245.   WR_COMM();
  246.   LCD=(digit[j]);
  247.   WR_DATA();
  248.   LCD=0xc7;
  249.   WR_COMM();
  250.   LCD=(digit[k]);
  251.   WR_DATA();
  252.   LCD=0xc8;
  253.   WR_COMM();
  254.   LCD=(digit[l]);
  255.   WR_DATA();
  256.   delay(200);                                       //延时一点时间
  257. }

  258. //---------------------------------------- 显示温度的小数数部分函数 -----------------------------------------

  259. void DISP_TEMP2(unsigned char x)
  260. {
  261.    LCD=0xca;                                         //写显示地址在第2行第11列
  262.    WR_COMM();
  263.    LCD=(digit[x]);
  264.    WR_DATA();                                        //将小数部分写入LCD
  265.    delay(200);                                       //延时一点时间
  266. }

  267. //----------------------------------------  温度数据转换显示函数 -------------------------------------------
  268.    
  269. void CONV_TEMP(void)  
  270. {
  271.    unsigned char TL;                                  //储存温度低位
  272.    unsigned char TH;                                  //储存温度高位
  273.    unsigned char TN;                                  //储存整数部分
  274.    unsigned char TD;                                  //储存小数部分

  275.    while(1)                                           //不断检测显示温度
  276.     {
  277.       RE_TEMP();                                      //读温度函数
  278. //-------------------
  279.           TL=READ_1820();                                 //先读温度值低位
  280.       TH=READ_1820();                                 //接着读温度值高位

  281.         if(TH>=0xf8)
  282.          {
  283.            DISP_ZF('-');
  284.            if(TL==0)
  285.             {
  286.               TH=(~TH+1)&0x03;
  287.               TN=TH*16+TL/16;
  288.               TD=(TL%16)*10/16;
  289.               goto loopshow;
  290.             }
  291.    
  292.            TH=~TH&0x03;
  293.            TL=~TL+1;
  294.            TN=TH*16+TL/16;
  295.            TD=(TL%16)*10/16;
  296.            goto loopshow;
  297.         }
  298.           DISP_ZF('+');
  299.           TN=TH*16+TL/16;                             //计算温度值整数部分           
  300.           TD=(TL%16)*10/16;                           //计算温度的小数部分
  301.           loopshow:                  
  302. //------------------------
  303.         DISP_TEMP1(TN);                                  //显示温度的整数部分
  304.     DISP_TEMP2(TD);                                 //显示温度的小数部分           
  305.     delay(100);   
  306.   }
  307. }
  308. //---------------------------------------- 主函数 ----------------------------------------------   

  309. void main(void)
  310. {   
  311.    INIT_LCD();                                       //LCD初始化函数
  312.    delay(100);   
  313.    if(INIT_1820()==1)                                //DS18B20初始化函数
  314.    DISP_ERR();                                       //显示错误信息函数
  315.    STORE_DATA();                                     //自定义温度标志符函数
  316.    DISP_EXP();                                       //显示菜单函数
  317.    CONV_TEMP();                                      //温度数据转换显示函数


  318. …………限于本文篇幅 余下代码请从51黑下载附件…………


复制代码


该系列源码包含有很多非常经典,代码风格十分规范,而且注释详细的单片机例程,还带仿真,对于MCU学习特别是初学者是很有帮助的,全部源码下载(共25个项目):http://www.51hei.com/bbs/dpj-79328-1.html

本例程下载(含proteus仿真工程文件与源码):
单片机LCD1602温度计实验.rar (76.76 KB, 下载次数: 289)

评分

参与人数 6黑币 +30 收起 理由
slender宇 + 5 赞一个!
天才2333333 + 5 很给力!
Jehu_Yu + 5 很给力!
fyn162011 + 5 很给力!
沧海客 + 5 绝世好帖!
201511106109 + 5 很给力!

查看全部评分

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

使用道具 举报

沙发
ID:162634 发表于 2017-3-30 12:42 来自手机 | 只看该作者
可以。。
回复

使用道具 举报

板凳
ID:208351 发表于 2017-6-6 19:24 | 只看该作者
请问在这个基础上怎么加报警器,并且可以手动设置温度上限呢
回复

使用道具 举报

地板
ID:212907 发表于 2017-6-20 13:02 | 只看该作者
完美!
回复

使用道具 举报

5#
ID:257583 发表于 2017-12-5 10:44 | 只看该作者
好贴,很给力!
回复

使用道具 举报

6#
ID:260460 发表于 2017-12-12 01:05 | 只看该作者
刚好要用到,太有帮助了
回复

使用道具 举报

7#
ID:320097 发表于 2018-5-30 21:54 | 只看该作者
新手看得云里雾里的
回复

使用道具 举报

8#
ID:415717 发表于 2018-10-28 23:54 | 只看该作者
很实用,谢谢楼主
回复

使用道具 举报

9#
ID:410674 发表于 2019-3-5 16:30 | 只看该作者
正需要这个,谢谢啦
回复

使用道具 举报

10#
ID:492403 发表于 2019-3-17 09:56 | 只看该作者
感谢分享
回复

使用道具 举报

11#
ID:491410 发表于 2019-3-17 12:01 | 只看该作者
感谢分享,多谢
回复

使用道具 举报

12#
ID:558989 发表于 2019-6-10 15:04 | 只看该作者
感谢感谢
回复

使用道具 举报

13#
ID:563106 发表于 2019-6-19 09:15 | 只看该作者
怎么能在加个NRF24L01无线传输模块呢?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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