打印
[STC单片机]

STC90C52RC和STC12LE5608AD用DS18B20测温程序差别

[复制链接]
1239|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hxjlm|  楼主 | 2015-7-17 17:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*********************************************************************************************
* 程序名 * DS18B20温度实验 串口助手显示 小数点后4位精度
* 公司名 * 石家庄芯巢科技
* 编写人 *  何新建 
* 日  期 * 2015年7月16日
* 支  持 * STC90C52RC 11.0592MHz(12T)/单倍速
* 接  口 * P2.1接DS18b20
* 说  明 * 实验成功
*********************************************************************************************/
#include<reg52.h>  
#include <intrins.h>   
  
typedef unsigned char uint8;  
typedef unsigned int  uint16;  
typedef          char int8;  
typedef          int int16;

uint16 TempDec;//存放小数后4位数
bit fbj;//负号标记   
sbit DQ=P2^1;    //温度输入口DQ  
sbit led=P2^0; //LED
void nops()//延时子函数无返回值 约4us
//误差 -0.202256944444us
{
    unsigned char a;
    for(a=1;a>0;a--);
}   

void delay1us(void)   //11.0592MHz(6T)1.0851us误差 -0.000030555556us
{
}
void delay10us(int16 n)   //误差 -0.234375us
{
    unsigned char a;
         int16 b;//变量b如是 unsingned char型,串口助手无显示
    for(b=0;b<n;b++)
        for(a=5;a>0;a--);
}   
void delay1ms(int16 n)   //误差 -0.108506944445us
{
   unsigned char a,b;
        int16 c;//变量c如是 unsingned char型,串口助手无显示
   for(c=0;c<n;c++)
      for(b=4;b>0;b--)
         for(a=113;a>0;a--);
}   
  
/*******************************************
*DS1820复位及存在检测(通过存在脉冲可以判断DS1820是否损坏)
*函数名称:DS1820_Reset()
*说明:函数返回一个位标量(0或1)flag=0存在,反之flag=1不存在
*******************************************/
bit DS18b20_reset()
{
        bit flag;
       
        DQ=0;//拉低总线
        delay10us(48);//延时480us
        DQ=1;//释放总线
        delay10us(6);//延时60us
        flag=DQ;//对数据脚采样

        return(flag);//根据flag的值可知DS1820是否存在或损坏,可加声音告警提示DS1820故障
}  
  
/*
* 18B20写1个字节函数
* 向1-WIRE总线上写一个字节
*/  
void write_byte(uint8 val)  
{  
        uint8 i;  
  
        for (i=0; i<8; i++)  
   {  
      DQ = 1;  
                delay1us();     //两次传送间隔大于1us  
                DQ = 0;  
      nops(); //4us  
      DQ = val & 0x01;      //最低位移出  
      delay10us(6);           //60us  (30US)  
      val >>= 1;          //右移一位  
    }  
    DQ = 1;      
}  

//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
  
uint8 read_byte(void)  

{  
        uint8 i, value=0;  
  
        for (i=0; i<8; i++)  
        {  
                value >>= 1;//让从总线上读到的位数据,依次从高位移动到低位?
                DQ=1;  
                delay1us();//1us
                DQ = 0;//将总线拉低,要在1us之后释放总线  
                nops();   //4us //至少维持了1us,表示读时序开始
                DQ = 1;  
                nops();   //4us   
                if (DQ)//控制器进行采样  
                        value|=0x80;//若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0  
      delay10us(6);           //60us  
        }  
    DQ=1;  

    return value;  
}  
/*
* 启动温度转换
*/  
void start_temp_sensor(void)  
{  
        DS18b20_reset(); //DS18b20复位
        delay1ms (1); // 延时1毫秒
        write_byte(0xCC); // 发Skip ROM命令 写入跳过序列号命令字
        write_byte(0x44);// 发转换命令 写入温度转换命令字
}  
/*
* 读出温度
*/  
int16 read_temp(void)   
{        
        unsigned int value; //存放温度数值
        uint8 low, high;//存放温度高低字节

   DS18b20_reset();  // 复位
        delay1ms (1); // 延时1毫秒
   write_byte(0xCC); // 发Skip ROM命令  
   write_byte(0xBE); // 发读命令 写入读取数据令字                
        low = read_byte();//连续读取两个字节数据 先读出的是低位数据   
        high = read_byte();

        if(high&0xfc)//判断是正温度还是负温度读数 高8位的前6位是否为1,是为负温度
        {//负温度读数求补,取反加1,判断低8位是否有进位
                fbj=1;//负号标记
                value=((high<<8)|low);//高低字节组合
                value=(((~value)+1)*0.0625)+2.6;//求反补1
                TempDec=((~low)+1)&0x0f;
                TempDec=TempDec*625;
        }
        else
        {
                fbj=0;
                value=(((high<<8)|low)*0.0625)-2.6;//小数点以前的数2.6是误差
                TempDec=(low&0x0f)*625;//小数点以后4位数
        }         

        return value;//返回温度值
}  
/**
* UART初始化
* 波特率:9600
*/  
void uart_init(void)  
{  
        TMOD = 0x21;        // 定时器1工作在方式2(自动重装)T0用于定时,T1用于波特串口初始化函数  
        SCON = 0x50;        // 10位uart,允许串行接受  //01010000设置串行通信方式1 REN=1允许接收  
        TH1 = 0xfd; //晶振为11.0592波特率为9600,设定的参数为9600,N,8,1
        TL1 = 0xfd;   
        TR1=1;   //启动定时器/计数器1  
}  
//请用实际行动支持宏晶STC大陆本土MCU统一全球市场
/*
void uart_init(void)                //9600bps@11.0592MHz
{
        TMOD = 0x21;        // 定时器1工作在方式2(自动重装)T0用于定时,T1用于波特串口初始化函数  
        SCON = 0x50;        // 10位uart,允许串行接受  //01010000设置串行通信方式1 REN=1允许接收

        TH1=0xfd;//9600初值
        TL1=0xfd;//9600重装值
        TR1=1;//启动定时器
        SM1=1;//这1项关闭PC端“串口助手”接收的是乱码
}
*/  
/**
* UART发送一字节
*/  
void UART_Send_Byte(uint8 dat)  
{  
        SBUF = dat;//数据送发送缓冲区  
        while (!TI);//等待发送完成同(TI==0)  
        TI = 0;//清除发送完成标志位  
}  
  
/**
* 将数据转换成ASC码并通过UART发送出去
*/  
void UART_Send_Dat(uint8 dat)    //100度以下温度可用  
{  
        uint8 bw,sw;

        UART_Send_Byte(' ');//每行开始发送3个空格,发送一个空格,什么也不显示
        UART_Send_Byte(' ');//发送一个空格,什么也不显示
        UART_Send_Byte(' ');//发送一个空格,什么也不显示

        if(fbj==1)//判断是正温度还是负温度读数 正为0;负为1;
        {
                UART_Send_Byte('-');//是向串口发送负号
        }
        bw=dat/100;//取出百位数值
        if(bw==0)//如果百位是0
        {} //如果百位是0, 什么也不显示
        else//否则发送百位数值
        {
                UART_Send_Byte(dat/100+0x30);//取百位转换为ASCII码
        }
        sw=(dat%100)/10;//取出十位数值
        if(bw|sw==0)//如果百位和十位都是0(bw==0|sw==0)
        {}//十位百位都是0,十位0也不显示
        else//否则发送十位数值
        {
                UART_Send_Byte((dat%100)/10+0x30);//取十位转换为ASCII码
        }
        UART_Send_Byte((dat%100)%10+0x30);//取个为转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(0x2e);//发送小数点
        UART_Send_Byte(TempDec/1000+0x30);//取小数十分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte((TempDec%1000)/100+0x30);//取小数百分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(((TempDec%1000)%100)/10+0x30);//取小数千分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(((TempDec%1000)%100)%10+0x30);//取小数万分位转换为ASCII码+0x30与+'0'同一个事
   UART_Send_Byte(0x60);//发送温度字符  
   UART_Send_Byte('C');//发送温度字符
}  
   
/*
主函数
*/  
void main()  
{  
        int16 ans;//定义变量
        bit a;//定义局部位变量
        a=DS18b20_reset();//调用复位函数判断DS18b20好坏  
        if(a==0)led=0;//如果DS18b20是好的发光管亮
   uart_init();//调用串口初始化子函数  
   
   while(1)  
   {  
                start_temp_sensor();//调用温度转换子函数,
                led=~led;//熄灭发光管
           delay1ms (2000); // 延时1秒  
      ans=read_temp();//调用读出温度子函数其值赋予ans  

                UART_Send_Dat(ans); //待发送温度值进行转换并发送   
   }   
}
********************************************************************
*********************************************************************
**********************************************************************
/*********************************************************************************************
* 程序名 * DS18B20温度实验 串口助手显示 小数点后4位精度
* 公司名 * 石家庄芯巢科技
* 编写人 *  何新建 
* 日  期 * 2013年9月11日
* 支  持 * STC12LE5608AD3.3V 11.0592MHz
* 接  口 * P2.1接DS18b20 串口助手9600/8/N/1
* 说  明 * 实验通过正负温度显示
*********************************************************************************************/
#include<reg52.h>  
#include <intrins.h>   
  
typedef unsigned char uint8;  
typedef unsigned int  uint16;  
typedef          char int8;  
typedef          int int16;

uint16 TempDec;//存放小数后4位数
bit fbj;//负号标记   
sbit DQ=P2^1;    //温度输入口DQ  
sbit led=P2^0; //LED
void nops()//延时子函数无返回值  
{  
    _nop_();
    _nop_();  
    _nop_();  
    _nop_();  
}   

void delay_us(uint16 x)//延时子函数有返回值
{
        uint16 i;
        x=x*5/4;
        for(i=0;i<x;i++);
}
  
void delay_ms(uint16 n)//延时子函数有返回值  
{  
    uint8 m=120;  
  
    while (n--)  
            while (m--);  
}   
  
/*******************************************
*DS1820复位及存在检测(通过存在脉冲可以判断DS1820是否损坏)
*函数名称:DS1820_Reset()
*说明:函数返回一个位标量(0或1)flag=0存在,反之flag=1不存在
*******************************************/
bit DS18b20_reset()
{
        bit flag;
       
        DQ=0;//拉低总线
        delay_us(500);//延时480us
        DQ=1;//释放总线
        delay_us(60);//延时60us
        flag=DQ;//对数据脚采样

        return(flag);//根据flag的值可知DS1820是否存在或损坏,可加声音告警提示DS1820故障
}  
  
/*
* 18B20写1个字节函数
* 向1-WIRE总线上写一个字节
*/  
void write_byte(uint8 val)  
{  
        uint8 i;  
  
        for (i=0; i<8; i++)  
   {  
      DQ = 1;  
                _nop_();     //两次传送间隔大于1us  
                DQ = 0;  
      nops(); //4us  
      DQ = val & 0x01;      //最低位移出  
      delay_us(60);           //60us  (30US)  
      val >>= 1;          //右移一位  
    }  
    DQ = 1;      
}  

//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
  
uint8 read_byte(void)  

{  
        uint8 i, value=0;  
  
        for (i=0; i<8; i++)  
        {  
                value >>= 1;//让从总线上读到的位数据,依次从高位移动到低位?
                DQ=1;  
                _nop_();
                DQ = 0;//将总线拉低,要在1us之后释放总线  
                nops();   //4us //至少维持了1us,表示读时序开始
                DQ = 1;  
                nops();   //4us   
                if (DQ)//控制器进行采样  
                        value|=0x80;//若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0  
      delay_us(60);           //60us  
        }  
    DQ=1;  

    return value;  
}  
/*
* 启动温度转换
*/  
void start_temp_sensor(void)  
{  
        DS18b20_reset(); //DS18b20复位
        delay_ms (1); // 延时1毫秒
        write_byte(0xCC); // 发Skip ROM命令 写入跳过序列号命令字
        write_byte(0x44);// 发转换命令 写入温度转换命令字
}  
/*
* 读出温度
*/  
int16 read_temp(void)   
{        
        unsigned int value; //存放温度数值
        uint8 low, high;//存放温度高低字节

   DS18b20_reset();  // 复位
        delay_ms (1); // 延时1毫秒
   write_byte(0xCC); // 发Skip ROM命令  
   write_byte(0xBE); // 发读命令 写入读取数据令字                
        low = read_byte();//连续读取两个字节数据 先读出的是低位数据   
        high = read_byte();

        if(high&0xfc)//判断是正温度还是负温度读数 高8位的前6位是否为1,是为负温度
        {//负温度读数求补,取反加1,判断低8位是否有进位
                fbj=1;//负号标记
                value=((high<<8)|low);//高低字节组合
                value=(((~value)+1)*0.0625)+2.6;//求反补1
                TempDec=((~low)+1)&0x0f;
                TempDec=TempDec*625;
        }
        else
        {
                fbj=0;
                value=(((high<<8)|low)*0.0625)-2.6;//小数点以前的数
                TempDec=(low&0x0f)*625;//小数点以后4位数
        }         

        return value;//返回温度值
}  
/**
* UART初始化
* 波特率:9600
*/  
void uart_init(void)  
{  
        TMOD = 0x21;        // 定时器1工作在方式2(自动重装)T0用于定时,T1用于波特串口初始化函数  
        SCON = 0x50;        // 10位uart,允许串行接受  //01010000设置串行通信方式1 REN=1允许接收  
        TH1 = 0xfd; //晶振为11.0592波特率为9600,设定的参数为9600,N,8,1
        TL1 = 0xfd;   
        TR1=1;   //启动定时器/计数器1  
}  
  
/**
* UART发送一字节
*/  
void UART_Send_Byte(uint8 dat)  
{  
        SBUF = dat;//数据送发送缓冲区  
        while (!TI);//等待发送完成同(TI==0)  
        TI = 0;//清除发送完成标志位  
}  
  
/**
* 将数据转换成ASC码并通过UART发送出去
*/  
void UART_Send_Dat(uint8 dat)    //100度以下温度可用  
{  
        uint8 bw,sw;

        UART_Send_Byte(' ');//每行开始发送3个空格,发送一个空格,什么也不显示
        UART_Send_Byte(' ');//发送一个空格,什么也不显示
        UART_Send_Byte(' ');//发送一个空格,什么也不显示

        if(fbj==1)//判断是正温度还是负温度读数 正为0;负为1;
        {
                UART_Send_Byte('-');//是向串口发送负号
        }
        bw=dat/100;//取出百位数值
        if(bw==0)//如果百位是0
        {} //如果百位是0, 什么也不显示
        else//否则发送百位数值
        {
                UART_Send_Byte(dat/100+0x30);//取百位转换为ASCII码
        }
        sw=(dat%100)/10;//取出十位数值
        if(bw|sw==0)//如果百位和十位都是0(bw==0|sw==0)
        {}//十位百位都是0,十位0也不显示
        else//否则发送十位数值
        {
                UART_Send_Byte((dat%100)/10+0x30);//取十位转换为ASCII码
        }
        UART_Send_Byte((dat%100)%10+0x30);//取个为转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(0x2e);//发送小数点
        UART_Send_Byte(TempDec/1000+0x30);//取小数十分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte((TempDec%1000)/100+0x30);//取小数百分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(((TempDec%1000)%100)/10+0x30);//取小数千分位转换为ASCII码+0x30与+'0'同一个事
        UART_Send_Byte(((TempDec%1000)%100)%10+0x30);//取小数万分位转换为ASCII码+0x30与+'0'同一个事
   UART_Send_Byte(0x60);//发送温度字符  
   UART_Send_Byte('C');//发送温度字符
}  
   
/*
主函数
*/  
void main()  
{  
        int16 ans;//定义变量
        bit a;//定义局部位变量
        a=DS18b20_reset();//调用复位函数判断DS18b20好坏  
        if(a==0)led=0;//如果DS18b20是好的发光管亮
   uart_init();//调用串口初始化子函数  
   
   while(1)  
   {  
                start_temp_sensor();//调用温度转换子函数,
           delay_ms (2000); // 延时1秒  
                led=1;//熄灭发光管
      ans=read_temp();//调用读出温度子函数其值赋予ans  
      
                UART_Send_Dat(ans); //待发送温度值进行转换并发送   
   }   
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

117

帖子

0

粉丝