基于STC89C52RC单片机和DS18B20完成简易现场测温系统制作

2024-12-03 06:07:41
推荐回答(1个)
回答1:

#include
#include
#define uint unsigned int
#define uchar unsigned char
#define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
/********************** DS18B20 指令*********************/
#define ds18B20_READ_ROM 0x33 // 读 ROM 指令
#define ds18B20_MATCH_ROM 0x55 // 匹配 ROM 指令
#define ds18B20_SKIP_ROM 0xCC // 跳过 ROM 指令
#define ds18B20_SEARCH_ROM 0xF0 // 搜索 ROM 指令
#define ds18B20_ALARM_SEARCH 0xEC // 报警搜索指令
#define ds18B20_WRITE_SCRATCHPAD 0x4E // 写暂存寄存器指令
#define ds18B20_READ_SCRATCHPAD 0xBE // 读暂存寄存器指令
#define ds18B20_COPY_SCRATCHPAD 0x48 // 复制暂存寄存器指令
#define ds18B20_CONVERT_T 0x44 // 启动温度转换指令
#define ds18B20_RECALL_E2 0xB8 // 重新调出 E2PROM 的数据
#define ds18B20_READ_POWER_SUPPLY 0xB4 // 读电源
#define LCD_Data P1 //定义数据指令端口
sbit ds18B20_data = P3^3; //温度探头(DQ)数据端口对应的单片机引脚
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;

uchar Minus_Flag=0;
uchar code Temp_Disp_Title[]={"Current Temp : "};
uchar Current_Temp_Display_Buffer[]={"TEMP: "};
uchar Temp_Value[]={0x00,0x00};
uchar Display_Digit[]={0,0,0};

void Delay(uint x)
{
while(--x);
}
/****************************延时10us*************************/
//先执行一个LCALL指令(2 μs),然后执行6个_NOP_( )语句(6 μs),最后执行了一个RET指令(2 μs)
void Delay_10us(void)
{ _nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/***************************延时 time*15us******************** */
void delay_15us(uint time)
{
uint i;
for (i=0;i}
void DelayXus(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<200;i++);
}
}

bit LCD_Busy_Check()
{
bit result;
LCD_RS = 0; //zhi ling
LCD_RW = 1; //du zhuang tai
LCD_EN = 1;
delayNOP();
result = (bit)(LCD_Data&0x80);
LCD_EN=0;
return result;
}

void Write_LCD_Command(uchar cmd)
{
while(LCD_Busy_Check()); //bu mang lu
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
LCD_Data = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}

void Write_LCD_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCD_Data = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}

void LCD_Initialise()
{
Write_LCD_Command(0x01); //清屏
DelayXus(5);
Write_LCD_Command(0x38); //设置16*2显示,5*7点阵,8位数据接口
DelayXus(5);
Write_LCD_Command(0x0c); //画面开,禁止光标显示闪烁
DelayXus(5);
Write_LCD_Command(0x06);

//当读写一个字节后,光标自动加1
DelayXus(5);
}

void Set_LCD_POS(uchar pos)
{
Write_LCD_Command(pos|0x80);
}

/************************温度探头程序************************/
bit Rstds18B20(void); // DS18B20 复位程序, 返回 0-有设备连接,1-无设
void Writeds18B20(uchar ); // 写一个字节 ds18B20 数据、命令子程序
uchar Readds18B20(void); // 读一个字节ds18B20 数据子程序
uint GetTempValue(void); // 启动 ds18B20 温度转换程序
/***********************ds18B20 复位程序**********************/
bit Rstds18B20(void) // 返回,0-有设备连接;1-无设备连接
{
uchar i;
bit RstFlag;
RstFlag = 1;
ds18B20_data = 1;
_nop_();
ds18B20_data=0; // 发送复位脉冲,时间>480us
delay_15us(40); // 延时 480--960us
ds18B20_data = 1; // 拉高总线,延时 15us-60us 后等待ds18B20 响应
delay_15us(2); // 15us-60us
for (i=0;i<6;i++) // 60us-240us
{
delay_15us(1);
if (ds18B20_data==0)
RstFlag=0; // 接收 ds18B20 的存在信号
}
delay_15us(20); // 240us
return RstFlag;
}

/***************写一个字节 ds18B20 数据、命令子程序******************
功能:向 ds18B20 写入数据或命令
入口:待写入 ds18B20 的数据或命令
出口:无
******************************************************************/
void Writeds18B20(uchar ch)
{
uchar i;
ds18B20_data = 1; // 拉高总线,延时 1us,准备启动
_nop_();
for (i=0;i<8;i++)
{
ds18B20_data = 0; // 拉低总线
Delay_10us(); // 延时10us
ds18B20_data = ch&0x1; // 发送待写入的数据, “1”或“0”
delay_15us(2); // 保持写入数据时间 45us
ds18B20_data = 1; // 拉高总线,延时 1us 后准备下一位传输
ch = ch>>1; //先写低位,后写高位
_nop_();
}
}

/******************读一个字节 ds18B20 数据子程序********************
功能:从 ds18B20 读出数据
入口:无
出口:读出的 ds18B20 的数据
******************************************************************/
uchar Readds18B20(void)
{
uchar i,ch;
ch = 0;
ds18B20_data = 1; // 拉高总线,延时 1us,准备启动
_nop_();
for (i=0;i<8;i++)
{
ds18B20_data = 0; // 拉低总线
Delay_10us(); // 延时10us
ds18B20_data = 1; // 拉高总线,准备接收数据
_nop_();
ch = ch>>1;
if (ds18B20_data == 1) // 接收 ds18B20 的数据
ch = ch+0x80;
delay_15us(2); // 延时 45us,保证整个读命令有 60us
}
return ch;
}
/*******************启动

ds18B20 温度转换程序*******************
功能:读取 18B20 的温度值
入口:无
出口:0xffff-18B20 不正常
0x8000-温度低于零度
0~1250-摄氏温度(0~125)
**************************************************************/

uint GetTempValue(void)
{
uchar temp1=0,temp2=0;
uint T=0;
float TC; //TC(浮点数)实际温度
if(!Rstds18B20()) //如果探头连接正常
{
Rstds18B20(); // 复位 ds18B20
Writeds18B20(ds18B20_SKIP_ROM); // 跳过 ROM 操作
Writeds18B20(ds18B20_CONVERT_T); // 启动 ds18B20 温度转换
if(!Rstds18B20()) // 如果探头连接正常
{
Rstds18B20(); // 复位 ds18B20
Writeds18B20(ds18B20_SKIP_ROM); // 跳过 ROM 操作
Writeds18B20(ds18B20_READ_SCRATCHPAD); /* 发读 ds18B20 数据, 前两位是温度值 */
temp1 = Readds18B20(); // 温度值的低位数据
temp2 = Readds18B20(); // 温度值的高位数据
// temp1=0x56;
// temp2=0x05;
T = temp1+(temp2<<8);
if((temp2&0xfc)==0xfc)
{
Minus_Flag=1;
TC=~T+1;
}
else
{
Minus_Flag=0;
TC=T;
}
// TC=T*0.0625; //将测量的数据转换成实际温度
// TC=0x0556;
return (TC*0.625); //返回 TC
}
else
{
return 0xffff;
}
}
else
{
return 0xffff;
}
}

void Display_Temperature(uint num)
{
uchar m,n,q,i;
m=num/100; //得到十位
n=num%100/10; //得到个位
q=num%10; //对上述整数求余得到小数点后第一位
Display_Digit[2] = m;
Display_Digit[1] = n;
Display_Digit[0] = q;
if(Minus_Flag)
{
Current_Temp_Display_Buffer[7] = '-';
}
else Current_Temp_Display_Buffer[7] = ' ';
Current_Temp_Display_Buffer[11] = Display_Digit[0] + '0';
Current_Temp_Display_Buffer[10] = '.';
Current_Temp_Display_Buffer[9] = Display_Digit[1] + '0';
Current_Temp_Display_Buffer[8] = Display_Digit[2] + '0';
if(Display_Digit[2] == 0)
Current_Temp_Display_Buffer[8] = ' ';
Set_LCD_POS(0x00);
for(i=0;i<16;i++)
{
Write_LCD_Data(Temp_Disp_Title[i]);
}
Set_LCD_POS(0x40);
for(i=0;i<16;i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer[i]);
}
// Set_LCD_POS(0x4d);
// Write_LCD_Data(0x00);
Set_LCD_POS(0x4d);
Write_LCD_Data('C');
}

void main()
{
uint Temperature;
LCD_Initialise();
Delay(50000);
while(1)
{
Temperature=GetTempValue();
Display_Temperature(Temperature);
// Display_Temperature(865);
DelayXus(100);
}

}