请教C52单片机DS18B20温度传感器串口显的制作
本帖最后由 pdshyh 于 2019-2-21 17:16 编辑准备做电阻的温度系数测试,测量方案是借用论坛老师的原理图见下图,单片机年前年后在论坛相关学习贴学习,下载安装了仿真软件ISIS和烧录软件KEi通过仿真和KEi模拟做了流水灯实验,工作原理基本弄明白。
第一次应用单片机就使用例程比较多的C52单片机,STC89C52 +DS18B20,实物和原理图,购买单片机和DS18B20今天到货。
请教各位老师以下问题以后在制作过程遇到问题在随时请教:
1.我现在手头找到两个STC89C52 +DS18B20程序,读取温度这两个例程那个更好。
2.带串口显示的程序,单片机是UBS口,程序串口部分需要修改不,如何修改,需要帮助。
3.上位机是矿坛老师提供的Visual Studio软件Vb程序也是串口读取,是不是也需要修改。
freegps 发表于 2019-4-12 15:22
我用的是下面这个电路板
谢谢,我刚刚接触单片机,很多需要补课,进展比较慢。 /*********************************************************************************
* 【函数功能】: 利用单线制DS18B20温度传感器串口显示当前的温度值 * 【使用说明】: 波特率:9600 串口数据:温度值整数部分=前一位温度值小数部分后一位*16
**********************************************************************************/
#include <reg52.h>
#include<math.h>
#include <stdio.h>
#define PR printf
#include<intrins.h>
void delay(unsigned int i);
void delay1ms(unsigned int i);
void ReadTemperature(void);
void Init_DS18B20(void);
ReadOneChar();
void WriteOneChar(unsigned char dat);
/* 变量定义 -----------------------------------------------*/
sbit DQ=P3^6; //数据传输线接单片机的相应的引脚
unsigned char tempL=0; //设全局变量
unsigned char tempH=0;
unsigned int sdate;//测量到的温度的整数部分
unsigned char xiaoshu1;//小数第一位
unsigned char xiaoshu2;//小数第二位
unsigned char xiaoshu;//两位小数
bitfg=1; //温度正负标志
unsigned char date;
//******************************
//*****串口初始化函数***********
//******************************
void Initial_com(void)
{
SCON=0x50; //串口选择模式1, 8-bit UART, 使能接收
TMOD|=0x20; //用定时器1设置波特率
TH1=0xFD;
TR1=1;
TI=1; //开启串口中断
}
/*
********************************************************************************
** 函数名称 : delay(unsigned char i)
** 函数功能 : 延时函数 这个延时程序的具体延时时间是time=i*8+10,适用于小于2ms的延时
********************************************************************************
*/
void delay(unsigned int i)
{
while(i--);
}
/*
********************************************************************************
** 函数名称 :delay1ms(unsigned char i)
** 函数功能 : 延时函数
********************************************************************************
*/
void delay1ms(unsigned int i)
{
for(i=124;i>0;i--);//延时124*8+10=1002us
}
/*
********************************************************************************
** 函数名称 : Init_DS18B20(void)
** 函数功能 : 初始化
********************************************************************************
*/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ=1; //DQ先置高
delay(8); //稍延时
DQ=0; //发送复位脉冲
delay(80); //延时(>480us)
DQ=1; //拉高数据线
delay(5); //等待(15~60us)
x=DQ; //用X的值来判断初始化有没有成功,18B20存在的话X=0,否则X=1
delay(20);
}
/*
********************************************************************************
** 函数名称 :ReadOneChar()
** 函数功能 : 读一个字节
********************************************************************************
*/
ReadOneChar()//主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
{
unsigned char i=0; //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期
unsigned char dat=0;
for (i=8;i>0;i--) //一个字节有8位
{
DQ=1;
delay(1);
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
/*
********************************************************************************
** 函数名称 : WriteOneChar(unsigned char dat)
** 函数功能 : 写一个字节
********************************************************************************
*/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,
for(i=8;i>0;i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。
{
DQ=0; //在开始另一个写周期前必须有1us以上的高电平恢复期。
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
/*
********************************************************************************
** 函数名称 : ReadTemperature(void)
** 函数功能 : 读温度值(低位放tempL;高位放tempH;)
********************************************************************************
*/
void ReadTemperature(void)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
delay(125); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
if(tempH>0x7f) //最高位为1时温度是负
{
tempL=~tempL; //补码转换,取反加一
tempH=~tempH+1;
fg=0; //读取温度为负时fg=0
}
sdate = tempL/16+tempH*16; //整数部分
xiaoshu1 = (tempL&0x0f)*10/16; //小数第一位
xiaoshu2 = (tempL&0x0f)*100/16%10;//小数第二位
xiaoshu=xiaoshu1*10+xiaoshu2; //小数两位
}
//*************************
//**********主函数*********
//*************************
main()
{
Initial_com();
while(1)
{
ReadTemperature();
SBUF=sdate;
delay1ms(50000);
delay1ms(50000);
delay1ms(50000);
delay1ms(50000);
SBUF=xiaoshu;
delay1ms(50000);
delay1ms(50000);
delay1ms(50000);
delay1ms(50000);
}
/*所用单片机型号为STC89C52RC,晶振为11.0592MHz*/
#include<reg52.h>
#include<intrins.h>
sbit Bus=P1^1;//数据单总线
unsigned int Ds_Result();//返回最终结果
bit DS_Init();//初始化子函数
void Ds_Write(unsigned char dat);//“写”子函数(用于向总线写命令)
unsigned char Ds_Read();//“读”子函数(用于从总线读值)
void Ds_Change();//开始转换温度
unsigned int Get_Temp();//获取温度子函数
void Delay10us(unsigned int t);//延时10*t微秒
void Delay1ms(unsigned int t);
/*ds18b20 10*t延时函数*/
void Delay10us(unsigned int t)
{
unsigned int i;
for(i=t;i>0;i--)
{
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
}
}
/*dsb8b20 1ms延时函数*/
void Delay1ms(unsigned int t) //误差 0us
{
unsigned char a,b,c;
for(t;t>0;t--)
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
/*ds18b20初始化*/
bit Ds_Init()
{
bit ack;
Bus=0;
Delay10us(60);//最小480,最大960
Bus=1;
Delay10us(6);//15-60us
while(Bus==0);
Bus=1;//让传感器释放总线,避免影响下一步
return ack;//ack为0则响应成功
}
/*ds18b20写时序*/
void Ds_Write(unsigned char dat)//一个写周期为60-120us,主机在15--45us内对信号采样
{
unsigned char mask;
for(mask=0x01;mask!=0;mask<<=1)
{
Bus=0;
_nop_();
if((mask&dat)==0)
{
Bus=0;
}
else
{
Bus=1;
}
Delay10us(6);//15-60us采样
Bus=1;
_nop_();
_nop_();
}
}
/*ds18b20读时序*/
unsigned char Ds_Read()
{
unsigned char dat=0;
unsigned char mask,fmask;
for(mask=0x01;mask!=0;mask<<=1)//一个周期需要至少60us,但采样要在15us内完成
{
Bus=0;
_nop_();
Bus=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(Bus==0)//读0
{
fmask=~mask;
dat=dat&fmask;
}
else
{
dat|=mask;
}
Delay10us(5);
Bus=1;
}
return dat;
}
/*转换温度子函数*/
void Ds_Change()
{
Ds_Init();
Delay1ms(1);
Ds_Write(0xCC);//跳过ROM寻址
Ds_Write(0x44);//启动一次温度转换
}
/*ds18b20获取温度子函数*/
unsigned int Get_Temp()
{
unsigned int temp=0;
unsigned char LSB,MSB;//用来储存数据的第八位与高八位
Ds_Init();
Delay1ms(1);
Ds_Write(0xCC);//跳过寻址
Ds_Write(0xBE);//发送读值命令?
LSB=Ds_Read();
MSB=Ds_Read();
temp=MSB;
temp<<=8;
temp|=LSB;
return temp;
}
/*ds18b20返回最终结果子函数*/
unsigned int Ds_Result()
{
float tp;
unsigned int temp;
Delay1ms(10);//10ms度过不稳定期
Ds_Change();//转换温度
Delay1ms(1000);//延时1s等待转化
temp=Get_Temp();
tp=temp;
temp=tp*0.0625;
return temp;//最终结果为temp
}
int main()
{
unsigned int temp;
temp=Ds_Result();//该值即为结果
} 闻太师 发表于 2019-2-21 18:49
网上找到的18b20代码基本上只能用来玩而难以用在实际的项目里。
实用还有不小差距,还在补课,一步一步学,谢谢。 想先仿真在制作,正在用ISIS做C52单片机DS18B20温度传感器串口显仿真,请教CH340芯片找不到,网上PL2303可以代替也找不到,如何解决谢谢。 pdshyh 发表于 2019-2-22 11:35
想先仿真在制作,正在用ISIS做C52单片机DS18B20温度传感器串口显仿真,请教CH340芯片找不到,网上PL2303可 ...
不需要找元件,串口用模拟仪器仿真:handshake
本帖最后由 pdshyh 于 2019-2-22 19:04 编辑
gxg0000 发表于 2019-2-22 16:42
不需要找元件,串口用模拟仪器仿真
谢谢,网上搜了有说用模拟仪器仿真,就是不知道是什么样子,仿真软件在办公室电脑安装,到单位试着模拟仪器看,有什么情况不明白在请教,谢谢:handshake 本帖最后由 pdshyh 于 2019-2-23 17:02 编辑
keil的stc芯片的文件头装载上了,选择STC89C52,晶振频率选择11.0592,其他很多空格不知道对不对
运行后一堆错误翻译后,雷同错误多,使用的是2楼程序,主程序问题多,各位老师帮忙看看谢谢!
一下是错误:
生成目标“目标1”
正在编译wdcl.c…
wdcl.c(166):错误c132:“initial_-com”:不在形参列表中
wdcl.c(167):错误C141:在“while”附近有语法错误
wdcl.c(167):错误C141:靠近“1”的语法错误
wdcl.c(169):错误c231:“readtemperature”:重新定义
wdcl.c(170):错误c231:“sbuf”:重新定义
wdcl.c(170):错误C247:非地址/常量初始值设定项
wdcl.c(170):错误c231:“sbuf”:重新定义
wdcl.c(171):错误C141:“50000”附近的语法错误
wdcl.c(171):错误c231:“u delay1ms”:重新定义
wdcl.c(172):错误c141:“50000”附近的语法错误
wdcl.c(172):错误c231:“u delay1ms”:重新定义
wdcl.c(173):错误C141:“50000”附近的语法错误
wdcl.c(173):错误C231:“_delay1ms”:重新定义
wdcl.c(174):错误C141:“50000”附近的语法错误
wdcl.c(174):错误c231:“u delay1ms”:重新定义
wdcl.c(175):错误c279:“sbuf”:多次初始化
wdcl.c(175):错误c231:“sbuf”:重新定义
wdcl.c(175):错误C247:非地址/常量初始值设定项
wdcl.c(175):错误c231:“sbuf”:重新定义
wdcl.c(176):错误C141:“50000”附近的语法错误
wdcl.c(176):错误c231:“u delay1ms”:重新定义
wdcl.c(177):错误C141:“50000”附近的语法错误
wdcl.c(177):错误c231:“u delay1ms”:重新定义
wdcl.c(178):错误C141:语法错误接近“50000”
wdcl.c(178):错误c231:“u delay1ms”:重新定义
wdcl.c(179):错误C141:“50000”附近的语法错误
wdcl.c(179):错误c231:“u delay1ms”:重新定义
wdcl.c(180):错误C141:“”附近的语法错误
未创建目标
将3楼例程装入Keil,问题不多但是运行build (F7);
Build target 'Target 1'
compiling wdcl22.c...
WDCL22.C(142): warning C290: missing return value
linking...
Program Size: data=15.1 xdata=0 code=757
"wdcl" - 0 Error(s), 1 Warning(s).
生成目标“目标1”
正在编译wdcl22.c…
wdcl22.c(142):警告c290:缺少返回值
链接…
程序大小:数据=15.1扩展数据=0代码=757
“wdcl”-0个错误,1个警告。
原来Create Hex File没有选择,现在可以生成Hex文件了:L
gxg0000 发表于 2019-2-22 16:42
不需要找元件,串口用模拟仪器仿真
看您的图很方便就找到了,相当于Multisim的仪表,谢谢。 本帖最后由 pdshyh 于 2019-2-24 10:38 编辑
运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。 pdshyh 发表于 2019-2-24 10:31
运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。
CH340、PL2303、FT232...都是 USB 总线上的 UART(TTL)转换芯片,装好之后系统中直接多出一个串口(TTL 电平),像普通串口那样操作即可,所以仿真不需要它,直接监控单片机串口就行。
我当时劝你用我那个 FastAVR,起码语法上和上位机(VB)一致而且我的程序你可以直接拿去用;如果觉得 FastAVR 太老没前途也可以考虑 Arduino,你用 Arduino 现在估计早就搞定了 :lol为何非要用 STC,例程多么,出问题都没人理 ;P
另外调串口不对,如果确保程序无误,可以用波波看看串口的实际波形是什么;类似的 1WBus(DS18b20)也是,调不出来的话上波波。
简单讲,如果实在搞不定 UART,可以在程序里反复发送 0x00,0xff,0xf0,0x0f,0xaa,0x55 这些玩意,因为它们直接用肉眼看波形都能看出对还是不对 :lol
如果波形对了,再根据波波时间轴算波特率对不对,都对了,基本就没问题。不对,你程序有问题 ;P 本帖最后由 gxg0000 于 2019-2-24 20:42 编辑
pdshyh 发表于 2019-2-24 10:31
运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。
单片机、晶振和模拟终端参数设置了吗?
C1、C2和C3都大了点?复位电路也有问题,RST一直高电平(红色)。 本帖最后由 gxg0000 于 2019-2-24 20:31 编辑
这时一个很简单的串口收发程序,供参考一下,在模拟终端上输入字符或数据,能返回同样的字符和数据,Protues具有很高的仿真可信度,下载到硬件上运行,基本上是没有问题的。