找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机,18B20,1602温度计+串口通信,实际温度计 上位机程序VS2010 C++ MFC

  [复制链接]
跳转到指定楼层
楼主
ZMRGHY 发表于 2020-11-21 01:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
制作出来的实物图如下:




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


上位机:


安装程序解压到同一目录下。再运行setup安装。。。。

温度计.exe
编写环境Win10 x64.     VS2010 x86  C++ MFC
测试环境Win10 x64.   

在32位系统上,能不能正常使用还不清楚。
所以公布了源代码文件,如果在32位系统上,不能正常使用。
请使用源代码文件,在32位系统上重新生成一下应用程序。。。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include "math.h"

  3. bit flag1s = 0, _up = 0;          //1s定时标志
  4. unsigned char T0RH = 0;  //T0重载值的高字节
  5. unsigned char T0RL = 0;  //T0重载值的低字节

  6. void ConfigTimer0(unsigned int ms);
  7. unsigned char IntToString(unsigned char *str, int dat);
  8. extern bit Start18B20();
  9. extern bit Get18B20Temp(int *temp);
  10. extern void InitLcd1602();
  11. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

  12. //串口初始化函数
  13. void InitUART()
  14. {
  15.                 //IP = 0x10;
  16.                 TMOD &= 0x0F;
  17.     TMOD |= 0x20;
  18.     SCON = 0x50;
  19.     TH1 = 0xF3;
  20.     TL1 = TH1;
  21.     PCON = 0x00;
  22.     EA = 1;
  23.     ES = 1;
  24.     TR1 = 1;
  25. }

  26. //串口发送1字节数据
  27. void SendOneByte(unsigned char c)
  28. {
  29.     SBUF = c;
  30.     while(!TI);
  31.     TI = 0;
  32. }
  33. void main()
  34. {
  35.     bit res;
  36.     int temp, former=0xffff;        //读取到的当前温度值
  37.     int intT, decT;  //温度值的整数和小数部分
  38.     unsigned char len;
  39.     unsigned char str[12];
  40.                
  41.                 IP = 0x10;
  42.                 InitUART();
  43.     // EA = 1;            //开总中断
  44.     ConfigTimer0(10);  //T0定时10ms
  45.     Start18B20();      //启动DS18B20
  46.     InitLcd1602();     //初始化液晶
  47.    
  48.     while (1)
  49.     {
  50.         if (flag1s || _up)  //每秒更新一次温度
  51.         {
  52.             flag1s = 0;
  53.             res = Get18B20Temp(&temp);  //读取当前温度
  54.             if (res && ((abs(temp-former) >= 4)||_up))                 //读取成功时,刷新当前温度显示
  55.             {
  56.                                                                 former = temp;                                                                //记录新的温度
  57.                                                                 _up = 0;
  58.                                                                 SendOneByte((unsigned char) (temp/256));
  59.                                                                 SendOneByte((unsigned char) (temp%256));
  60.                 intT = temp >> 4;             //分离出温度值整数部分
  61.                 decT = temp & 0xF;            //分离出温度值小数部分
  62.                 len = IntToString(str, intT); //整数部分转换为字符串
  63.                 str[len++] = '.';             //添加小数点
  64.                 decT = (int)((decT*100) * 0.0625 + 0.5);        //二进制的小数部分转换为1位十进制位
  65.                 str[len++] = decT/10 + '0';      //十进制小数位再转换为ASCII字符
  66.                                                                 str[len++] = decT%10 + '0';
  67.                                                                 str[len++] = 'C';
  68.                 while (len < 7)               //用空格补齐到6个字符长度
  69.                 {
  70.                     str[len++] = ' ';
  71.                 }
  72.                 str[len] = '\0';              //添加字符串结束符
  73.                 LcdShowStr(0, 0, str);        //显示到液晶屏上
  74.             }
  75.             else                        //读取失败时,提示错误信息
  76.             {
  77.                                                                 if(!res)
  78.                                                                         LcdShowStr(0, 0, "error!");
  79.             }
  80.             Start18B20();               //重新启动下一次转换
  81.         }
  82.     }
  83. }
  84. /* 整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
  85. unsigned char IntToString(unsigned char *str, int dat)
  86. {
  87.     signed char i = 0;
  88.     unsigned char len = 0;
  89.     unsigned char buf[6];
  90.    
  91.     if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号
  92.     {
  93.         dat = -dat;
  94.         *str++ = '-';
  95.         len++;
  96.     }
  97.     do {          //先转换为低位在前的十进制数组
  98.         buf[i++] = dat % 10;
  99.         dat /= 10;
  100.     } while (dat > 0);
  101.     len += i;     //i最后的值就是有效字符的个数
  102.     while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上
  103.     {
  104.         *str++ = buf[i] + '0';
  105.     }
  106.     *str = '\0';  //添加字符串结束符
  107.    
  108.     return len;   //返回字符串长度
  109. }
  110. /* 配置并启动T0,ms-T0定时时间 */
  111. void ConfigTimer0(unsigned int ms)
  112. {
  113.     unsigned long tmp;  //临时变量
  114.    
  115.     tmp = 12000000 / 12;      //定时器计数频率
  116.     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  117.     tmp = 65536 - tmp;        //计算定时器重载值
  118.     tmp = tmp + 15;           //补偿中断响应延时造成的误差
  119.     T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
  120.     T0RL = (unsigned char)tmp;
  121.     TMOD &= 0xF0;   //清零T0的控制位
  122.     TMOD |= 0x01;   //配置T0为模式1
  123.     TH0 = T0RH;     //加载T0重载值
  124.     TL0 = T0RL;
  125.     ET0 = 1;        //使能T0中断
  126.     TR0 = 1;        //启动T0
  127. }
  128. /* T0中断服务函数,完成1秒定时 */
  129. void InterruptTimer0() interrupt 1
  130. {
  131.     static unsigned char tmr1s = 0;
  132.    
  133.     TH0 = T0RH;  //重新加载重载值
  134.     TL0 = T0RL;
  135.     tmr1s++;
  136.     if (tmr1s >= 100)  //定时1s
  137.     {
  138.         tmr1s = 0;
  139.                                 if(!flag1s)
  140.                                         flag1s = 1;
  141.     }
  142. }

  143. //串口中断服务函数,
  144. void UARTInterrupt(void) interrupt 4
  145. {
  146.                 char ch=0;
  147.     if(RI)
  148.     {
  149.         RI = 0;
  150.                                 ch = SBUF;
  151.                                 if((ch=='1') && !_up)
  152.                                         _up = 1;
  153.         //add your code here!
  154.     }/*
  155.     else
  156.         TI = 0;*/
  157. }
复制代码

所有资料51hei提供下载:
温度计。单片机 仿真.rar (106.64 KB, 下载次数: 5)
温度计。上位机.rar (130.59 KB, 下载次数: 5)
安装程序.7z (13.13 MB, 下载次数: 6)

评分

参与人数 2黑币 +110 收起 理由
changhz + 10
admin + 100 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

来自 2#
 楼主| ZMRGHY 发表于 2020-11-21 20:19 | 只看该作者
更正说明。。。。
设计开发时,一直用的是开发板。

显示的都是实时温度。。。。采集不到负温度。。。。
今天自己在仿真中发现。。。当负温度时,1602和电脑上显示不一样,而且两个都与DS18B20显示不一样。。。
查找原因,发现思路没错,细节决定成败。。。

在C51中,
int i;
-32768<= i <= 32767

unsigned int  i;
0 <=  i   <=  65535

unsigned char LSB, MSB;

当i为int变量时。

i = (int)MSB<<8;

i += LSB    与    i |= LSB  两者的区别是什么。。。


当i为int变量时。
MSB = i/256; LSB = i%256;      与     MSB = i>>8;    LSB =  i & 0xff    的区别是什么呀。。。。。

找到原因,才知道很简单。。。。
1、修改了DS18B20.c中的读温度函数。。。。
2、修改了main.c中转换字符串函数。。。。。
有一句话与大家共勉。。。。。。。。
编程入门很重要,养成良好的书写习惯,才是编程的必修课。。。。

keil.rar

45.46 KB, 下载次数: 1, 下载积分: 黑币 -5

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
 楼主| ZMRGHY 发表于 2020-11-21 01:19 | 只看该作者
忘了,还有一个工具,仿真需虚拟串口

vspd.zip

4.72 MB, 下载次数: 2, 下载积分: 黑币 -5

回复

使用道具 举报

地板
51hei团团 发表于 2020-11-21 01:52 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

5#
 楼主| ZMRGHY 发表于 2020-11-21 04:24 | 只看该作者
51hei团团 发表于 2020-11-21 01:52
好资料,51黑有你更精彩!!!

团团,早上好
回复

使用道具 举报

6#
zkele 发表于 2020-11-21 07:49 | 只看该作者
51黑有你更精彩!!!下载一份有空学习一下
回复

使用道具 举报

7#
renzaijiangnan 发表于 2020-11-21 14:00 | 只看该作者
好东东
回复

使用道具 举报

8#
 楼主| ZMRGHY 发表于 2020-11-21 22:02 | 只看该作者

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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