📄 8-2.c
字号:
#include<at89x51.h>
#include<intrins.h>
unsigned char code displaybit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位扫描译码表
unsigned char code displaycode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, //共阴数码管段码译码表高位有效
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40}; //第1个元素灭数码管,第17个元素点亮G段
unsigned char code dotcode[32]={0,3,6,9,12,16,19,22,25,28,31,34,38,41,44,48,50,
53,56,59,63,66,69,72,75,78,81,84,88,91,94,97}; //小数部分32个值对应的十进制数表
unsigned char displaycount;
unsigned char displaybuf[8]={16,16,16,16,16,16,16,16}; //显示缓冲区
unsigned char timecount;
unsigned char readdata[8];
sbit DQ=P3^7; //DS18B20的数据输入引脚
bit sflag;
void delay(unsigned int i)
{while(i--);}
resetpulse(void) //复位DS18B20的函数
{
unsigned char x=0;
DQ=1; //使总线为高电平
delay(8);
DQ=0; //使总线为低电平
delay(80); //延迟一段时间,最少480us
DQ=1; //使总线为高电平
delay(14); //延迟一段时间,等待DS18B20回应低电平
x=DQ; //将DS18B20的回应读到变量x,用于判断复位是否成功,x=0表复位成功
delay(20);
}
void writecommandtods18b20(unsigned char command) //写字节到DS18B20的函数
{
unsigned char i=0;
for(i=8;i>0;i--)
{DQ=0; //使总线为低电平
DQ=command&0x01; //将发送字节的最低位送到总线
delay(5); //延迟一段时间(30us),等待DS18B20取走总线数据
DQ=1; //将总线拉高
command>>=1; //将待发送的字节右移,继续发送
}}
unsigned char readdatafromds18b20(void) //从DS18B20读取一个字节
{
unsigned char i=0;
unsigned char temp=0;
for(i=8;i>0;i--)
{DQ=0;
temp>>=1;
DQ=1; //使总线为高电平
if(DQ) //如果DS18B20输出为高电平(总线电平为1)
temp|=0x80; //将暂存变量的最高位置1
delay(4);
}
return(temp);
}
void main(void)
{
TMOD=0x01;
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
ET0=1;
EA=1;
resetpulse();
writecommandtods18b20(0xcc); //发送跳过ROM搜索命令
writecommandtods18b20(0x44); //启动一次转换,表第一次读DS18B20能得准确数,若多次读不设也可
TR0=1;
while(1);
}
void t0(void)interrupt 1 using 0
{unsigned char x;
unsigned int result;
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
if(displaycount==2)
P0=displaycode[displaybuf[displaycount]]|0x80; //显示缓冲区的次高位数码管显示的段码,同时显示小数点
else
P0=displaycode[displaybuf[displaycount]]; //显示缓冲区的其它位置的段码
P2=displaybit[displaycount]; //位扫描信号
displaycount++;
if(displaycount==8) //如果8位扫描完毕,返回到1继续显示
displaycount=0;
timecount++;
if(timecount==150)
{timecount=0;
resetpulse();
writecommandtods18b20(0xcc); //发送跳过ROM搜索命令
writecommandtods18b20(0xbe); //发送读命令
readdata[0]=readdatafromds18b20(); //读温度值低8位,高4位为整数部分,低4位为小数
readdata[1]=readdatafromds18b20(); //读温度值高8位,高5位为符号位,0表正数,1表负数,低3位为温度值
for(x=0;x<8;x++)
displaybuf[x]=16; //将显示数据缓冲区的内容置为16,则8个数码管各段都灭
sflag=0;
if((readdata[1]&0xf8)!=0x00)
{sflag=1;
readdata[1]=~readdata[1]; //求反码
readdata[0]=~readdata[0];
result=readdata[0]+1; //低8位加1,形成补码送变量result
readdata[0]=result; //送回原变量
if(result>255) //若低8位大于255
readdata[1]++; //向高3位进位
}
readdata[1]=readdata[1]<<4; //将温度值高8位左移4位 0xxx
readdata[1]=readdata[1]&0x70; //将温度值高8位与01110000相与,只保留有效温度值
x=readdata[0]; //将温度值低8位赋予x
x=x>>4; //将温度值低8位中的整数部分右移到低4位
x=x&0x0f; //将低8位温度值中的高4位清0
readdata[1]=readdata[1]|x; //将温度值高8位中的3位有效温度值与温度值低8位中的4位有效温度,连结成一个温度整数字节
x=2; //如下语句处理显示缓冲器的第2位置中保存内容
result=readdata[1]; //将温度的整数部分赋予变量result
while(result/10) //如果整数部分超过10
{
displaybuf[x]=result%10;
result=result/10;
x++;
}
displaybuf[x]=result;
if(sflag==1)
displaybuf[x+1]=17; //在显示缓冲器的第x+1位值显示符号(数码管只有G段亮)
x=readdata[0]&0x0f; //将温度值的小数部分取出
x=x<<1; //左移一位相当于乘以2,则得32个数
displaybuf[0]=(dotcode[x])%10;
displaybuf[1]=(dotcode[x])/10;
resetpulse();
writecommandtods18b20(0xcc);
writecommandtods18b20(0x44);
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -