18b20二叉树获取编码只能获取1个器件

华仔lugl 2014-08-22 11:41:32
单一总结上挂接了两个18b20,可能获取到一个元器件的ROM,把程序贴上来,希望大家帮我诊断一下。

#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char //定义无符号单字节
#define uint unsigned int //定义无符号整形
#define MAXNUM 2 //定义最多DS18B20个数 超过的无法显示

typedef bit BOOL; // 用BOOL代替bit
typedef unsigned char BYTE; //用BYTE代替unsigned char
sbit DQ=P3^7;//ds18b20与单片机连接口
sbit LCD_RS = P2^6; //复位端
sbit LCD_RW = P2^5; //写数据端
sbit LCD_EP = P2^7; //使能端
uchar code lcd0[]={"SEARCH ROMING..."};
uchar code lcd1[]={"SEARCH ROM OK!"};
uchar code lcd2[]={"The total is:"};
uchar code lcd3[]={"No.( ):"};
uchar code lcd4[]={'0','1','2','3','4','5','6','7','8','9','.',0xdf,0x43};
uchar dat[6];
uchar read_bit[64];
uchar temp_l,temp_h,is_fuwen,temp_x,temp_over,t;
uchar num=0;
uint i;
uchar al[MAXNUM];
idata uchar ID[MAXNUM][8]; // ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
void alarm_search(void);
void delay(int ms);
BOOL lcd_bz();
void lcd_wcmd(int cmd);
void lcd_pos(BYTE pos);
void lcd_wdat(BYTE dat);
void lcd_init();

/***********************液晶模块**********************************/
void delay(int ms)
{ //延时子程序
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_(); //空执行
_nop_();
_nop_();
_nop_();
}
}
}
BOOL lcd_bz()
{
BOOL result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (BOOL)(P0 & 0x80); //检测P0最高位是否为1
LCD_EP = 0;
return result;//返回侧忙结果
}


/****************写命令函数************************/

void lcd_wcmd_8bit(int cmd)
{ // 写入指令数据到LCD
while(lcd_bz());
LCD_RS = 0;
LCD_RW = 0;
LCD_EP = 0;
_nop_();
_nop_();
P0 = cmd; //将高4位位指令通过P0口传给1602
_nop_();
_nop_(); //用于产生一个脉冲宽度
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
void lcd_wcmd(int cmd)
{ // 写入指令数据到LCD
while(lcd_bz());
LCD_RS = 0;
LCD_RW = 0;
LCD_EP = 0;
_nop_();
_nop_();
P0 = cmd; //将高4位位指令通过P0口传给1602
_nop_();
_nop_(); //用于产生一个脉冲宽度
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
P0 = (cmd&0x0f)<<4; //将低4位指令通过P0口传给1602
_nop_();
_nop_(); //用于产生一个脉冲宽度
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}

void lcd_pos(BYTE pos)
{ //设定显示位置
lcd_wcmd(pos | 0x80);
}
/****************写数据函数************************/
void lcd_wdat(BYTE dat)
{ //写入字符显示数据到LCD
while(lcd_bz());
LCD_RS = 1;
LCD_RW = 0;
LCD_EP = 0;
P0 = dat ; //将高4位数据通过P0口传给1602
_nop_();
_nop_(); //用于产生一个脉冲宽度
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;

LCD_RS = 1;
LCD_RW = 0;
LCD_EP = 0;
_nop_();
_nop_();
_nop_();
_nop_();
P0 = (dat&0x0f)<<4; //将低4位位数据通过P0口传给1602
_nop_();
_nop_(); //用于产生一个脉冲宽度
_nop_();
_nop_();
LCD_EP = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EP = 0;
}
void lcd_init() //LCD初始化设定
{
lcd_wcmd_8bit(0x38); //16*2显示,5*7点阵,8位数据
delay(1);
lcd_wcmd_8bit(0x38); //16*2显示,5*7点阵,8位数据
delay(1);
lcd_wcmd_8bit(0x28); //16*2显示,5*7点阵,8位数据
delay(1);
lcd_wcmd(0x28);
delay(1);
lcd_wcmd(0x0c); //显示开,关光标
delay(1);
lcd_wcmd(0x02); //显示开,关光标
delay(1);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(1);
}

/************************ds18b20****************************/
void delay_nus(uint n)//延时 程序 一次8+6(进出)=14us
{
while(n--);
}
void reset(void) //ds18b20初始化复位操作
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_nus(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_nus(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_nus(10);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_nus(5);
}
void write_bit(uchar dat) //DS18B20 写一位 操作
{
DQ = 0;
_nop_();
_nop_();
DQ = dat&0x01;
delay_nus(5);
DQ = 1;
}
void write_byte(uchar dat)//写一个字节
{
unsigned char i,j;
for (i=8; i>0; i--)
{
j=dat&0x01;
write_bit(j);
dat>>=1;
}
}


uchar read_2bit()//读二位 子程序
{
uchar i;
uchar dat = 0;

for (i=2;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat<<=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x01;
delay_nus(4);
}
return(dat);
}
uchar read_byte()//读一个字节 子程序
{
uchar i=0;
uchar dat = 0;

for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_nus(4);
}
return(dat);
}
void delay_nms(uint n)
{
uint j;
for(j=0;j<n;j++);
}
void read_temp(uchar i)//读取温度 子程序
{
uchar f;
reset();
write_byte(0xcc);
write_byte(0x44);

delay_nms(50000);

reset();
write_byte(0x55);
for(f=0;f<8;f++)
{
write_byte(ID[i][f]);//发匹配ROM
}
delay_nus(100);
write_byte(0xbe);
delay_nus(100);
temp_l=read_byte();
temp_h=read_byte();
}
void temp_convert()//温度转换
{
temp_x=(temp_l&0x0f)*0.625+0.5;
is_fuwen=temp_h&0xf8;
if(is_fuwen)
{
is_fuwen=1;
temp_h=~temp_h;
if(temp_l==0)temp_h++; //若低8位全为0且温度为负,取补时就要向高位进1
temp_l=~temp_l+1;
}

temp_h<<=4;
temp_l>>=4;
temp_over=temp_h|temp_l;
delay_nus(255);
}

/*******************显示***************************/
void _search_cartoon(void)//搜索ROM动画
{
lcd_init();
lcd_wcmd(0x80);
for(i=0;i<16;i++)
{
lcd_wdat(lcd0[i]);
}
lcd_wcmd(0xc0);
for(i=0;i<16;i++)
{
lcd_wdat(0xff);
delay_nms(num*2000);
}
}

void _display_total() //显示总数
{
lcd_init();
lcd_wcmd(0x80);
for(i=0;i<14;i++)
{
lcd_wdat(lcd1[i]);
}
lcd_wcmd(0xc0);
for(i=0;i<13;i++)
{
lcd_wdat(lcd2[i]);
}
lcd_wdat(lcd4[num]);
delay_nms(50000);
delay_nms(50000);
}
void _display_ds18b20(i)//显示编号为i的DS18B20的温度//
{
uint data_b,data_temp,l;
data_b=temp_over/100;//百位//
data_temp=temp_over%100;
dat[0]=data_temp/10;//十位//
dat[1]=data_temp%10;//个位//
dat[2]=10;
dat[3]=temp_x;
dat[4]=11;
dat[5]=12;
lcd_init();
lcd_wcmd(0x80);
for(l=0;l<14;l++)
{
lcd_wdat(lcd1[l]);
}
lcd_wcmd(0xc0);
for(l=0;l<7;l++)
{
lcd_wdat(lcd3[l]);
}
lcd_wcmd(0xc4);
lcd_wdat(lcd4[++i]);
lcd_wcmd(0xc8);
if(is_fuwen==1)
{
lcd_wdat(0x2d);
}
else
{
lcd_wdat(lcd4[data_b]);
}
for(l=0;l<6;l++)
lcd_wdat(lcd4[dat[l]]);
delay_nms(50000);
delay_nms(50000);
}


/***********************自动搜索ROM*****************************/
void search_rom(void)//搜索ROM
{
uchar k,l,chongtuwei,m,n,z;
uchar zhan[(MAXNUM-1)];
uchar ss[64];
l=0;
do

{
reset();
write_byte(0xf0);
for(m=0;m<8;m++)
{
uchar s=0;
for(n=0;n<8;n++)
{
k=read_2bit();//读两位数据
k=k&0x03;
s>>=1;
if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应
{
write_bit (0);
ss[(m*8+n)]=0;
}
else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应
{
s=s|0x80;
write_bit (1);
ss[(m*8+n)]=1;
}
else if(k==0x00)//读到的数据为00 有冲突位 判断冲突位
{ //如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1
chongtuwei=m*8+n+1;
if(chongtuwei>zhan[l])
{
write_bit (0);
ss[(m*8+n)]=0;
zhan[++l]=chongtuwei;
}
else if(chongtuwei<zhan[l])
{
s=s|((ss[(m*8+n)]&0x01)<<7);
write_bit (ss[(m*8+n)]);
}
else if(chongtuwei==zhan[l])
{
s=s|0x80;
write_bit (1);
ss[(m*8+n)]=1;
l=l-1;
}
}
else
{
goto loop;
}
}
ID[num][m]=s;
}
num=num+1;
} while(zhan[l]!=0&&(num<MAXNUM));

loop:_search_cartoon();
_display_total();
}

void match_rom(uchar i)
{
uchar c;
reset();
write_byte(0x55);
for(c=0;c<8;c++)
write_byte(ID[--i][c]);
}

void write_schratchpad(char H,char L)
{
write_byte(0x4e);
write_byte(H);
write_byte(L);
}

void copy_schratchpad()
{
write_byte(0x48);
}

void recall_EE()
{
write_byte(0xb8);
}


void main (void)
{
uchar i;
search_rom();//搜索ROM并且存储
// reset();
// write_byte(0xcc);
// write_schratchpad(30,15);
// reset();
// write_byte(0xcc);
// copy_schratchpad();
reset();
// match_rom(0);
recall_EE();
while(1)
{
unsigned char z,tempt;
for(i=0;i<num;i++) //编号0到num-1 个ds18b20 循环
{
//加的
lcd_wcmd(0x80);//从第一排显示
for (z=0;z<8;z++)
{
tempt = ID[i][z]>>4; //显示高四位
if (tempt<10)
lcd_wdat(tempt + 0x30);
else
lcd_wdat(tempt + 0x37);
tempt = ID[i][z]&0x0f;//显示低四位
if (tempt<10)
lcd_wdat(tempt+ 0x30);
else
lcd_wdat(tempt + 0x37);
}
//加结束
read_temp(i); //读编号 i (0--(num-1)) ds18b20 的温度
temp_convert(); //调用温度转换
_display_ds18b20(i);//显示 编号 i 的温度
}
// alarm_search();
}
while(1);
}
void alarm_search(void)
{
uchar k,l,chongtuwei,m,n,numb,a;
uchar zhan[(MAXNUM-1)];
uchar ss[64],ID0[MAXNUM][8];
l=0;
P0=0xe0;
do
{
reset();
write_byte(0xec);
for(m=0;m<8;m++)
{
uchar s=0;
for(n=0;n<8;n++)
{
k=read_2bit();//读两位数据
k=k&0x03;
s>>=1;
if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应
{
write_bit (0);
ss[(m*8+n)]=0;
}
else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应
{
s=s|0x80;
write_bit (1);
ss[(m*8+n)]=1;
}
else if(k==0x00)//读到的数据为00 有冲突位 判断冲突位
{ //如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1
chongtuwei=m*8+n+1;
if(chongtuwei>zhan[l])
{
write_bit (0);
ss[(m*8+n)]=0;
zhan[++l]=chongtuwei;
}
else if(chongtuwei<zhan[l])
{
s=s|((ss[(m*8+n)]&0x01)<<7);
write_bit (ss[(m*8+n)]);
}
else if(chongtuwei==zhan[l])
{
s=s|0x80;
write_bit (1);
ss[(m*8+n)]=1;
l=l-1;
}
}
else
{
goto loop1;
}
}
ID0[numb][m]=s;
}
numb=numb+1;
}while(zhan[l]!=0&&(numb<MAXNUM));
k=0;
for(m=0;m<numb;m++)
{
for(l=0;l<num;l++)
{
for(n=0;n<8;n++)
{
if(ID0[m][n]==ID[l][n])
{
a++;
if(a==8)
{
al[k]=m;
k++;
}
}
}
a=0;
}
}
lcd_wcmd(0x8f);
for(m=0;m<k;m++)
{
lcd_wdat(lcd4[al[m]+1]);
}
P0=0x00;
loop1: if(P0!=0x00)
P0=0xfe;

}
...全文
110 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧