////////////////////////////////////////////////// #include<reg51.h> #include<stdio.h> #include<math.h> #define uint unsigned int #define uchar unsigned char sbit DRV_EN=P2^6; sbit FUNC_KEY=P1^0; sbit DQ=P3^7; uchar tplsb,tpmsb; uint LEDBIT_B, LEDBIT_S, LEDBIT_G; uchar dis_buf[6]; uchar code LED1[6]={0xBE,0xBD,0xBB,0xB7,0xAF,0x9F};///位选 //uchar code LED1[6]={0x9F,0xAF,0xB7,0xBB,0xBD,0xBE};///位选 uchar code LEDSEG[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7C,0x07,0x7F,0x6F};//0,1,2,3,4,5,6,7,8,9
//****************调用延时子程序********************** void delay(uint x) { uint j; while (x--) { for(j=0;j<125;j++) /////////对于11.0592M时钟,延时约1MS {;} } }
//////////////显示函数/////// void display(void) {uint i; for(i=0;i<6;i++) {P2=LED1; P0=dis_buf; delay(2); } }
///////////////产生复位脉冲初始化DS18B20////////////// void TXRESET(void) { uint i; DQ=0; i=100; while(i>0) /////////////将DQ拉低约900US { i--; } DQ=1; ////////产生上升沿脉冲 i=4; while(i>0) { i--; } }
//////////////////等待应答脉冲////////////// void RXWAIT(void) { uint i; while(DQ); while(!DQ); i=4; while(i>0) { i--; } }
/////////////////////读取数据的一位,满足读时隙要求//////////// bit RDBIT(void) { uint i; bit b; DQ=0; i++; ////////////保持至少1US DQ=1; i++;i++; ///////////延15US。读时隙下降沿后15US,DS18B20输出数据才有效 b=DQ; i=8; ////////////读时隙不低于60US while (i>0) { i--; } return(b); }
////////////////读取数据的一个字节///////////////////// uchar RDBYTE(void) { uchar i,j,b; b=0; for(i=1;i<=8;i++) { j=RDBIT(); b=(j<<7)|(b>>1); } return(b); }
/////////////写数据一个字节,满足写1和写0的时隙的要求///////// void WRBYTE (uchar b) { uint i; uchar j; bit btmp; for(j=1;j<=8;j++) { btmp=b&0x01; b=b>>1; /////////////取下一位(由低位向高位) if(btmp) { DQ=0; ///////////写1/////////// i++;i++; ////////延15US 拉高总线 DQ=1; i=8; while (i>0) { i--; } } else //////////写0///////// { DQ=0; i=8; while(i>0)///////////保持低电平在60US到120US之间 { i--; } DQ=1; i++; i++; } } }
///////////////启动温度转换///////////// void convert (void) { TXRESET(); ///////////产生复位脉冲,初始化DS18B20 RXWAIT(); ////////////等待DS18B20给出应答脉冲 delay(1); WRBYTE(0xCC); //////skip rom命令 WRBYTE(0x44);////////convert T命令 }
///////////读取温度值///////////////// void RDTEMP(void) { TXRESET(); RXWAIT(); delay(1); WRBYTE(0xcc); WRBYTE(0xbe); tplsb=RDBYTE(); //////// 温度值地位字节(其中低4位为2进制的“小数”部分) tpmsb=RDBYTE(); //////// 高位值高位字节(其中高5位为符号位) }
//////////主程序////////////////////////读取的温度值最终存放在tplsb和tpmsb变量中,tplsb其中低位4位为2进制小数部位,tpmsb的高5位为符号位。通过数码管输出时,需要进行到10进制有符号实数(包括小数)的转换。
void main(void) {
uint a,b,c,d,e,f,g,h; DRV_EN=1;//关闭总的驱动74HC244 P0=0x00; DRV_EN=0;//总的驱动74HC244 TMOD=0x01; ///10MS中断 TH0=0xD8; TL0=0xF0; TR0=1; ET0=1; EA=0; while(1) { delay(1); convert(); //////启动温度转换,需要750MS delay(1000); //////延时1S RDTEMP(); //////读取温度 //a=tplsb&0x10; //b=tplsb&0x20; //c=tplsb&0x40; //d=tplsb&0x80; //e=tpmsb&0x01; //f=tpmsb&0x02; //g=tpmsb&0x04;
if(tplsb&0x10==0x10) /////////数据转换 { a=1; } else { a=0; } if(tplsb&0x20==0x20) { b=1; } else { b=0; } if(tplsb&0x40==0x40) { c=1; } else { c=0; } if(tplsb&0x80==0x80) { d=1; } else { d=0; } if(tpmsb&0x01==0x01) { e=1; } else { e=0; } if(tpmsb&0x02==0x02) { f=1; } else { f=0; } if(tpmsb&0x04==0x04) { g=1; } else { g=0; }
h=(a*1)+(b*2)+(c*2*2)+(d*2*2*2)+(e*2*2*2*2)+(f*2*2*2*2*2)+(g*2*2*2*2*2*2); LEDBIT_B=(h/100)%10; LEDBIT_S=(h/10)%10; LEDBIT_G=h%10; dis_buf[0]=LEDSEG[LEDBIT_B]; dis_buf[1]=LEDSEG[LEDBIT_S]; dis_buf[2]=LEDSEG[LEDBIT_G]; //display(); //delay(2); //DRV_EN=1; } }
void t0(void) interrupt 1 using 0 { TR0=0; TH0=0xD8; TL0=0xF0; TR0=1; DRV_EN=1; display(); delay(5); DRV_EN=1;
}
硬件接口: 1, P0口数码管段码. 2, P2.0~P2.5数码管位码(当然在实际中只想用其中3位数码管显示). 3, P2.6数码管总驱动. 4, P3.7 DS18B20 的信号线 DQ. 温度传感器用了外电源VDD的 5, 晶震12M.
现象: 1, 用上面程序时,数码管没有显示. 2,a 将主程序中的EA=1;该为:EA=0(不用中断); b 且将delay(1000);去掉; c在主程序强制循环中 加入display(); 后 数码管显示112和127(只用了3位数码管112和127各显示一小会). 问题: 1,为什么用中断显示数码管的时候 数码管没有显示.? 2,为什么温度是112和127,我用手拿着DS18B20一会 数码管显示也没有改变,说明温度的读取就有问题.?
求: 各位大吓帮我瞧瞧.主要是上面2个问题(希望详细的说出那里有问题,不要光说个 时序 问题),拜谢各位了.
|