永发信息网

单片机测温程序在临界点跳来跳去问题

答案:1  悬赏:0  手机版
解决时间 2021-02-28 02:21
  • 提问者网友:孤凫
  • 2021-02-27 15:32
单片机测温程序在临界点跳来跳去问题
最佳答案
  • 五星知识达人网友:夜余生
  • 2021-02-27 15:53

#include
#include
#define uchar unsigned char
#define uint unsigned int

#define data_port P1    //液晶屏指令、数据通信接口
sbit rs=P2^0; //液晶屏寄存器选择接口(rs=0时选择指令寄存器,rs=1时选择数据寄存器)
sbit rw=P2^1; //液晶屏读写选择接口(rw=0时选择写入,rw=1时选择读出)
sbit en=P2^2; //液晶屏使能接口(en=0时通信接口中断,en=1时通信接口接通)
uchar code line1_str[]={"  Temperature   "};//液晶屏第一行要显示的字符串
uchar code num_tab[]={"0123456789"};

sbit DQ=P3^5; //温度传感器18b20的数据接口

void T1_int();              //定时器T1初始化子函数声明
void in_command(uchar com); //向液晶屏输入命令子函数声明
void in_data(uchar dat); //向液晶屏输入数据子函数声明
void lcd_disp_string(uchar str[]); //液晶屏显示一串字符子函数声明 
void lcd_int(); //液晶屏初始化子函数声明
void disp_temperature(uint temp);//lcd1602显示温度子函数声明
bit ds18b20_ret(); //温度传感器18b20复位子函数声明
void ds18b20_wr_com(uchar com); //向温度传感器18b20写入命令子函数声明
void rd_ram_command(); //发送命令子函数(读取18b20的RAM)
uint ds18b20_rd_data(); //读出温度传感器18b20寄存器的相关数据(主要是温度值)子函数声明
void temperature_convert(); //18b20温度转换子函数声明
void delayms(uint ms); //毫秒延时子函数声明
void delay_n10_us(uchar n); //微秒延时子函数声明

void main()
{
T1_int();                //定时器T1初始化
DQ=1; //释放温度传感器18b20的数据接口
temperature_convert(); //第一次调用18b20温度转换子函数消除85°C问题 
lcd_int(); //液晶屏初始化(放在18b20温度转换子函数后边用来延时,跳过85°C)  
while(1)
{
temperature_convert(); //调用18b20温度转换子函数
rd_ram_command(); //发送命令子函数(读取18b20的RAM)
disp_temperature(ds18b20_rd_data());//调用lcd1602显示温度子函数
}
}

void T1_int()
{
TMOD=0x10; //0001 0000 T1工作在定时方式1
    TH1=0;             //T1设定初值
TL1=0;
TR1=0; //暂时关闭T1

 
void temperature_convert()
{
while(ds18b20_ret()==0);//温度传感器18b20复位
ds18b20_wr_com(0xcc); //向温度传感器18b20写入"跳跃ROM命令"
ds18b20_wr_com(0x44); //向温度传感器18b20写入"温度转换命令"
delay_n10_us(50);   //500us延时,等待转换完成


void rd_ram_command()
{
while(ds18b20_ret()==0);
ds18b20_wr_com(0xcc); //向温度传感器18b20写入"跳跃ROM命令"
ds18b20_wr_com(0xbe); //向温度传感器18b20写入"读RAM命令"
}           

uint ds18b20_rd_data()
{
uchar i;
uint temp_val;
for(i=0;i<16;i++)
{
temp_val>>=1;
DQ=0;
_nop_();
DQ=1;
_nop_();
_nop_();
if(DQ==1)
{
temp_val|=0x8000;
}
delay_n10_us(7); //70us延时,确保读出
}
return(temp_val);
}

void ds18b20_wr_com(uchar com)
{
uchar i;
for(i=0;i<8;i++)
{
if((com&0x01)==0)
{
DQ=0;  
  delay_n10_us(7); //70us延时,确保写入0
DQ=1;
_nop_();
}
else
{
DQ=0;  
_nop_();
DQ=1;
  delay_n10_us(7); //70us延时,确保写入1
}
com>>=1;
}
}
 
bit ds18b20_ret()
{
uint temp;              //暂存脉冲时间
DQ=0;                   //启动复位脉冲
delay_n10_us(50); //500us延时(大于480us)
DQ=1;                   //停止复位脉冲
TR1=1; //启动T1
while(DQ==1 && TH1*256+TL1<=60);//等待18b20回应,等待时间不超过60us
    if(DQ==0) //18b20回应
{
  temp=TH1*256+TL1;
while(TH1*256+TL1-temp<40); //等待60us再次检测回应脉冲是否存在
if(DQ==0) //18b20正常回应
{
while(TH1*256+TL1<=480);//等待正常复位完成
TR1=0; //关闭T1
TH1=0; //计时归零
TL1=0;          
return(1); //18b20有正常回应返回1
}
else
{
TR1=0; //关闭T1
TH1=0; //计时归零
TL1=0;          
return(0); //18b20有正常回应返回0
}
}
else
{
TR1=0; //关闭T1
TH1=0; //计时归零
TL1=0;          
return(0); //18b20没有回应返回0
}
}

void disp_temperature(uint temp)
{
uchar temp_h,temp_l,flag=0; //温度整数部分,小数部分(二进制)和最高位是否为'0'标志
uint temp_decimal=0;        //存储温度值的小数部分(十进制)
in_command(0xc2); //设定第二行字符串起始显示位置
if(temp>=0x8000)
{
in_data('-'); //显示'-'号
temp=~temp;
temp+=1;
}
else
{
in_data(' '); //'+'号不显示
}
temp_h=temp/16;
temp_l=temp%16;
if(temp_h/100!=0)
{
flag=1;
in_data(num_tab[temp_h/100]); //显示温度值的百位
}
else
{
in_data(' ');                //百位为'0'则百位不显示
}
temp_h%=100;
if(temp_h/10!=0 || flag==1)
{
flag=1;
in_data(num_tab[temp_h/10]); //显示温度值的十位
}
else
{
in_data(' ');   //百位,十位都为'0'则十位不显示
}
temp_h%=10;
in_data(num_tab[temp_h]);     //显示温度值的个位
in_data('.');   //显示小数点
if(temp_l/8==1)
{temp_decimal+=5000;}
temp_l=temp_l%8;
if(temp_l/4==1)
{temp_decimal+=2500;}
temp_l=temp_l%4;
if(temp_l/2==1)
{temp_decimal+=1250;}
temp_l=temp_l%2;
if(temp_l==1)
{temp_decimal+=625;}
in_data(num_tab[temp_decimal/1000]);//显示温度值的十分位
    in_data(' '); 
in_data(223);  //显示温度单位标志'摄氏度' 
in_data('C');  
}
 
void lcd_int()
{

delayms(15); //延时15MS,等待LCD初始化
in_command(0x01); //清显示屏
in_command(0x38); //8位通信,2行显示,5*7点阵
in_command(0x0c); //开显示,关光标,关闪烁
in_command(0x06); //字符不动,光标右移动,地址加一

in_command(0x80); //设定第一行字符串起始显示位置
lcd_disp_string(line1_str); //显示数据(字符)
}
 
void lcd_disp_string(uchar str[])
{
uchar i=0;
while(str[i]!='\0')
{
in_data(str[i]); //显示数据(字符)
i++;
delayms(50); //延时
}
}

void in_command(uchar com)
{
delayms(2);
en=0;//关闭通信,为设置参数做准备
rs=0;//选择指令寄存器
rw=0;//写入液晶
_nop_();
data_port=com;
en=1;//开始通信
_nop_();
en=0;//关闭通信,为设置参数做准备
}

void in_data(uchar dat)
{
delayms(2);
en=0;//关闭通信,为设置参数做准备
rs=1;//选择数据寄存器
rw=0;//写入液晶
_nop_();
data_port=dat;
_nop_();
en=1;//开始通信
_nop_();
en=0;//关闭通信,为设置参数做准备
}

void delay_n10_us(uchar n)
{
while(n--)
{
_nop_();
_nop_();
}
}

void delayms(uint ms)       
{
uchar i;
while(ms--)
{
for(i=0;i<124;i++);
}
}
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯