找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
ID:285473 发表于 2019-6-28 17:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include <reg51.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int   
  5. //**********宏定义所需指令
  6. #define BASIC_SET  0x30
  7. #define EXTEND_SET 0x34
  8. #define DRAW_ON    0x36
  9. #define DRAW_OFF   0x34  
  10. //*************端口定义
  11. sbit LCD_RS = P3^5;
  12. sbit LCD_RW = P3^6;
  13. sbit LCD_EN = P3^4;  
  14. sbit DQ=P2^2;      
  15. //sbit k1=P1^0;


  16. //定义温度DS18B20接口
  17. //************变量定义
  18. uchar code t0[]="温度   .  ℃";
  19. uchar code t1[]="0123456789";        //利用一个温度表解决温度显示乱码
  20. uchar i,k,a,b;
  21. unsigned int temperature;
  22. unsigned char temp_x;                       //温度小数部分
  23. unsigned int temp_disp;   
  24. //****************短延时
  25. void delay(uint k)
  26. {  
  27.         uint i;
  28.     uchar j;
  29.         for(i = 0; i < k ;i ++)
  30.          for(j = 120; j>0 ;j--);
  31. }   
  32. //***********12864写指令函数
  33. void write_com(uchar cmd)
  34. {
  35.     LCD_RS = 0;
  36.         LCD_RW = 0;  
  37.         
  38.         delay(5);  
  39.         LCD_EN = 1;  P0 = cmd;  
  40.         delay(10);  
  41.         LCD_EN = 0;
  42. }   
  43. //********12864写数据函数
  44. void write_dat(uchar dat)
  45. {   
  46. LCD_RS = 1;     
  47. LCD_RW = 0;  

  48. delay(5);  
  49. LCD_EN = 1; P0 = dat;  
  50. delay(10);  
  51. LCD_EN = 0;
  52. }   
  53. //


  54. uchar read_dat(void)
  55. {
  56. uchar temp;   
  57. P0 = 0XFF;
  58. //释放数据线  
  59. LCD_RS = 1;   
  60. //数据  
  61. LCD_RW = 1;   
  62. // 读模式   
  63. LCD_EN = 1;   
  64. //E为高电平进行读数据或指令  
  65. delay(1);  
  66. temp = P0;  
  67. LCD_EN = 0;  
  68. return temp;  
  69. }   
  70. //设置光标(地址)函数  
  71. //参数说明:x---为行号,y为列号  
  72. void set_cursor(unsigned char x, unsigned char y)
  73. {   
  74. unsigned char i;   
  75. switch(x)           
  76. //确定行号  
  77. {   
  78. case 0x00: i=0x80; break;    //第一行   
  79. case 0x01: i=0x90; break;     //第二行   
  80. case 0x02: i=0x88; break;     //第三行   
  81. case 0x03: i=0x98; break;     //第四行   
  82. default : break;  
  83. }   
  84. i = y+i;          //确定列号
  85. write_com(i);
  86. }     
  87. //********************************************************
  88. //显示字符函数  
  89. //********************************************************
  90. void display_char(unsigned char Alphabet)
  91. {
  92.     write_dat(Alphabet);  
  93.          //写入需要显示字符的显示码
  94. }     
  95. //********************************************************
  96. //指定位置显示字符串函数  
  97. //参数说明:x为行号,y为列号  
  98. //********************************************************
  99. void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet)
  100. {   
  101. unsigned char i=0;   
  102. set_cursor(x,y);    //设置显示的起始地址  
  103. while(Alphabet[i]!='\0')  
  104. {   
  105. write_dat(Alphabet[i]);   //写入需要显示字符的显示码   
  106. i++;  
  107. }
  108. }
  109. //以下为GDRAM绘图部分

  110. //绘图显示的清屏函数(因清屏指令在画图时不能用)


  111.   void gui_clear()
  112.   {   
  113.   uchar i , j , k;   
  114.   write_com(EXTEND_SET);//扩展指令集,8位数据传输  
  115.   write_com(DRAW_OFF);//绘图显示关闭  
  116.   for(i = 0; i < 2; i ++)//分上下两屏写  
  117. {   
  118.   for(j = 0; j < 32; j ++)   
  119. {     
  120.   write_com(0x80 + j);//写y坐标   
  121.   delay(1);     
  122.   if(i == 0) //写x坐标   
  123.    {     
  124.    write_com(0x80);
  125.    delay(1);   
  126.    }     
  127.   else      //写下半屏   
  128.          {     
  129.          write_com(0x88);     
  130.          delay(1);   
  131.          }     
  132.   for(k = 0; k < 16; k ++)//写一整行数据   
  133.          {      
  134.          write_dat(0x00);//写高字节     
  135.          write_dat(0x00);//写低字节     
  136.          delay(1);   
  137.           }
  138.             
  139. }  
  140. }   
  141. write_com(DRAW_ON);//打开绘图显示  
  142. write_com(BASIC_SET);//打开基本指令集
  143. }
  144. //(给定坐标并打点的)任意位置打点函数
  145. void lcd_set_dot(uchar x,uchar y)
  146. {   
  147. uchar x_byte,x_bit;   //确定在坐标的那一字节哪一位  
  148. uchar y_ping , y_bit;    //确定在坐标的哪一屏哪一行   
  149. uchar tmph , tmpl;   //定义两个临时变量,用于存放读出来的数据  
  150. write_com(EXTEND_SET);    //扩展指令集  
  151. write_com(DRAW_OFF);        //绘图显示关闭   
  152. x_byte = x / 16;        //算出在哪一字节,注意一个地址是16位的  
  153. x_bit = x % 16;        //& 0x0f;//算出在哪一位   
  154. y_ping = y / 32;        //确定在上半屏还是下半屏,0代表上半屏,1代表下半屏  
  155. y_bit = y % 32;        //& 0x1f;//确定在第几行   
  156. write_com(0X80 + y_bit);//先写垂直地址(最高位必须)   
  157. write_com(0x80 + x_byte + 8 * y_ping);//水平坐标,下半屏坐标起始地址为0x88,(+8*y_ping)就是用来确定上半屏还是下半屏  
  158. read_dat();//预读取数据   
  159. tmph = read_dat();//读取当前显示高8位数据  
  160. tmpl = read_dat();//读取当前显示低8位数据  
  161. delay(1);   
  162. write_com(0x80 + y_bit);//读操作会改变AC,所以重新设置一下  
  163. write_com(0x80 + x_byte + 8 * y_ping);  
  164. delay(1);  
  165. if(x_bit < 8)  
  166. {   
  167. write_dat(tmph | (0x01 << (7 - x_bit)));//写高字节,因为坐标是从左向右的,GDRAM高位在昨,低位在右   
  168. write_dat(tmpl);//原低位数据送回  
  169. }  
  170. else  
  171. {   
  172. write_dat(tmph);//原高位数据送回   
  173. write_dat(tmpl | (0x01 << (15 - x_bit)));  
  174. }   
  175. write_com(DRAW_ON); //打开绘图显示  
  176. write_com(BASIC_SET);//回到基本指令集
  177. }     
  178. //画水平线函数
  179. //x0、x1为起始点和终点的水平坐标,y为垂直坐标
  180. //**********************************************************
  181. void gui_hline(uchar x0, uchar x1, uchar y)
  182. {   
  183. uchar bak;//用于对两个数互换的中间变量,使x1为大值  
  184. if(x0 > x1)  
  185. {   
  186. bak = x1;  
  187.   x1 = x0;   
  188.   x0 = bak;  
  189.   }   
  190. do  
  191. {   
  192.    lcd_set_dot(x0 , y);//从左到右逐点显示  
  193.    x0 ++;   
  194. }
  195. while(x1 >= x0);
  196.         }   
  197. //***********画竖直线函数***********************************//
  198. //x为起始点和终点的水平坐标,y0、y1为垂直坐标***************//
  199. //**********************************************************//
  200.   void gui_rline(uchar x, uchar y0, uchar y1)
  201.   {   
  202.   uchar bak;//用于对两个数互换的中间变量,使y1为大值  
  203.   if(y0 > y1)  
  204.   {   
  205.    bak = y1;   
  206.     y1 = y0;  
  207.     y0 = bak;  
  208.         }   
  209.         do  
  210.         {   
  211.         lcd_set_dot(x , y0);//从上到下逐点显示   
  212.         y0++;
  213.             
  214.         }
  215.         while(y1 >= y0);
  216.         }     
  217.          //*********任意两点间画直线*********************************//
  218.          //x0、y0为起始点坐标,x1、y1为终点坐标**********************//
  219.          //**********************************************************//
  220. void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1)
  221. {   
  222.   char dx;        //直线x轴差值
  223.   char dy;        //直线y轴差值   
  224.   char dx_sym;        //x轴增长方向,为-1时减值方向,为1时增值方向  
  225.   char dy_sym;        //y轴增长方向,为-1时减值方向,为1时增值方向  
  226.   char dx_x2;        //dx*2值变量,用于加快运算速度  
  227.   char dy_x2;        //dy*2值变量,用于加快运算速度  
  228.   char di;   //决策变量   
  229.   if(x0 == x1)//判断是否为垂直线  
  230.   {   
  231.   gui_rline(x0 , y0 , y1);//画垂直线   
  232.   return;  
  233.   }   
  234.   if(y0 == y1)//判断是否为水平线  
  235.   {   
  236.   gui_hline(x0 , x1 , y0);//画水平线   
  237.   return;  
  238.   }   
  239.    dx = x1 - x0;//求取两点之间的差值  
  240.    dy = y1 - y0;//****判断增长方向,或是否为水平线、垂直线、点*//  
  241.    if(dx > 0)//判断x轴方向   
  242.    dx_sym = 1;  
  243.    else  
  244.    {   
  245.    if(dx < 0)     
  246.    dx_sym = -1;   
  247.    else   
  248.    {     
  249.    gui_rline(x0 , y0 , y1);   
  250.    return;   
  251.    }  
  252.    }   
  253.    if(dy > 0)//判断y轴方向   
  254.    dy_sym = 1;  
  255.    else  
  256.    {   
  257.    if(dy < 0)     
  258.    dy_sym = -1;
  259.    else   
  260.    {     
  261.    gui_hline(x0 , x1 , y0);   
  262.    return;  
  263.     }  
  264.         }     
  265.         /*将dx、dy取绝对值***********/
  266.           dx = dx_sym * dx;  
  267.           dy = dy_sym * dy;   
  268.           /****计算2倍的dx、dy值*******/   
  269.            dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点对应
  270.            dy_x2 = dy * 1;    /***使用bresenham法进行画直线***/   
  271.            if(dx >= dy)//对于dx>=dy,使用x轴为基准  
  272.            {   
  273.                     di = dy_x2 - dx;   
  274.                         while(x0 != x1)   
  275.                         {     
  276.                                 lcd_set_dot(x0,y0);   
  277.                                 x0 +=dx_sym;   
  278.                                 if(di < 0)      
  279.                                 di += dy_x2;//计算出下一步的决策值   
  280.                         else   
  281.                         {      
  282.                                 di += dy_x2 - dx_x2;     
  283.                                 y0 += dy_sym;   
  284.                         }   
  285.                         }   
  286.                         lcd_set_dot(x0, y0);//显示最后一点  
  287.                 }   
  288.                 else  //对于dx<dy使用y轴为基准
  289.                  {   
  290.                          di = dx_x2 - dy;   
  291.                          while(y0 != y1)   
  292.                          {     
  293.                                  lcd_set_dot(x0, y0);   
  294.                                  y0 += dy_sym;   
  295.                                  if(di < 0)     
  296.                                          di += dx_x2;     
  297.                                  else
  298.                                    {      
  299.                                    di += dx_x2 - dy_x2;     
  300.                                    x0 += dx_sym;   
  301.                                    }  
  302.                                  }   
  303.                                 lcd_set_dot(x0, y0);//显示最后一点  
  304.                 }
  305. }         
  306.                         //以上为自定义字库部分
  307.                         //****************12864初始化函数
  308. void lcd_init()
  309. {   
  310.         write_com(0x30);//基本指令操作,8位并口  
  311.         delay(1);   
  312.         write_com(0x0c);//设置为游标右移,DDRAM地址加一,画面不动  
  313.         delay(1);   
  314.         write_com(0x01);//显示开,关光标  
  315.         delay(1);   
  316.         write_com(0x06);//清除lcd显示内容  
  317.         delay(1);
  318. }   //5ms延时  
  319. void Delay5Ms(void)
  320. {   
  321.         unsigned int TempCyc = 5552;
  322.         while(TempCyc--);
  323. }   
  324.                                         //400ms延时  
  325. void Delay400Ms(void)
  326. {   
  327. unsigned char TempCycA = 5;
  328. unsigned int TempCycB;  
  329. while(TempCycA--)  
  330. {   
  331. TempCycB=7269;   
  332. while(TempCycB--);  
  333. };
  334. }  
  335. /*************DS18B20温度读取模块*************/
  336. void delay_nus(unsigned char n)
  337. {
  338.     while(n--)
  339.         {
  340.             _nop_();
  341.                 _nop_();
  342.         }
  343. }
  344. bit ds18b20_reset(void)
  345. {
  346.     CY = 1;
  347.         while(CY)
  348.         {
  349.             DQ = 0;                         //送低电平复位信号
  350.                 delay_nus(240);                 //至少延时480us
  351.         delay_nus(240);
  352.                 DQ = 1;                         //释放数据线
  353.                 delay_nus(60);                  //等待60us
  354.                 CY = DQ;                        //检测存在脉冲
  355.                 delay_nus(240);                 //等待设备释放数据线
  356.                 delay_nus(180);
  357.         }
  358.         return 1;
  359. }
  360. unsigned char ds18b20_readbyte(void)
  361. {
  362.     unsigned char i;
  363.         unsigned char dat = 0;
  364.         for(i=0;i<8;i++)
  365.         {
  366.             dat >>= 1;
  367.                 DQ = 0;                         //开始时间片
  368.                 delay_nus(1);                   //延时等待
  369.                 DQ = 1;                         //准备接收
  370.                 delay_nus(1);                   //延时
  371.                 if(DQ) dat |= 0x80;             //读取数据
  372.                 delay_nus(60);                  //等待时间片结束
  373.         }
  374.         return dat;
  375. }
  376. void ds18b20_writebyte(unsigned char dat)
  377. {
  378.     unsigned char i;
  379.         for(i=0;i<8;i++)
  380.         {
  381.             DQ = 0;
  382.                 delay_nus(1);
  383.                 dat >>= 1;
  384.                 DQ = CY;
  385.                 delay_nus(60);
  386.                 DQ = 1;
  387.                 delay_nus(1);
  388.         }
  389. }
  390. void read_temp(void)
  391. {
  392.     if(ds18b20_reset())
  393.         {
  394.             ds18b20_writebyte(0xcc);
  395.             ds18b20_writebyte(0x44);
  396.                 if(ds18b20_reset())
  397.                 {
  398.                     ds18b20_writebyte(0xcc);
  399.                         ds18b20_writebyte(0xbe);
  400.                     temperature = ds18b20_readbyte();                                //读温度整数值
  401.                         temperature = (ds18b20_readbyte() << 8) + temperature;
  402.                         temp_x = (unsigned char)(temperature & 0x000f);                          //读温度小数值
  403.                         temp_x = (unsigned char)(((unsigned int)temp_x * 625) / 1000);
  404.                         temperature >>= 4;
  405.                         temp_disp = temperature * 10 + temp_x;
  406.                 }
  407.         }
  408. }
  409. //*****************************显示函数
  410. void display()
  411. {   
  412.         uint num;                  
  413.         uint shi,ge,xiaoshu;     
  414.         num=temp_disp;  
  415.         shi=num/100;  
  416.         ge=num/10%10;  
  417.         xiaoshu=num%10;   
  418.          if(k==100)  
  419.          {
  420.                  ++i;  
  421.                  k=0;   
  422.                  if(i>127)  
  423.                  {
  424.                          i=0;  
  425.                          a=0;  
  426.                          b=0;   
  427.                          gui_clear();//画图时清屏函数  
  428.                          gui_line(0,15,0,63);  
  429.                          gui_line(0,63,127,63);  
  430.                  }      
  431.                  gui_line(a,63-b,i,63-shi*10-ge);
  432.                  b=shi*10+ge;
  433.                  a=i;
  434.            }     
  435.            write_com(0x82);
  436.            write_dat(t1[shi]);
  437.            write_dat(t1[ge]);
  438.            write_com(0x84);
  439.            write_dat(t1[xiaoshu]);
  440. }     
  441.            void init_time0()   
  442.            {      
  443.            TMOD |= 0x10;   
  444.            TH1=(65536-50000)/256;     //50毫秒
  445.            TL1=(65536-50000)%256;   
  446.            EA=1;            
  447.            ET1=1;            
  448.            TR1=1;           
  449.            }  
  450.            
  451.            
  452.            void main()  
  453.            {
  454.             init_time0();     //中断
  455.                 lcd_init();//12864初始化函数   
  456.                 gui_clear();//画图时清屏函数  
  457.                 delay(10);
  458.                 display_string(0,0,t0);  
  459.                 gui_line(0,15,0,63);  
  460.                 gui_line(0,63,127,63);  
  461.                  
  462.                 while(1)  
  463.                 {   
  464.                 display();read_temp();   
  465.                 }
  466.                 }
  467.                  void time0() interrupt 3   
  468.                  {   
  469.                  TH1=(65536-50000)/256;     //,50毫秒        
  470.                  TL1=(65536-50000)%256;  
  471.                   k++;      
  472.                 }      
复制代码

12864温度有线.rar

109.3 KB, 下载次数: 46, 下载积分: 黑币 -5

51单片机温度显示曲线

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

使用道具 举报

沙发
ID:1 发表于 2019-6-28 18:07 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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