📄 multi-points.c
字号:
/**************************************************************************************/
/*单片机采用STC89C52,晶振为12MHz。P1.0与DS18B20的数据端相连*/
/*P0为数码管的字段码口,P2口为位选码口*/
/*P3.2与按键0相连,P3.3与按键1相连*/
/*MAXNUM是单总线上最大可扫描DS18B20个数*/
/*flag为温度的正负号标志单元,flag为"1"时表示温度值为负值,为"0"时表示温度值为正值*/
/*温度测量范围为(-55.0~99.9摄氏度)。*/
/*变量cc中保存计算出的温度值的整数部分,xs保存计算出的温度值的小数部分的第一位*/
/*num记录当前单总线上DS18B20的个数*/
/*z是按键标志位,z为1时表明有按键按下*/
/*a,b分别是按键0和按键1的记录变量*/
/*m是轮换显示各DS18B20温度值和序列号的全局标志变量*/
/*二维数组ID用于记录各DS18B20的ROM序列号*/
/*数组disbuffer是LCD显示缓存数组*/
/*数组RomID_temp用于匹配DS18B20时临时记录要匹配DS18B20的序列号*/
/*共用体temp用于存放从DS18B20读入的数据*/
/**************************************************************************************/
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define MAXNUM 4 //宏定义单总线上最大可扫描DS18B20个数
sbit DS=P1^0; //用P1.0口作为各DS18B20与单片机的I/O口
sbit Key0=P3^2; //P3.2用作按键0的输入,采用外部中断方式获取按键信号
sbit Key1=P3^3; //P3.3用作按键1的输入,采用外部中断方式获取按键信号
union{ //定义共用体temp用于存放从DS18B20读入的数据,Keil C51采用大端格式,c[1]是高地址.
uchar c[2]; //其中存放读取温度数值的低字节;c[0]是低地址,其中存放读取温度数值的高字节.
uint x; //这样根据大端格式的要求,即数据的高字节存储在低地址中,数据的低字节存放在高地址中,
}temp; //x便刚好是读出的温度数值.
uchar idata flag; //温度的正负号标志,flag为"1"时表示温度值为负值,为"0"时表示温度值为正值
uint cc,xs; //变量cc中保存计算出的温度值的整数部分,xs保存计算出的温度值的小数部分的第一位
uchar idata disbuffer[6]; //LCD显示缓存数组
uchar idata ID[4][8]={0}; //用于记录各DS18B20的ROM序列号
uchar idata RomID_temp[8]; //匹配DS18B20时临时记录要匹配DS18B20的序列号
uchar m=0; //m是轮换显示各DS18B20温度值和序列号的全局标志变量
uchar num=0; //num记录当前单总线上DS18B20的个数
uchar z=0; //z是按键标志位,z为1时表明有按键按下
uchar a=0; //a是按键0的记录变量
uchar b=0; //b是按键1的记录变量
void delay(uint i) //延时i*9.62us
{
uint j;
for(j=i;j>0;j--);
}
void delay_ms(uchar i) //延时(j*2+1+2)*i+5 个机器周期
{ uchar j; //12MHz时,延时 0.5*i ms
do{j=248;
do{j--;}while(j);
i--;
}while(i);
}
void delay_2us(uchar i) //延时 2*i+5 us
{
while(--i);
}
uchar DS_init(void) //18B20复位,初始化函数
{
uchar presence;
DS=0; delay_2us(250); //根据DS18B20的复位时序.先把总线拉低555us
DS=1; delay_2us(30); //再释放总线,65us后读取DS18B20发出的信号
presence=DS; delay_2us(250); //如果复位成功,则presence的值为0;否则为1
return (presence); //返回0则初始化成功,否则失败
}
uchar read_byte(void) //读1字节
{
uchar i,j,dat=0;
for(i=1;i<=8;i++) //作8个循环,读出的8位组成一个字节
{DS=0; _nop_(); //先将总线拉低1us,
DS=1; delay_2us(2); //再释放总线,产生读起始信号,延迟9us后读取总线上的DS18B20发出的值
j=DS; delay_2us(30); //一位读完后,延迟65us后读下一位
dat=(j<<7)|(dat>>1); //读出的数据最低位在一个字节的最低位,这样刚好一个字节在DAT里
}
return(dat);
}
uchar read_2bit(void) //读2位
{
uchar i=0,j=0;
DS=0; _nop_(); //先将总线拉低1us,
DS=1; delay_2us(2); //再释放总线,产生读起始信号,延迟9us后读取总线上的DS18B20发出的值
j=DS; delay_2us(30); //一位读完后,延迟65us后读下一位
DS=0; _nop_();
DS=1; delay_2us(2);
i=DS; delay_2us(30);
i=j*2+i; //将读出的两位放到变量i中,其中第一个读出的位处于i的第1位;而第二个读出的位处于i的第0位
return(i);
}
void write_byte(uchar dat) //写1字节
{
uchar i;
for(i=0;i<8;i++) //作8个循环,写入的8位组成一个字节
{DS=0; //先将总线拉低
DS = dat&0x01; //向总线上放入要写的值
delay_2us(50); //延迟105us,以使DS18B20能采样到要写入的值
DS = 1; //释放总线,准备写入下一位
dat>>=1; //将要写的下一位移到dat的最低位
}
}
void write_bit(bit dat) //写1位
{
DS=0; //先将总线拉低
DS=dat; //向总线上放入要写的值
delay_2us(50); //延迟105us,以使DS18B20能采样到要写入的值
DS = 1; //释放总线
}
void display_ROMID(void) //定义显示序列号的函数
{
uchar i,p,t,k;
uint q;
uchar disbuffer_rom[8];
uchar codevalue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xbf};
//共阳极的字段码
uchar chocode[]={0xf7,0xfb,0xfd,0xfe,0x7f,0xbf,0xdf,0xef};
//位选码表
z=0; //z归零,表明没有按键按下
for(q=0;q<500;q++) //显示各DS18B20的序号
{ if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
break;
t=chocode[7]; //取当前的位选码
P2=t; //送出位选码
t=codevalue[m+10]; //查得显示字符的字段码
P0=t; //送出字段码
delay(100);
}
P2=0xFF; //关断LCD一段时间,产生闪屏效果
for(q=0;q<500;q++)
{ if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个循环中跳出
break;
delay(100);
}
for(k=0;k<8;k=k+4) //依次显示序列号的低32位或高32位
{ if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个循环中跳出
break;
//接下来将序列号的低32位或高32位值取出放入disbuffer_rom存储
disbuffer_rom[0]=(ID[m][k]&0x0F);
disbuffer_rom[1]=((ID[m][k]&0xF0)>>4);
disbuffer_rom[2]=(ID[m][k+1]&0x0F);
disbuffer_rom[3]=((ID[m][k+1]&0xF0)>>4);
disbuffer_rom[4]=(ID[m][k+2]&0x0F);
disbuffer_rom[5]=((ID[m][k+2]&0xF0)>>4);
disbuffer_rom[6]=(ID[m][k+3]&0x0F);
disbuffer_rom[7]=((ID[m][k+3]&0xF0)>>4);
for(q=0;q<250;q++) //显示序列号的低32位或高32位
{ if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
break;
for (i=0;i<8;i++)
{ if(z==1)
break;
t=chocode[i]; //取当前的位选码
P2=t; //送出位选码
p=disbuffer_rom[i]; //取当前显示的字符
t=codevalue[p]; //查得显示字符的字段码
P0=t; //送出字段码
delay(40);
}
}
P2=0xFF; //显示完一轮,灯灭
for(q=0;q<500;q++)
{
if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
break;
delay(100);
}
}
}
void display_error(void) //定义显示总线上没有DS18B20时的函数
{
uchar i,p,t;
uint q;
uchar disbuffer_temp[8]={0,2,8,1,16,0x0f,0x0f,0}; //显示内容为"OFF 1820"
uchar codevalue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xbf};
//共阳极的字段码
uchar chocode[]={0xf7,0xfb,0xfd,0xfe,0x7f,0xbf,0xdf,0xef};
//位选码表
for(q=0;q<250;q++)
{
for (i=0;i<8;i++)
{
t=chocode[i]; //取当前的位选码
P2=t; //送出位选码
p=disbuffer_temp[i]; //取当前显示的字符
t=codevalue[p]; //查得显示字符的字段码
P0=t; //送出字段码
delay(40);
}
}
}
uchar search_rom(void) //遍历搜索单线上所连的所有18b20的序列号
{
uchar k,l=0,chongtuwei,m,n,a;
uchar _00web[MAXNUM]={0};
do
{
DS_init(); //复位单总线上的所有DS18B20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -