找回密码
 立即注册

QQ登录

只需一步,快速开始

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

LCD12864基于ds18b20 显示温度曲线 单片机源程序

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include "lcd12864.h"
  2. #ifdef LCD12864_DEV_DRIVER
  3. sbit DQ = DS18B20_DQ_PIN
  4. static uint16_t clock_ticks = 0;
  5. static bool_t second_flag = 0;
  6. static uint8_t pos_x = 0;
  7. static uint8_t pos_y = 0;
  8. static uint8_t pos_x_befor = 0;
  9. static uint8_t pos_y_befor = 0;
  10. static idata int16_t temperature;
  11. static idata float temp_display;
  12. static idata uint8_t display_buf[8];
  13. static void ds18b20_delay(uint16_t i)
  14. {
  15.         while( i-- );
  16. }
  17. static bool_t ds18b20_reset(void) /* 初始化函数 */
  18. {
  19.   uint8_t x = 0;
  20.   
  21.   DQ = 1;          //DQ复位
  22.   ds18b20_delay(8);  //稍做延时
  23.   DQ = 0;          //单片机将DQ拉低
  24.   ds18b20_delay(80); //精确延时 大于 480us
  25.   DQ = 1;          //拉高总线
  26.   ds18b20_delay(14);
  27.   x = DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  28.   ds18b20_delay(20);

  29.   if(x == 0){
  30.     return TRUE;
  31.   }else{
  32.     return FALSE;
  33.   }
  34. }
  35. static uint8_t ds18b20_read_one_char(void)/* 读一个字节 */
  36. {
  37.         uint8_t i=0;
  38.         uint8_t dat = 0;
  39.   
  40.   for (i=8;i>0;i--){
  41.     DQ = 0;       /* 给脉冲信号 */
  42.     dat>>=1;
  43.     DQ = 1;       /* 给脉冲信号 */
  44.     if(DQ)
  45.     dat|=0x80;
  46.     ds18b20_delay(4);
  47.   }
  48.   
  49.          return dat;
  50. }

  51. static uint8_t ds18b20_write_one_char(uint8_t dat)/* 写一个字节      */
  52. {
  53.   uint8_t i=0;
  54.   
  55.   for (i=8; i>0; i--){
  56.     DQ = 0;
  57.     DQ = dat&0x01;
  58.     ds18b20_delay(5);
  59.     DQ = 1;
  60.     dat>>=1;
  61.   }
  62.   return dat;
  63. }
  64. int16_t ds18b20_read_temperature(void)/* 读取温度, 返回的温度值 *10, 即一位小数 */
  65. {
  66.         uint8_t a = 0;
  67.         uint8_t b = 0;
  68.         int16_t  t = 0;
  69.   bool_t is_negative_temp = 0;
  70.   
  71.         __disable_irq();
  72.   
  73.         ds18b20_reset();

  74.         ds18b20_write_one_char(0xCC); /* 跳过读序号列号的操作 */
  75.         ds18b20_write_one_char(0x44); /* 启动温度转换 */
  76.         ds18b20_delay(100);
  77.   ds18b20_reset();
  78.         
  79.         ds18b20_write_one_char(0xCC); /* 跳过读序号列号的操作 */
  80.         ds18b20_write_one_char(0xBE); /* 读取温度寄存器等(共可读9个寄存器) 前两个就是温度 */
  81.         a = ds18b20_read_one_char();
  82.         b = ds18b20_read_one_char();
  83.   
  84.         __enable_irq();        

  85.   if( b > 0x7f )      /* 最高位为1 时温度是负 */
  86.   {
  87.     a = ~a + 1;
  88.     b = ~b;
  89.     is_negative_temp = 1;
  90.   }

  91.   t = a >> 4;
  92.   t += b << 4;

  93.   a = (a&0x0f)*10 >> 4;

  94.   t *= 10;
  95.   t += a;
  96.   
  97.   if(is_negative_temp){
  98.     t = -t;
  99.   }
  100.   
  101.         return t;
  102. }
  103. void ds18b20_init(void)
  104. {
  105.   ds18b20_reset();

  106.   ds18b20_write_one_char(0xcc);//忽略ROM指令
  107.   ds18b20_write_one_char(0x4e);//写暂存器指令
  108.   ds18b20_write_one_char(0); //TH值未使用
  109.   ds18b20_write_one_char(0);  //TL值未使用
  110.   ds18b20_write_one_char(0x3f);// 采用bit数。
  111.   //0x1f : 0.5000°C  转换时间93.75ms
  112.   //0x3f : 0.2000°C  转换时间187.5ms
  113.   //0x5f : 0.1250°C  转换时间375ms
  114.   //0x7f : 0.0625°C  转换时间750ms

  115.   ds18b20_read_temperature();  /* 第一次读取值错误,丢弃 */
  116. }
  117. static void draw_coord(void)/* 画坐标 */
  118. {
  119.   pos_x = 0;
  120.   pos_y = 0;
  121.   pos_x_befor = 0;
  122.   pos_y_befor = 0;
  123.   lcd12864_clear_display(0);
  124.   
  125.   lcd12864_draw_dotted_line(0,63, 0, 0);
  126.   lcd12864_draw_dotted_line(0,32,127,32);
  127.   lcd12864_draw_dotted_line(0, 63,127, 63);

  128.   lcd12864_show_string(0, 80, "T:0");
  129. }
  130. void Delay500ms()                //@11.0592MHz
  131. {
  132.         unsigned char i, j, k;

  133.         _nop_();
  134.         i = 4;
  135.         j = 129;
  136.         k = 119;
  137.         do
  138.         {
  139.                 do
  140.                 {
  141.                         while (--k);
  142.                 } while (--j);
  143.         } while (--i);
  144. }
  145. void main(void)
  146. {
  147.   SCON = 0x50;    /* 8位数据,可变波特率 */
  148.   TMOD &= 0x0f;   /* 设定定时器1为16位自动重装方式 */
  149.   TMOD |= 0x20;   /* 设定定时器1为16位自动重装方式 */
  150.   PCON = 0x00;    /* 波特率不加倍 */
  151.   TH1 = 0xFD;     /* 设定定时初值 */
  152.   TL1 = 0xFD;     /* 设定定时初值 */
  153.   TR1 = 1;        /* 启动定时器1 */
  154.   REN = 1;        /* 使能接收 */
  155.   ES = 1;         /* 打开串口中断 */
  156.   
  157.   TMOD &= 0xF0;                //设置定时器模式
  158.         TMOD |= 0x01;                //设置定时器模式
  159.         TL0 = 0x00;                //设置定时初值,50ms中断
  160.         TH0 = 0x4C;                //设置定时初值
  161.         TF0 = 0;                //清除TF0标志
  162.         TR0 = 1;                //定时器0开始计时
  163.   ET0 = 1;          //允许定时/计数器0中断
  164.   
  165.   ds18b20_init();
  166.   lcd12864_init();
  167.   __enable_irq();
  168.   draw_coord();
  169.   second_flag = 1;

  170.   ds18b20_read_temperature();
  171.   Delay500ms();
  172.   ds18b20_read_temperature();
  173.   Delay500ms();
  174.   while(1){
  175.     if(second_flag == 1){
  176.       second_flag = 0;
  177.       if(pos_x == 128){
  178.         draw_coord();
  179.       }
  180.    
  181.       temperature = ds18b20_read_temperature();
  182.       temp_display = temperature / 10.0;
  183.       sprintf(display_buf, "%.1f", temp_display);
  184.       lcd12864_show_string(0, 96, "    ");
  185.       lcd12864_show_string(0, 96, display_buf);
  186.       if(temperature > 630){
  187.         temperature = 630;
  188.       }else if(temperature < 0){
  189.         temperature = 0;
  190.       }
  191.       
  192.       pos_y = temperature / 10;
  193.       pos_y = 63 - pos_y;
  194.       
  195.       if(pos_x == 0){
  196.         pos_x_befor = 0;
  197.         pos_y_befor = pos_y;
  198.       }
  199.       lcd12864_draw_line(pos_x_befor, pos_y_befor, pos_x, pos_y);
  200.       pos_x_befor = pos_x;
  201.       pos_y_befor = pos_y;
  202.       pos_x++;
  203.     }
  204.   }
  205. }
  206. void timer0() interrupt 1
  207. {
  208.   TL0 = 0x00;//重新装载初值, 50ms中断
  209.   TH0 = 0x4c;  
  210.          
  211.   clock_ticks++;

  212.   if(clock_ticks == 20){
  213.     clock_ticks = 0;
  214.     second_flag = 1;
  215.   }
  216. }

  217. sbit RST = LCD12864_RST;
  218. sbit E   = LCD12864_EN;
  219. sbit RW  = LCD12864_RW;
  220. sbit DI  = LCD12864_DI;
  221. sbit CS1 = LCD12864_CS1;
  222. sbit CS2 = LCD12864_CS2;

  223. #define LCDPORT   P0
  224. #define LCDSTARTROW 0xC0                            /* 设置起始行指令 */
  225. #define LCDPAGE     0xB8                                  /* 设置页指令 */
  226. #define LCDLINE     0x40                                  /* 设置列指令 */
  227. #define ASCII_CODE_12864_ELEMENT_NUM      ( 67 )
  228. extern ascii_12864 code ascii_code_12864[];
  229. /*---------------------------------------------------------------------------*/
  230. static bool_t lcd12864_is_busy(void)
  231. {
  232.   uint8_t state = 0;
  233.   bool_t busy;
  234.   
  235.         LCDPORT = 0xFF;
  236.         RW = 1;
  237.         DI = 0;
  238.         E = 1;
  239.         E = 0;
  240.   E = 1;/* E的下降沿,然后E持续拉高读才有效 */
  241.   state = LCDPORT;
  242.   E = 0;

  243.   busy = (bool_t)(state>>7);
  244.         return busy;
  245. }
  246. /*---------------------------------------------------------------------------*/
  247. static void lcd12864_write_data(uint8_t ucData)
  248. {
  249.   uint16_t timeout;

  250.   timeout = 0;
  251.         while(lcd12864_is_busy()){
  252.     timeout++;
  253.     if(timeout > 0xff){
  254.       break;
  255.     }
  256.   }
  257.         LCDPORT = 0xFF;

  258.         RW = 0;
  259.         DI = 1;
  260.         LCDPORT = ucData;
  261.         E = 1;
  262.         E = 0;
  263. }
  264. /*---------------------------------------------------------------------------*/
  265. static void lcd12864_write_cmd(uint8_t ucCMD)
  266. {
  267.         uint16_t timeout;

  268.   timeout = 0;
  269.         while(lcd12864_is_busy()){
  270.     timeout++;
  271.     if(timeout > 0xff){
  272.       break;
  273.     }
  274.   }
  275.         LCDPORT = 0xFF;

  276.         RW = 0;
  277.         DI = 0;
  278.         LCDPORT = ucCMD;
  279.         E = 1;
  280.         E = 0;
  281. }
  282. /*---------------------------------------------------------------------------*/
  283. void lcd12864_init( void )
  284. {
  285.         CS1 = 1;
  286.         CS2 = 1;
  287.   
  288.         lcd12864_write_cmd(0x38);                      /* 8位形式,两行字符 */
  289.         lcd12864_write_cmd(0x0F);                      /* 开显示 */
  290.         lcd12864_write_cmd(0x01);                      /* 清屏 */
  291.         lcd12864_write_cmd(0x06);                      /* 画面不动,光标右移 */
  292.         lcd12864_write_cmd(LCDSTARTROW);        /* 设置起始行 */
  293. }

  294. /*---------------------------------------------------------------------------*/
  295. static void lcd12864_show_custom_row(uint8_t ucPage,uint8_t ucLine,uint8_t ucWidth,uint8_t *ucaRow)
  296. {
  297.         uint8_t ucCount;
  298.   
  299.         if(ucLine < 64){
  300.           CS1=1;
  301.           CS2=0;
  302.           lcd12864_write_cmd(LCDPAGE + ucPage);
  303.           lcd12864_write_cmd(LCDLINE + ucLine);
  304.           if( (ucLine + ucWidth) < 64 ){
  305.                   for(ucCount = 0; ucCount < ucWidth; ucCount++){
  306.                           lcd12864_write_data(*(ucaRow + ucCount));
  307.                   }
  308.                 }
  309.           else{
  310.                   for(ucCount = 0; ucCount < (64 - ucLine); ucCount++){
  311.                           lcd12864_write_data(*(ucaRow+ucCount));
  312.       }


  313. ……………………

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

所有资料51hei提供下载:
程序+proteus.zip (167.24 KB, 下载次数: 120)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:748788 发表于 2021-3-7 16:32 | 只看该作者
如果横轴和纵轴有时间和温度标尺就更好了
回复

使用道具 举报

板凳
ID:53978 发表于 2021-8-11 12:29 | 只看该作者
谁能把18B20程序换成K型热电偶吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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