📄 ds1820.txt
字号:
#define uchar unsigned char
#define ulong unsigned long int
#define DS18b20io P2_0 //DS18B20数据线
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
uchar DS18b20_temp[2]; //读出的18b20温度值存放地
uchar display_date[4]; //要显示的四位数据的存放地
uchar dispaly_dot; //LED显示小数点位置
uchar *display_point; //LED显示数据存放地指针
void delay_5us(uchar y) //(2.17*y+5)us延时,11.0592M晶振
{
while(--y);
}
void delay(uint v) //1ms单位延时(实际是0.998ms)。50是49ms;500是490ms,还算准. 晶振11.0592M
{
uchar i;
while(v--)
{
for(i=0;i<111;i++);
}
}
void display(uchar *z,uchar spot) //数码管显示子程序。入口是要显示的4位数字(0、1、2、3。。。)及小数点位置,0/1/2/3四个位置,其他数字表示无小数点。BCD码转换等应由前期解决。
{ //为避免闪烁,应在主程序里不停调用这个子程序.它大约耗时4ms.因此凡是需要4ms以上延时的地方,最好都用它来延时.
uchar i;
for(i=0;i<4;i++)
{
P2|=0xf0; //关所有4个数码管
switch(*(z+i))
{
case 0:P0=0xc0;break; //共阳的段码表。若LED共阴,则码表取反。
case 1:P0=0xf9;break;
case 2:P0=0xa4;break;
case 3:P0=0xb0;break;
case 4:P0=0x99;break;
case 5:P0=0x92;break;
case 6:P0=0x82;break;
case 7:P0=0xf8;break;
case 8:P0=0x80;break;
case 9:P0=0x90;break;
case 12:P0=0xbf;break; //“-”,表示零下温度
case 13:P0=0xa7;break; //“c”,表示温度
case 15:P0=0xff;break; //不亮
default:P0=0xff; //不亮
}
if(spot==i)
P0&=0x7f;
P2&=~(0x80>>i);
delay(1); //亮1mS
}
P2|=0xf0; //关所有4个数码管,否则最后一位就会格外亮.
}
void DS18b20_w_byte(uchar x) //向18b20写一个字节.x是要写的内容
{
uchar i;
for(i=0;i<8;i++)
{
DS18b20io=0;
_nop_(); //要求>1us,但又不能超过15us
_nop_();
if(0x01&x)
DS18b20io=1;
delay_5us(30); //要求总时间在60-120us
DS18b20io=1; //释放总线
_nop_(); //要求>1us
x=x>>1;
}
}
uchar DS18b20_r_byte(void) //从18b20读一个字节.返回读到的内容
{
uchar i,j;
j=0;
for(i=0;i<8;i++)
{
j=j>>1;
DS18b20io=0;
_nop_(); //要求>1us,但又不能超过15us
_nop_();
DS18b20io=1; //释放总线
_nop_();
_nop_();
if(DS18b20io)
j|=0x80;
delay_5us(30); //要求总时间在60-120us
DS18b20io=1; //释放总线
_nop_(); //要求>1us
}
return j;
}
void DS18b20_int(void) //每次上电都给18b20初始化,设置18b20的参数.
{
DS18b20io=0;
delay_5us(255); //要求480-960us
DS18b20io=1; //释放总线
delay_5us(30); //要求60-120us
if(DS18b20io==0)
{
delay_5us(200); //要求释放总线后480us内结束复位
DS18b20io=1; //释放总线
DS18b20_w_byte(0xcc); //发送Skip ROM命令
DS18b20_w_byte(0x4e); //发送"写"暂存RAM命令
DS18b20_w_byte(0x00); //温度报警上限设为0
DS18b20_w_byte(0x00); //温度报警下限设为0
DS18b20_w_byte(0x3f); //将18b20设为10位,精度就是0.25度
DS18b20io=0;
delay_5us(255); //要求480-960us
DS18b20io=1; //释放总线
delay_5us(240); //要求释放总线后480us内结束复位
DS18b20io=1; //释放总线
}
}
void DS18b20_readTemp(void) //读18b20温度值
{
uchar i;
DS18b20io=0;
delay_5us(255); //要求480-960us
DS18b20io=1; //释放总线
delay_5us(30); //要求60-120us
if(DS18b20io==0)
{
delay_5us(200); //要求释放总线后480us内结束复位
DS18b20io=1; //释放总线
DS18b20_w_byte(0xcc); //发送Skip ROM命令
DS18b20_w_byte(0x44); //发送温度转换命令
DS18b20io=1; //释放总线
for(i=0;i<50;i++) //10位方式需要180ms.这里用显示子程序代替延时,可以避免LED闪烁,一举两得
display(display_point,dispaly_dot);
DS18b20io=0;
delay_5us(255); //要求480-960us
DS18b20io=1; //释放总线
delay_5us(30); //要求60-120us
if(DS18b20io==0)
{
delay_5us(200); //要求释放总线后480us内结束复位
DS18b20io=1; //释放总线
DS18b20_w_byte(0xcc); //发送Skip ROM命令
DS18b20_w_byte(0xbe); //发送"读"暂存RAM命令
DS18b20_temp[0]=DS18b20_r_byte(); //读温度低字节
DS18b20_temp[1]=DS18b20_r_byte(); //读温度高字节
DS18b20io=0;
delay_5us(255); //要求480-960us
DS18b20io=1; //释放总线
delay_5us(240); //要求释放总线后480us内结束复位
DS18b20io=1; //释放总线
}
}
}
void main(void)
{
uchar zz;
uint DS18b20_tempdate; //为整理读到的温度值而设的中间结果存放地
display_point=&display_date[0];
EA=0;
DS18b20_int();
EA=1;
while(1)
{
EA=0;
DS18b20_readTemp();
EA=1;
if(DS18b20_temp[1]&0xf8) //显示零下温度,小数不显示,有负标志
{
DS18b20_tempdate=DS18b20_temp[1]<<8;
DS18b20_tempdate+=DS18b20_temp[0];
DS18b20_tempdate&=0x03ff;
DS18b20_tempdate=DS18b20_tempdate>>2;
DS18b20_tempdate-=1;
DS18b20_tempdate=~DS18b20_tempdate; //以上是将18b20里的负温度补码转换为原码
DS18b20_tempdate=DS18b20_tempdate/4;
zz=(uchar)(DS18b20_tempdate&0x00ff); //这是整数位,小数位忽略不显示
display_date[0]=12; //负温度标志“-”
display_date[1]=zz/10; //温度十位数
display_date[2]=zz%10; //温度个位数
dispaly_dot=9;
}
else
{
DS18b20_tempdate=(((DS18b20_temp[1]&0x07)<<8)+DS18b20_temp[0])>>2;
DS18b20_temp[1]=DS18b20_tempdate>>2; //这是整数位
DS18b20_temp[0]=DS18b20_tempdate&0x03; //这是小数位
if(DS18b20_temp[1]>=100) //如果超过100度,就不显示小数位
{ //显示100度以上温度,无小数位
display_date[0]=DS18b20_temp[1]/100; //温度百位数
display_date[1]=(DS18b20_temp[1]-100)/10; //温度十位数
display_date[2]=(DS18b20_temp[1]-100)%10; //温度个位数
dispaly_dot=9;
}
else //0-100度,显示一位小数
{
display_date[0]=DS18b20_temp[1]/10; //温度十位数
display_date[1]=DS18b20_temp[1]%10; //温度个位数
switch(DS18b20_temp[0])
{
case 0:display_date[2]=0;break;
case 1:display_date[2]=2;break;
case 2:display_date[2]=5;break;
case 3:display_date[2]=8;break;
default:display_date[2]=0;
}
dispaly_dot=1;
}
}
display_date[3]=13; //显示温度符号“c”
display(display_point,dispaly_dot); //实际显示温度
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -