pdshyh 发表于 2019-2-21 17:08:04

请教C52单片机DS18B20温度传感器串口显的制作

本帖最后由 pdshyh 于 2019-2-21 17:16 编辑

准备做电阻的温度系数测试,测量方案是借用论坛老师的原理图见下图,单片机年前年后在论坛相关学习贴学习,下载安装了仿真软件ISIS和烧录软件KEi通过仿真和KEi模拟做了流水灯实验,工作原理基本弄明白。

第一次应用单片机就使用例程比较多的C52单片机,STC89C52 +DS18B20,实物和原理图,购买单片机和DS18B20今天到货。

请教各位老师以下问题以后在制作过程遇到问题在随时请教:
1.我现在手头找到两个STC89C52 +DS18B20程序,读取温度这两个例程那个更好。
2.带串口显示的程序,单片机是UBS口,程序串口部分需要修改不,如何修改,需要帮助。
3.上位机是矿坛老师提供的Visual Studio软件Vb程序也是串口读取,是不是也需要修改。

pdshyh 发表于 2019-4-14 14:34:03

freegps 发表于 2019-4-12 15:22
我用的是下面这个电路板




谢谢,我刚刚接触单片机,很多需要补课,进展比较慢。

pdshyh 发表于 2019-2-21 17:12:18

/*********************************************************************************
* 【函数功能】: 利用单线制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);                                     
          }

pdshyh 发表于 2019-2-21 17:13:08


/*所用单片机型号为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:20

pdshyh 发表于 2019-2-22 10:38:07

闻太师 发表于 2019-2-21 18:49
网上找到的18b20代码基本上只能用来玩而难以用在实际的项目里。

实用还有不小差距,还在补课,一步一步学,谢谢。

pdshyh 发表于 2019-2-22 11:35:35

想先仿真在制作,正在用ISIS做C52单片机DS18B20温度传感器串口显仿真,请教CH340芯片找不到,网上PL2303可以代替也找不到,如何解决谢谢。

gxg0000 发表于 2019-2-22 16:42:45

pdshyh 发表于 2019-2-22 11:35
想先仿真在制作,正在用ISIS做C52单片机DS18B20温度传感器串口显仿真,请教CH340芯片找不到,网上PL2303可 ...

不需要找元件,串口用模拟仪器仿真:handshake

pdshyh 发表于 2019-2-22 19:03:30

本帖最后由 pdshyh 于 2019-2-22 19:04 编辑

gxg0000 发表于 2019-2-22 16:42
不需要找元件,串口用模拟仪器仿真

谢谢,网上搜了有说用模拟仪器仿真,就是不知道是什么样子,仿真软件在办公室电脑安装,到单位试着模拟仪器看,有什么情况不明白在请教,谢谢:handshake

pdshyh 发表于 2019-2-23 15:12:02

本帖最后由 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

pdshyh 发表于 2019-2-23 16:10:09

gxg0000 发表于 2019-2-22 16:42
不需要找元件,串口用模拟仪器仿真

看您的图很方便就找到了,相当于Multisim的仪表,谢谢。

pdshyh 发表于 2019-2-24 10:31:11

本帖最后由 pdshyh 于 2019-2-24 10:38 编辑

运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。

washu 发表于 2019-2-24 15:52:53

pdshyh 发表于 2019-2-24 10:31
运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。

CH340、PL2303、FT232...都是 USB 总线上的 UART(TTL)转换芯片,装好之后系统中直接多出一个串口(TTL 电平),像普通串口那样操作即可,所以仿真不需要它,直接监控单片机串口就行。

我当时劝你用我那个 FastAVR,起码语法上和上位机(VB)一致而且我的程序你可以直接拿去用;如果觉得 FastAVR 太老没前途也可以考虑 Arduino,你用 Arduino 现在估计早就搞定了 :lol为何非要用 STC,例程多么,出问题都没人理 ;P

另外调串口不对,如果确保程序无误,可以用波波看看串口的实际波形是什么;类似的 1WBus(DS18b20)也是,调不出来的话上波波。



washu 发表于 2019-2-24 15:56:33

简单讲,如果实在搞不定 UART,可以在程序里反复发送 0x00,0xff,0xf0,0x0f,0xaa,0x55 这些玩意,因为它们直接用肉眼看波形都能看出对还是不对 :lol

如果波形对了,再根据波波时间轴算波特率对不对,都对了,基本就没问题。不对,你程序有问题 ;P

gxg0000 发表于 2019-2-24 20:15:54

本帖最后由 gxg0000 于 2019-2-24 20:42 编辑

pdshyh 发表于 2019-2-24 10:31
运行串口显示例程,仿真一帧显示,在终端显示3个图块不是数字字符,希望高手看看对不对,给与指教。

单片机、晶振和模拟终端参数设置了吗?
C1、C2和C3都大了点?复位电路也有问题,RST一直高电平(红色)。

gxg0000 发表于 2019-2-24 20:30:30

本帖最后由 gxg0000 于 2019-2-24 20:31 编辑

这时一个很简单的串口收发程序,供参考一下,在模拟终端上输入字符或数据,能返回同样的字符和数据,Protues具有很高的仿真可信度,下载到硬件上运行,基本上是没有问题的。
页: [1] 2 3 4 5 6 7
查看完整版本: 请教C52单片机DS18B20温度传感器串口显的制作