找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4184|回复: 14
收起左侧

单片机+LCD12864显示温度曲线程序

  [复制链接]
ID:1030230 发表于 2022-5-27 17:43 | 显示全部楼层 |阅读模式
本实验适51单片机开发板,需要接上带字库的LCD12864才能正常显示,如果接上后没有显示,请调节LCD12864背后的小  电位器进行对比度调节。

另外除A2、A3、A4和V2.0开发板以外的51开发板,还需要另外在温度模块输出管脚接线到P37。程序初始化较慢,下载完程序后需要稍等才能显示,属于正常现象。

程序还有许多可以优化或添加功能的地方,大家可以自行研究学习。
制作出来的实物图如下:
网页捕获_27-5-2022_17403_prechin.net.jpeg
这里给出完整代码供参考。

单片机源程序如下:

  1. #include<12864.h>
  2. void delay(uint i)        //延时函数
  3. {
  4.         while(--i);
  5. }
  6. void Read_busy()        //LCD12864忙检测
  7. {
  8.         RS=0;
  9.         RW=1;
  10.         EN=1;
  11.         LCD_databus=0xFF;
  12.         while(LCD_databus & 0x80);        //判断最高位,1---busy,0---Nobusy
  13.         EN=0;
  14. }
  15. void write_LCD_command(uchar value)//写指令
  16. {
  17.         RS=0;
  18.         RW=0;
  19.         delay(40);
  20.         EN=1;
  21.         LCD_databus=value;
  22.         delay(40);
  23.         EN=0;
  24. }
  25. void write_LCD_data(uchar value)//写数据
  26. {
  27.         RS=1;
  28.         RW=0;
  29.         delay(40);
  30.         EN=1;
  31.         LCD_databus=value;
  32.         delay(40);
  33.         EN=0;
  34. }
  35. void init_LCD()                //初始化LCD
  36. {
  37.         write_LCD_command(0x30);        //8位数,基本指令
  38.         delay(100);
  39.         write_LCD_command(0x30);
  40.         delay(37);
  41.         write_LCD_command(0x0C);        //开显示,不显示光标,光标不闪烁
  42.         delay(100);
  43.         write_LCD_command(0x01);        //清屏指令
  44.         delay(100);
  45.         write_LCD_command(0x06);        //没写入数据,地址指针加1
  46. }
  47. <p style="line-height: 30px; text-indent: 2em;">void Clear_GDRAM()                //清楚GDRAM
  48. {
  49.         uchar x,y;
  50.         for(y=0;y<64;y++)
  51.         {
  52.                 for(x=0;x<16;x++)
  53.                 {
  54.                         write_LCD_command(0x34);
  55.                         write_LCD_command(y+0x80);        //先送垂直地址
  56.                         write_LCD_command(x+0x80);        //后送水平地址
  57.                         write_LCD_command(0x30);        //基本指令
  58.                         write_LCD_data(0x00);                //写入数据0
  59.                         write_LCD_data(0x00);
  60.                 }
  61.         }
  62. }
  63. <p style="line-height: 30px; text-indent: 2em;">uchar ReadByte()        //读LCD
  64. {
  65.         uchar Read_value;
  66.         Read_busy();
  67.         RS=1;
  68.         RW=1;
  69.         EN=0;
  70.         EN=1;
  71.         Read_value=LCD_databus;        
  72.         EN=0;
  73.         
  74.         return Read_value;
  75. }
  76. void display_BMP(uchar *address)//显示图片
  77. {
  78.         uchar i,j;
  79.         for(i=16;i<32;i++)
  80.         {
  81.                 write_LCD_command(0x80+i);        //先送垂直地址
  82.                 write_LCD_command(0x80);        //再送水平地址
  83.                 for(j=0;j<16;j++)
  84.                 {
  85.                         write_LCD_data(*address);//写入数据
  86.                         address++;
  87.                 }
  88.         }
  89.         
  90.         for(i=0;i<32;i++)
  91.         {
  92.                 write_LCD_command(0x80+i);//先送垂直地址
  93.                 write_LCD_command(0x88);        //再送水平地址
  94.                 for(j=0;j<16;j++)
  95.                 {
  96.                         write_LCD_data(*address);
  97.                         address++;
  98.                 }
  99.         }
  100.         
  101. }
  102. /********************************************************
  103. 画点函数说明:增加LCD读函数,目的是使不打点的地方数据保持
  104. 不变:方法是先读出不打点位置的数据,打完点后将读到的数据写
  105. 入原来的位置,只有这样才会显示打点的曲线。
  106. *********************************************************/
  107. void Draw_dots(uchar x,uchar y,uchar color)
  108. {
  109.         uchar ROW,xlabel,xlabel_bit;
  110.         uchar Read_H,Read_L;
  111.         write_LCD_command(0x34);
  112.         write_LCD_command(0x36);
  113.         xlabel=x>>4;
  114.         xlabel_bit=x & 0x0F;
  115.         
  116.         if(y<32)
  117.         {
  118.                 ROW=y;
  119.         }
  120.         else
  121.         {
  122.                 ROW=y-32;
  123.                 xlabel+=8;
  124.         }
  125.         write_LCD_command(ROW+0x80);
  126.         write_LCD_command(xlabel+0x80);
  127.         ReadByte();        //读取当前GDRAM数据前要进行一次空读,接下来就可以读出数据了
  128.         Read_H=ReadByte();
  129.         Read_L=ReadByte();
  130.         
  131.         write_LCD_command(ROW+0x80);
  132.         write_LCD_command(xlabel+0x80);
  133.         
  134.         if(xlabel_bit<8)
  135.         {
  136.                 switch(color)
  137.                 {
  138.                         case 0:Read_H &= (~(0x01<<(7-xlabel_bit)));//若变白
  139.                         break;
  140.                         case 1:Read_H |= (0x01<<(7-xlabel_bit));//若涂黑
  141.                         break;
  142.                         case 2:Read_H ^= (0x01<<(7-xlabel_bit));//若反转
  143.                         break;        
  144.                         default:break;
  145.                 }
  146.                 write_LCD_data(Read_H);//将数据写入GDRAM
  147.                 write_LCD_data(Read_L);//先写高位,再写低位(地址指针顺序)
  148.         }
  149.         else
  150.         {
  151.                 switch(color)//color设置
  152.                 {
  153.                         case 0: Read_L &= (~(0x01<<(15-xlabel_bit)));//若变白
  154.                         break;
  155.                         case 1: Read_L |= (0x01<<(15-xlabel_bit));//若涂黑
  156.                         break;
  157.                         case 2: Read_L ^= (0x01<<(15-xlabel_bit));//若反转
  158.                         break;
  159.                         default:break;
  160.                 }
  161.                 write_LCD_data(Read_H);
  162.                 write_LCD_data(Read_L);//写入数据
  163.         }
  164.         
  165.         write_LCD_command(0x30);//回到普通模式
  166. }
复制代码
  1. #include<ds18b20.h>

  2. uchar HZ1[]="温度曲线";
  3. uchar code table[]={0x00,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,
  4. 0x70,0x30,0x88,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x80,
  5. 0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //自定义字符:显示℃

  6. void delay_us(uchar i)        //精确延时---- T=2*i+5 单位:us
  7. {
  8.         while(--i);                        
  9. }

  10. void Reset_DS18B20()        //复位DS18B20
  11. {
  12.         DQ=1;
  13.         DQ=0;
  14.         delay_us(494);                //低电平至少保持480——960us
  15.         DQ=1;                                //释放总线,准备接收存在脉冲---低电平
  16.         delay_us(200);        
  17. }

  18. void write_DS18B20(uchar value)        //写DS18B20指令
  19. {
  20.         uchar i = 0;
  21.         for(i = 0; i < 8; i ++)
  22.                 {
  23.                         DQ = 1;
  24.                         DQ = 0;
  25.                         delay_us(10);                        
  26.                         DQ = value & 0x01;
  27.                         delay_us(40);
  28.                         DQ = 1;
  29.                         value >>= 1;         
  30.                 }
  31. }

  32. uchar Read_DS18B20(void)        //读DS18b20
  33. {
  34.         uchar i=0;
  35.         uchar value=0;
  36.         for(i=0;i<8;i++)
  37.                 {
  38.                         DQ=1;
  39.                         DQ=0;
  40.                         delay_us(10);                        
  41.                         DQ=1;                //将总线释放,以便读取数值
  42.                         delay_us(2);
  43.                         value>>=1;
  44.                         if(DQ)                                                                        
  45.                                 value |=0x80;        //先读MSB,后读LSB
  46.                         delay_us(34);//在60us内完成读取                                
  47.                 }
  48.         return value;
  49. }

  50. uchar Read_temp()
  51. {
  52.         uchar temp;
  53.         uchar temp_L,temp_H;
  54.         Reset_DS18B20();
  55.         write_DS18B20(0xCC);
  56.         write_DS18B20(0x44);
  57.         Reset_DS18B20();
  58.         write_DS18B20(0xCC);
  59.         write_DS18B20(0xBE);
  60.         temp_L=Read_DS18B20();        //读温度的低8位
  61.         temp_H=Read_DS18B20();        //再读温度高8位
  62.         
  63.         temp=(temp_H*256+temp_L)/16;//将十六进制转化为10进制

  64.         return temp;        //返回当前温度的值
  65. /**注:没对复位度进行处理**/
  66. }
复制代码


  1. #include"temp.h"


  2. uchar code table_[]={0x00,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,
  3. 0x70,0x30,0x88,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x80,
  4. 0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //自定义字符:显示℃


  5. uchar HZ[]="温度曲线";
  6. /*******************************************************************************
  7. * 函数名         : Delay1ms
  8. * 函数功能                   : 延时函数
  9. * 输入           : 无
  10. * 输出                  : 无
  11. *******************************************************************************/

  12. void Delay1ms(unsigned int y)
  13. {
  14.         unsigned int x;
  15.         for(y;y>0;y--)
  16.                 for(x=110;x>0;x--);
  17. }
  18. /*******************************************************************************
  19. * 函数名         : Ds18b20Init
  20. * 函数功能                   : 初始化
  21. * 输入           : 无
  22. * 输出                  : 初始化成功返回1,失败返回0
  23. *******************************************************************************/

  24. unsigned char Ds18b20Init()
  25. {
  26.         unsigned int i;
  27.         DSPORT=0;                         //将总线拉低480us~960us
  28.         i=70;        
  29.         while(i--);//延时642us
  30.         DSPORT=1;                        //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
  31.         i=0;
  32.         while(DSPORT)        //等待DS18B20拉低总线
  33.         {
  34.                 i++;
  35.                 if(i>5000)//等待>5MS
  36.                         return 0;//初始化失败        
  37.         }
  38.         return 1;//初始化成功
  39. }

  40. /*******************************************************************************
  41. * 函数名         : Ds18b20WriteByte
  42. * 函数功能                   : 向18B20写入一个字节
  43. * 输入           : com
  44. * 输出                  : 无
  45. *******************************************************************************/

  46. void Ds18b20WriteByte(unsigned char dat)
  47. {
  48.         unsigned int i,j;
  49.         for(j=0;j<8;j++)
  50.         {
  51.                 DSPORT=0;                        //每写入一位数据之前先把总线拉低1us
  52.                 i++;
  53.                 DSPORT=dat&0x01; //然后写入一个数据,从最低位开始
  54.                 i=6;
  55.                 while(i--); //延时68us,持续时间最少60us
  56.                 DSPORT=1;        //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
  57.                 dat>>=1;
  58.         }
  59. }
  60. /*******************************************************************************
  61. * 函数名         : Ds18b20ReadByte
  62. * 函数功能                   : 读取一个字节
  63. * 输入           : com
  64. * 输出                  : 无
  65. *******************************************************************************/


  66. unsigned char Ds18b20ReadByte()
  67. {
  68.         unsigned char byte,bi;
  69.         unsigned int i,j;        
  70.         for(j=8;j>0;j--)
  71.         {
  72.                 DSPORT=0;//先将总线拉低1us
  73.                 i++;
  74.                 DSPORT=1;//然后释放总线
  75.                 i++;
  76.                 i++;//延时6us等待数据稳定
  77.                 bi=DSPORT;         //读取数据,从最低位开始读取
  78.                 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
  79.                 byte=(byte>>1)|(bi<<7);                                                  
  80.                 i=4;                //读取完之后等待48us再接着读取下一个数
  81.                 while(i--);
  82.         }                                
  83.         return byte;
  84. }
  85. /*******************************************************************************
  86. * 函数名         : Ds18b20ChangTemp
  87. * 函数功能                   : 让18b20开始转换温度
  88. * 输入           : com
  89. * 输出                  : 无
  90. *******************************************************************************/

  91. void  Ds18b20ChangTemp()
  92. {
  93.         Ds18b20Init();
  94.         Delay1ms(1);
  95.         Ds18b20WriteByte(0xcc);                //跳过ROM操作命令                 
  96.         Ds18b20WriteByte(0x44);            //温度转换命令
  97. //        Delay1ms(100);        //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
  98.    
  99. }
  100. /*******************************************************************************
  101. * 函数名         : Ds18b20ReadTempCom
  102. * 函数功能                   : 发送读取温度命令
  103. * 输入           : com
  104. * 输出                  : 无
  105. *******************************************************************************/

  106. void  Ds18b20ReadTempCom()
  107. {        

  108.         Ds18b20Init();
  109.         Delay1ms(1);
  110.         Ds18b20WriteByte(0xcc);         //跳过ROM操作命令
  111.         Ds18b20WriteByte(0xbe);         //发送读取温度命令
  112. }
  113. /*******************************************************************************
  114. * 函数名         : Ds18b20ReadTemp
  115. * 函数功能                   : 读取温度
  116. * 输入           : com
  117. * 输出                  : 无
  118. *******************************************************************************/

  119. //int Ds18b20ReadTemp()
  120. //{
  121. //        int temp=0;
  122. //        unsigned char tmh,tml;
  123. //        Ds18b20ChangTemp();                                 //先写入转换命令
  124. //        Ds18b20ReadTempCom();                        //然后等待转换完后发送读取温度命令
  125. //        tml=Ds18b20ReadByte();                //读取温度值共16位,先读低字节
  126. //        tmh=Ds18b20ReadByte();                //再读高字节
  127. //        temp=tmh;
  128. //        temp<<=8;
  129. //        temp|=tml;
  130. //        return temp;
  131. //}

  132. int Ds18b20ReadTemp()
  133. {
  134.         int temp=0;
  135.         float tp;
  136.         unsigned char tmh,tml;
  137.         Ds18b20ChangTemp();                                 //先写入转换命令
  138.         Ds18b20ReadTempCom();                        //然后等待转换完后发送读取温度命令
  139.         tml=Ds18b20ReadByte();                //读取温度值共16位,先读低字节
  140.         tmh=Ds18b20ReadByte();                //再读高字节
  141.         temp=tmh;
  142.         temp<<=8;
  143.         temp |=tml;

  144.         if(temp < 0)
  145.         {
  146.                 temp=temp-1;
  147.                 temp=~temp;
  148.                 tp=temp;
  149.                 temp=tp*0.0625*100+0.5;        
  150.         }
  151.         else
  152.         {
  153.                 tp=temp;
  154.                 temp=tp*0.0625*100+0.5;        
  155.         }

  156.         return temp/100;
  157. }
复制代码
  1. /***********************************************************
  2. 功能:12864显示温度曲线
  3. 接线:DS18B20输出管脚接到P37
  4. ************************************************************/
  5. #include"bmp.h"
  6. #include"12864.h"
  7. #include"temp.h"


  8. void main()
  9. {
  10.         uchar i,j,color=1,num;
  11.         init_LCD();
  12.         while(1)
  13.         {
  14.                 write_LCD_command(0x30);
  15.                 write_LCD_command(0x80);//基本指令,显示汉字
  16.                 for(i=0;i<8;i++)
  17.                 {
  18.                         write_LCD_data(HZ[i]);
  19.                 }
  20.                 Clear_GDRAM();        //清楚GDRAM区的内容
  21.                 write_LCD_command(0x36);//扩展指令,绘图打开  
  22.                 display_BMP(ZB);//显示坐标                        
  23.                 for(i=13;i<128;i++)        //打点
  24.                 {
  25.                         j=70-Ds18b20ReadTemp();
  26.                         Draw_dots(i,j,1);
  27.                         delay(40000);
  28.                         delay(40000);
  29.                         write_LCD_command(0x30);
  30.                         write_LCD_command(0x84);        //切换到基本指令显示字符
  31.                         write_LCD_data(':');
  32.                         write_LCD_data(Ds18b20ReadTemp()/100+0x30);
  33.                         write_LCD_data(Ds18b20ReadTemp()/10+0x30);
  34.                         write_LCD_data(Ds18b20ReadTemp()%10+0x30);//显示温度的值
  35.                         
  36.                         write_LCD_command(0x40);        //自定义第一个CGRAM,编码为0000
  37.                         for(num=0;num<32;num++)
  38.                         {
  39.                                 write_LCD_data(table_[num]);
  40.                         }
  41.                         write_LCD_command(0x86);        //规定CGRAM字符显示位置
  42.                         write_LCD_data(0x00);
  43.                         write_LCD_data(0x00);
  44.                 }

  45.         }
  46.         
  47. }
复制代码

Keil代码下载:   
12864液晶显示温度.zip (57.24 KB, 下载次数: 212)

评分

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

查看全部评分

回复

使用道具 举报

ID:278457 发表于 2022-6-1 17:18 | 显示全部楼层
向你学习,很强
回复

使用道具 举报

ID:1038309 发表于 2022-7-6 09:14 | 显示全部楼层

这个代码可以显示出来吗
回复

使用道具 举报

ID:863362 发表于 2022-7-7 08:37 | 显示全部楼层
大还不错就是 发表于 2022-7-6 09:14
这个代码可以显示出来吗

可以显示出来
回复

使用道具 举报

ID:292359 发表于 2022-7-7 11:59 | 显示全部楼层
厉害!我一直是用ADT75+数码管显示温度就完事了,有想串口送出数据搞成曲线在电脑上用MFC写个程序显示出来,也想用LCD显示显示曲线,但懒得弄,学习了。
回复

使用道具 举报

ID:366877 发表于 2022-8-20 14:08 | 显示全部楼层
a4umi001 发表于 2022-7-7 11:59
厉害!我一直是用ADT75+数码管显示温度就完事了,有想串口送出数据搞成曲线在电脑上用MFC写个程序显示出来 ...

请问坐标图片能发一份吗?
回复

使用道具 举报

ID:388477 发表于 2022-11-11 15:12 | 显示全部楼层
可以显示,非常好!
回复

使用道具 举报

ID:981391 发表于 2022-11-16 16:19 | 显示全部楼层
这个代码可以用,非常好!
回复

使用道具 举报

ID:433219 发表于 2022-11-16 17:27 | 显示全部楼层
并行液晶,太浪费io了 ,,,建议改 st7920的12864 就2个io驱动,
回复

使用道具 举报

ID:1067121 发表于 2023-3-19 11:10 | 显示全部楼层
只能显示坐标轴没有曲线是为什么,温度读取是没问题的
回复

使用道具 举报

ID:216265 发表于 2023-3-22 19:52 | 显示全部楼层
多谢,正好研究下
回复

使用道具 举报

ID:53978 发表于 2023-3-23 09:07 | 显示全部楼层
加个k型热电偶啊 这样就更实用了。
回复

使用道具 举报

ID:1105394 发表于 2023-12-20 16:55 | 显示全部楼层
很好的代码,好好研究一下,最近正好用到
回复

使用道具 举报

ID:433219 发表于 2023-12-21 08:39 | 显示全部楼层
一看  RS=0;       RW=1;       EN=1; 就知道是并行接法,完全浪费了st7920类2线液晶的优势   
回复

使用道具 举报

ID:1064915 发表于 2023-12-21 15:21 | 显示全部楼层
能否改成ks0108的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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