ds18b20测温,串口发出,但是数据一直不对
#include "INTRINS.H"
#include "REG52.H"
#define u8 unsigned char
#define u16 unsigned int
typedef unsigned short ushort;
sbit DQ = P2^5; //DS18B20的数据口位P2.5
u8 TPH,t,tt; //存放温度值的高字节
u8 TPL; //存放温度值的低字节
u16 wendu,temp;
void DelayXus(u8 n);
void DS18B20_Reset();
void DS18B20_WriteByte(u8 dat);
u8 DS18B20_ReadByte();
sfr AUXR = 0x8E; //0000,0000 辅助寄存器
//****************************************
//函数声明
//****************************************
void delay_x1ms(u16 t);
void InitUART(void);
void Send_UART(u8 send_data);
//****************************************
// 串口初始化
//****************************************
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//9600波特率,无校验,STC15@11M
//不接收,无发送中断,占用T1定时器
//sfr AUXR = 0x8E; //0000,0000 辅助寄存器
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xC7; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1; //总中断
ES = 1;
}
//****************************************
// 串口发送
//****************************************
void Send_UART(u8 send_data) // Send_UART();
{
SBUF=send_data;
while(!TI);
TI=0;
}
//*********************************************************
//主程序
//*********************************************************
void UARTInterrupt(void) interrupt 4
{
if(RI)
{
RI = 0;
}
else
TI = 0;
}
void main()
{ UartInit() ;
TPL=0;
while(1)
{
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0x44); //开始转换命令
while (!DQ); //等待转换完成
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0xBE); //读暂存存储器命令
TPL = DS18B20_ReadByte(); //读温度低字节
TPH = DS18B20_ReadByte(); //读温度高字节
wendu =TPH; //先把高八位有效数据赋于wendu
wendu <<= 8; //把以上8位数据从wendu低八位移到高八位
wendu = wendu|TPL; //两字节合成一个整型变量
tt = wendu*0.0625; //得到真实十进制温度值
//因为DS18B20可以精确到0.0625度
//所以读回数据的最低位代表的是0.0625度
wendu = tt*10+0.5; //放大十倍
//这样做的目的将小数点后第一位也转换为可显示数字
//同时进行一个四舍五入操作。
Send_UART(wendu);
Delay100ms();
Delay100ms();
} }
/**************************************
延时X微秒(STC12C5A60S2@12M)
不同的工作环境,需要调整此函数
此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
**************************************/
void DelayXus(u8 n)
{
while (n--)
{
_nop_();
_nop_();
}
}
/**************************************
复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
CY = 1;
while (CY)
{
DQ = 0; //送出低电平复位信号
DelayXus(240); //延时至少480us
DelayXus(240);
DQ = 1; //释放数据线
DelayXus(60); //等待60us
CY = DQ; //检测存在脉冲
DelayXus(240); //等待设备释放数据线
DelayXus(180);
}
}
/**************************************
从DS18B20读1字节数据
**************************************/
u8 DS18B20_ReadByte()
{
u8 i;
u8 dat = 0;
for (i=0; i<8; i++) //8位计数器
{
dat >>= 1;
DQ = 0; //开始时间片
DelayXus(1); //延时等待
DQ = 1; //准备接收
DelayXus(1); //接收延时
if (DQ) dat |= 0x80; //读取数据
DelayXus(60); //等待时间片结束
}
return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte(u8 dat)
{
char i;
for (i=0; i<8; i++) //8位计数器
{
DQ = 0; //开始时间片
DelayXus(1); //延时等待
dat >>= 1; //送出数据
DQ = CY;
DelayXus(60); //等待时间片结束
DQ = 1; //恢复数据线
DelayXus(1); //恢复延时
}
}
|