资源描述
/*
温度传感器头文件(.h文件);
*/
/*
ds18b20程序。
本程序使用说明:
在使用之前必须在相应的代码文件里全局位置加入一
段代码:
// #define FLOAT_MODE 1
#if FLOAT_MODE
unsigned char Temperature[8]; //小数模式需要8个
字节;
#define Temp_Len_ 7 //温度值字符串有效长度;
#else
unsigned char Temperature[5]; //整数模式需要5个
字节;
#define Temp_Len_ 4 //温度值字符串有效长度;
#endif
加入此段代码后可以通过是否注释 #define
FLOAT_MODE 1
这句代码来选择是获取整数温度还是获取小数温度,注释后
为获
取整数温度。
获取温度的函数如下:
TemperatureConver();
不需要参数,结果以字符串的形式保存在
Temperature[x]中,
通过字符串操作方式操作该数组变量;
该程序在cc2530采用外部晶振32MHZ时使用,如果频率
不是
32MHZ,会因为延时不正确导致时序问题,故在其他频率下
使用
需自行调试延时函数的函数体。
void ds18b20_delay_us(unsigned int x)
*/
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include <ioCC2530.h>
//引脚定义,即ds18b20的数据线;
#define Ds18b20_Data P0_7 //根据实际更改;
/*//////////////////////////////////////
开启下列定义表示读取的温度精确
到小数,注释后精度为整数;
*///////////////////////////////////////
//默认注释// #define FLOAT_MODE 1 //默 认 下 不 开 启 ;<<<<<<-----------//自 行 更 改;
////////////////////////////////////////
#if FLOAT_MODE
extern unsigned char Temperature[8]; //小数模式需要8个字节;
#define Temp_Len_ 7 //温度值字符串有效长度;
#else
extern unsigned char Temperature[5]; //整数模式需要5个字节;
#define Temp_Len_ 4 //温度值字符串有效长度;
#endif
//端口配置;
#define INPUT_MODE P0DIR &= 0x7f
#define OUTPUT_MODE P0DIR |= 0x80
//32MHZ下,供温度传感器使用的us延时函数;
void ds18b20_delay_us(unsigned int x);
//ds18b20初始化函数;
unsigned char DS18B20_Init(void);
//读一个字节函数:
unsigned char ReadByte(void);
//写一个字节函数;
void WriteByte(unsigned char Byte);
//读取温度函数;
unsigned int ReadTemperature(void);
//温度转换函数;
void TemperatureConver(void);
#endif
/*
温度传感器源文件;
*/
#include "ds18b20.h"
//#include "OnBoard.h"
void ds18b20_delay_us(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<2;j++);
}
/*
while(x--)
{
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
}
*/
}
unsigned char DS18B20_Init(void)
{
unsigned char IS_FINISH = 0; //若ds18b20复位成功,置1,默认为0;
unsigned int Count = 0; //获取ds18b20复位成功与否时防止超时的变量;
OUTPUT_MODE; //温度传感器IO口为输出模式;
Ds18b20_Data = 1; //初始时确保ds18b20数据线为高;
ds18b20_delay_us(100); //稍作延时;
Ds18b20_Data = 0; //复位ds18b20;
ds18b20_delay_us(600);//精确延时,必须满足480us~960us;
Ds18b20_Data = 1; //在480us~960us后拉高数据线,ds18b20会在在15~60us产生脉冲;
ds18b20_delay_us(40);//精确延时,15~60us后接收数据线上60~240us的存在脉冲;
INPUT_MODE; //温度传感器IO口为输入模式;
do
{
Count++;
IS_FINISH = Ds18b20_Data; //读IO口状态;
}
while((IS_FINISH != 0) && (Count<400)); //大约3ms,这段时间等待响应;
OUTPUT_MODE; //温度传感器IO口为输出模式;
Ds18b20_Data = 1; //归还数据线;
ds18b20_delay_us(100); //稍作延时;
//如果读取的脉冲为0,说明初始化成功,否则失败;
return IS_FINISH;
}
unsigned char ReadByte(void)
{
unsigned char i,Byte = 0; //Byte为读取的字节;
OUTPUT_MODE; //温度传感器IO口为输出模式;
Ds18b20_Data = 1; //初始时确保ds18b20数据线为高;
ds18b20_delay_us(100); //稍作延时;
for(i=0;i<8;i++) //8位,读8次;
{
Byte >>= 1; //腾出一位用于存入下次的读取位值;
Ds18b20_Data = 0; //ds18b20在拉低4us后沿拉高产生10us的读间隙;
ds18b20_delay_us(4); //精确延时;
Ds18b20_Data = 1; //拉高;
ds18b20_delay_us(2); //稍作延时;
if(Ds18b20_Data == 1) //判断数据位是否为高,若高,做运算,低则保留;
{ Byte |= 0x80; } //最高位置1;
ds18b20_delay_us(20); //稍作延时;
}
return Byte;
}
void WriteByte(unsigned char Byte)
{
unsigned char i;
OUTPUT_MODE; //温度传感器IO口为输出模式;
Ds18b20_Data = 1; //初始时确保ds18b20数据线为高;
ds18b20_delay_us(100); //稍作延时;
for(i=0;i<8;i++)
{
Ds18b20_Data = 0;//拉低数据线后的15us为写入位时间间隙;
Ds18b20_Data = Byte & 0x01; //数据位写入,写入后的45us内ds18b20采样,完成写//入位工作;
ds18b20_delay_us(40); //40us延时后保证采样成功;
Ds18b20_Data = 1; //数据线重新置高;
Byte >>= 1;//移出已经写入的位;
}
ds18b20_delay_us(10); //稍作延时;
}
/*
读取温度的步骤:
1.启动温度转换;(1.复位 2.发Skip ROM命令,即0xcc 3.发Convert T命令,即0x44);
2.复位;
3.发Skip ROM命令,即0xcc;
4.读ds18b20寄存器命令,即0xbe;
5.读两字节温度;(低字节 高字节)
6.温度格式转换;
*/
unsigned int ReadTemperature(void)
{
unsigned int Temperature = 0, //最终的返回值,同时也用来存放高字节;
low = 0; //低字节;
DS18B20_Init(); //复位;
WriteByte(0xcc); //skip ROM命令;
WriteByte(0x44); //Conver T命令;
ds18b20_delay_us(5); //稍作延时;
DS18B20_Init(); //复位;
WriteByte(0xcc); //skip ROM命令;
WriteByte(0xbe); //读寄存器命令,前两个寄存器存放温度值;
low = ReadByte(); //读取第一个寄存器,即低位温度值;
Temperature = ReadByte(); //读取第二个寄存器,即高位温度值;
Temperature <<= 8; //高字节移动到高8位,低8位用来放低字节;
Temperature += low; //存入低字节;
return Temperature;//返回读取值;
}
void TemperatureConver(void)
{
#if FLOAT_MODE
unsigned char TempH,TempL;
unsigned int Temp;
Temp = ReadTemperature(); //读取当前温度;
if(Temp & 0x80000) //最高位为1时表示温度为负数;
{
Temperature[0] = '-'; //负号标志,表示温度为负数;
Temp = ~Temp; //取反
Temp += 1; //加1;
//当读出数为负的时,必须做取反加1操作;
}//if
else { Temperature[0] = ' '; } //温度为正时,第一位置空;
//整数部分;
TempH = Temp >> 4; //将温度整数部分存放在TempH中,整数部分包括高字节的低4位//和低字节的高4位;
//小数部分;
TempL = (unsigned char)(Temp & 0x000f); //将温度小数部分存放在TempL中,小数部分由// 低字节的低4位决定;
//小数近似处理,处理原理见下表:
//------------------------------------------------------------------------------//
/*
二进制:1 1 1 1
十进制: 8 4 2 1
小数: 0.5 0.25 0.125 0.0625
存在一个整数6,使得十进制数与小数点后的值的转换关系近似相等:
8*6 = 48 偏差 2
4*6 = 24 1
2*60 = 120 忽略
1*600 = 600
于是,若我们只需要小数点后两位,则只需要 *6 即可,需要后一位的话 *6/10;
若还想提高精度,可加一个修正值,该值建议为:1或者2;
*/
//--------------------------------------------------------------------------------//
TempL = TempL * 6; //近似处理转换,两位小数;
TempL += 1; //修正值;
//百位温度值;
if(TempH/100 == 0) { Temperature[1] = ' '; }
else { Temperature[1] = TempH/100+'0'; }
//十位温度值;
if((TempH/100 == 0)&&((TempH%100)/10==0))
{ Temperature[2] = ' '; }
else { Temperature[2] = (TempH%100)/10+'0'; }
//个位温度;
Temperature[3] = (TempH%100)%10+'0';
//小数点;
Temperature[4] = '.';
//小数部分;
Temperature[5] = TempL/10 + '0';
Temperature[6] = TempL%10 + '0';
//字符串结束符;
Temperature[7] = '\0';
//_1ms(); //稍作延时;
ds18b20_delay_us(5);
#else
unsigned int Temp;
Temp = ReadTemperature(); //读取当前温度;
if(Temp & 0x80000) //最高位为1时表示温度为负数;
{
Temperature[0] = '-'; //负号标志,表示温度为负数;
Temp = ~Temp; //取反
Temp += 1; //加1;
//当读出数为负的时,必须做取反加1操作;
}//if
else { Temperature[0] = ' '; } //温度为正时,第一位置空;
//整数部分;
Temp >>= 4; //将低4位移除,因为这4位为小数部分;
//百位温度值;
if(Temp/100 == 0) { Temperature[1] = ' '; }
else { Temperature[1] = Temp/100+'0'; }
//十位温度值;
if((Temp/100 == 0)&&((Temp%100)/10==0))
{ Temperature[2] = ' '; }
else { Temperature[2] = (Temp%100)/10+'0'; }
//个位温度;
Temperature[3] = (Temp%100)%10+'0';
//字符串结束符;
Temperature[4] = '\0';
//_1ms(); //稍作延时;
ds18b20_delay_us(5);
#endif
}
/*
主函数所在文件,用做测试;
*/
/*
USART0发送温度程序测试。
*/
#include <IOcc2530.h>
#include <string.h>
#include "ds18b20.h"
/* 使用ds18b20需引用的一段代码 */
// #define FLOAT_MODE 1
#if FLOAT_MODE
unsigned char Temperature[8]; //小数模式需要8个字节;
#define Temp_Len_ 7 //温度值字符串有效长度;
#else
unsigned char Temperature[5]; //整数模式需要5个字节;
#define Temp_Len_ 4 //温度值字符串有效长度;
#endif
void delay(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<1000;j++);
}
}
void CLOCK_Init()
{
CLKCONCMD &= ~0x40;
while(CLKCONSTA & 0x40);
CLKCONCMD &= ~0x47;
}
void UART0_Init()
{
PERCFG = 0x00;
P0SEL = 0x0c;
P2DIR &= ~0xc0;
U0CSR |= 0x80;
U0GCR |= 11;
U0BAUD |= 216;
U0CSR |= 0x40;
UTX0IF = 0;
}
void SendString(char *String,unsigned char Len)
{
unsigned char i;
for(i=0;i<Len;i++)
{
U0DBUF = *String ++;
while(UTX0IF == 0);
UTX0IF = 0;
}
}
void main()
{
P0SEL &= 0x7f;
CLOCK_Init();
UART0_Init();
while(1)
{
TemperatureConver();
delay(5);
SendString(Temperature,Temp_Len_);
delay(1000);
}
}
展开阅读全文