📄 multi-points.c
字号:
write_byte(0xf0); //单片机发布搜索命令
for(m=0;m<8;m++)
{
uchar s=0; //s用来记录本次循环得到的1个字节(8位)序列号
for(n=0;n<8;n++)
{
k=read_2bit(); //读第m*8+n位的原码和反码,保存在k中
k=k&0x03; //屏蔽掉k中其它位的干扰,为下一步判断作准备
s>>=1; //s右移一位,即把上一次循环得到的位值右移一位,
//这样执行完一次n为变量的循环,便可得到一个字节的ROM号
if(k==0x01) //k为01,表明读到的数据为0,即所有器件在这一位都为0,所以向总线上写0
//同时对s的值不进行操作,即这位的序列号记为0
{
write_bit (0);
}
else if(k==0x02)//k为02,表明读到的数据为1,即所有器件在这一位都为1,所以向总线上写1
{
s=s|0x80; //记录下此位的值,即s的最高位置1
write_bit (1);
}
else if(k==0x00)
{
chongtuwei=m*8+n+1; //记录下这个冲突位发生的位置;之所以加1是为了让_00web数组中的第一位保持0不变,
//便于判断搜索循环是否结束;
if(chongtuwei>_00web[l])//如果冲突位比标志00位的位高,即发现了新的冲突位,那么这位写0
{
write_bit (0);
_00web[++l]=chongtuwei; //依次记录位比冲突标志位高的冲突位在_00web数组中
}
else if(chongtuwei<_00web[l]) //如果冲突位比标志00位的位低,那么把ID中这位所在的字节右移n位,
{ //从而得到这位先前已经写过的值,如果为0,说明这位先前写的是0,那么继续写0,
// 如果这位先前写的是1,那么继续写1
a=(ID[num-1][m]>>n)&0x01;
s=s|(a<<7); //记录下此位的值
write_bit(a);
}
else if(chongtuwei==_00web[l])//如果冲突位就是标志00位,那么s的最高位置1,即这位记为1,同时向总线上写1;
//之所以不写0,是因为前面已经写过0,再写0,就得不到遍历的效果.
{
s=s|0x80;
write_bit (1);
l=l-1; //改变标志00位的位置,即向前推一个00位,并且是往低位方向推
}
}
else if(k==0x03) //k为03,表明总线上没有DS18B20,函数结束,同时返回零值
{return(0);}
}
ID[num][m]=s;
}
num++; //DS18B20的个数加1
}while((_00web[l]!=0)&&(num<MAXNUM));//如果冲突位记录数组已经前推到0值或是DS18B20的数目已经超过最大允许数目,
//就退出循环
return(1); //搜索完毕,返回1值
}
void Read_Temperature_rom(void) //读取温度函数
{ uchar i;
DS_init();
write_byte(0x55); //匹配ROM
for(i=0;i<8;i++) //发出64位ROM编码
write_byte(RomID_temp[i]);
write_byte(0x44); //开始转换
DS_init();
write_byte(0x55); //匹配ROM
for(i=0;i<8;i++) //发出64位ROM编码
write_byte(RomID_temp[i]);
write_byte(0xBE); //发读温度命令
temp.c[1]=read_byte(); //读低字节,之所以c[1]中放低字节,是因为C51采用的是大端格式,具体详见共用体定义的说明
temp.c[0]=read_byte(); //读高字节,之所以c[0]中放低字节,是因为C51采用的是大端格式,具体详见共用体定义的说明
}
void Temperature_cov(void) //温度转换
{
if (temp.c[0]>0xf8) {flag=1;temp.x=~temp.x+1;}
//如果为负,则符号标志置1,计算温度值,注意c[0]中放的是读取温度值的高字节
//还要注意读出的数值一共是12位
cc=temp.x/16; //计算出温度值的整数部分,这个语句相当于数值乘0.0625再取整数部分
xs=temp.x&0x0f; //取温度值小数部分的第一位
xs=xs*10; //这两条语句相当于乘0.625,得小数位的第一位,注意不是乘0.0625
xs=xs/16;
}
void display(void) //定义温度底层显示函数
{
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};
//位选码表
uchar i=0,p,t;
disbuffer[4]=0x10; //让LCD的第5位全灭,即什么也不显示,注意是16进制表示
disbuffer[5]=0x0a+m; //LCD的第6位显示DS18B20序列号,以字母A,B,C,D,E,F来给示,所以加上0x0a
if (flag==1)disbuffer[3]=0x11;//判断是否显示负号
else disbuffer[3]=0x10;
disbuffer[0]=xs; //放入小数位显示的数值
disbuffer[1]=(cc%10);//放入个数要显示的数值
disbuffer[2]=(cc/10);//放入十位要显示的数值
for (i=0;i<6;i++)
{
t=chocode[i]; //取当前的位选码
P2=t; //送出位选码
p=disbuffer[i]; //取当前显示的字符
t=codevalue[p]; //查得显示字符的字段码
if (i==1) t=t+0x80; //个位比较特殊,因为有小数点,所以要加上0x80
P0=t; //送出字段码
delay(40);
}
}
void diplay_final(void) //定义温度上层显示函数
{ uint q,r;
z=0;
for(q=0;q<8;q++) //将要显示DS18B20的温度值的序列号放入数组RomID_temp中
{
RomID_temp[q]=ID[m][q];
}
P2=0xFF;
if(a==0) //如果按键0的标志变量a=0,即进行闪烁显示
{
for(q=0;q<3;q++) //闪烁空隙仍在读取温度
{
if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个循环中跳出
break;
flag=0;
Read_Temperature_rom(); // 读取双字节温度
Temperature_cov(); //温度转换
for(r=0;r<15;r++)
delay(1000);
}
}
for(q=0;q<5;q++) //读取温度并显示
{ if(z==1) //如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
break;
flag=0;
Read_Temperature_rom(); // 读取双字节温度
Temperature_cov(); //温度转换
for(r=0;r<100;r++)
display(); //显示温度
}
}
void key_0() interrupt 0 //外部中断0的中断处理函数
{
delay(1200); //延时消抖
if(Key0==0)
{
if(a==0) //a只可能取0值或1值
a=1;
else a=0;
b=0; //同时一旦0键按下就将b归零
z=1; //将有按键按下标志位z置位
}
}
void key_1() interrupt 2 //外部中断1的中断处理函数
{
delay(1200); //延时消抖
if(Key1==0)
{ if(a==0) //只有a等于0时才让b的值在0或1之间转变
{
if(b==0)
b=1;
else b=0;
}
z=1; //将有按键按下标志位z置位
if(a==1) //当a=1时进入固定显示一个DS18B20的温度值的状态
{
m++; //按一次1键m值加1,即在不同的DS18B20切换显示
if(m>=num) //当然,m的值不能超过或等于总线上挂接的DS18B20的数目
m=0;
}
}
}
void main() //主函数
{ uchar p,i;
delay(10);
p=search_rom(); //执行搜索DS18B20算法,同时返回搜索情况,p值为0,表明总线上没有DS18B20,p值为1表明搜索到DS18B20;
if(p==0) //如果总线上没有DS18B20,显示"OFF 1820"
while(1)
display_error();
EA=1; //开中断
EX0=1; //允许外部中断0
IT0=1; //外部中断0为边沿触发方式
EX1=1; //允许外部中断1
IT1=1; //外部中断1为边沿触发方式
while(1)
{
if(a==0&&b==0) //按键0和1的状态变量值都为0,此时轮换显示各DS18B20的温度值
{
diplay_final(); //显示DS18B20的温度值
if(m<num-1) //为了实现轮换显示,要改变m的值
m++;
else m=0;
if(z==1) //如果有按键按下,将m清零
{
m=0;
}
}
else if(a==0&&b==1) //按键0和按键1的状态变量值分别为0和1,此时轮换显示各DS18B20的序列号
{
display_ROMID(); //显示DS18B20的序列号
if(m<num-1) //为了实现轮换显示,要改变m的值
m++;
else m=0;
if(z==1) //如果有按键按下,将m清零
{
m=0;
}
}
else //按键0的状态变量值为1,此时固定显示各DS18B20的温度值,按键1用于不同DS18B20间的切换
{
diplay_final(); //显示DS18B20的温度值
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -