//学会DS18B20与单片机的连接方法,掌握程序设计思路及编程调试 #include <REGX52.h> #include <intrins.h> //使用NOP函数 #define uchar unsigned char #define uint unsigned int #define NOP _nop_() sbit OE=P3^0; //ADC0808的OE端,转换结果数据允许输出 sbit EOC=P3^1; //ADC0808的EOC端,转换结束的信息 sbit CLOCK=P2^6; //ADC0808工作必需的时钟信号 sbit ST=P3^2; //ADC0808的START和ALE端,开始转换的命令 sbit LED4=P2^3; sbit LED3=P2^2; sbit LED2=P2^1; sbit LED1=P2^0; //温度测量数据线 sbit DQ=P3^5; //温度读取数据线 //共阴数码管显示段码 uchar code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0,0x40}; //带小数点数字 uchar code tab1[]={0xbF,0x86,0xdB,0xcF,0xe6,0xeD,0xfD,0x87,0xfF,0xeF}; //温度的小数位 uchar code tab2[]={0x00,0x06,0x12,0x19,0x25,0x31,0x38,0x44,0x50,0x56,0x63,0x69,0x75,0x81,0x88,0x94}; uchar dat[]={0,0,0,0}; //显示缓冲区 uchar adc; //存放ADC0809转换后的数据 unsigned int tmp; uchar temp_h,temp_l; /*温度值变量*/ bit flag; /*正负标志位*/ void Delay(void) { unsigned char i; for(i=0;i<250;i++); } //温度DS18B20子程序 //函数功能:延时 us void Delay_us(uchar n) { uchar i; i=0; while(i<n) {i++;} return; } //DS18B20复位 void dsreset(void) { unsigned int i; DQ=0; i=103; while(i>0)i--; DQ=1; i=4; while(i>0)i--; } //读1个字节数据 uchar ReadByte(void) { uchar i,k; i=8; k=0; while(i--) //8位数据循环读 { DQ=1; Delay_us(1); //延时1us DQ=0; k=k>>1; DQ=1; NOP; if(DQ)k |= 0x80; //读出数据存入K Delay_us(4); } return(k); } //写入1个字节数据 void tmpwrite(unsigned char dat) { unsigned int i; unsigned char j; bit testb; //定义位变量 for(j=1;j<=8;j++) { testb=dat&0x01; //求出位数据 dat=dat>>1; if(testb) { DQ=0;i++;i++; //i用于确定高低电平时间 DQ=1; i=8;while(i>0)i--; } else { DQ=0; i=8;while(i>0)i--; DQ=1;i++;i++; } } } //启动温度转换 void tmpchange(void) { dsreset(); /*复位*/ Delay(); tmpwrite(0xcc); //跳过序列号命令 tmpwrite(0x44); //转换命令 } //将温度值读出来并转化为显示数组 void temp(void) { uint dis; //数据变量 char xiaos,xsxs,jh; //温度的小数位,显示小数数据 dsreset(); //DS18B20复位 Delay(); tmpwrite(0xcc); //写入命令 tmpwrite(0xbe); //写入命令 temp_l=ReadByte(); //读取温度,低位在前 temp_h=ReadByte(); //读取温度,高位在后 flag=temp_h&0xf8; //判断温度正负值 if(flag) //flag1=1,温度为负值 { temp_h=~temp_h; //把补码变为反码 if(temp_l==0)temp_h++; //若低8位全为0且温度为负,取补时就要向高位进1 temp_l=~temp_l+1; } dis=(temp_h*256+temp_l)/16; //求出温度值(此求法只求整数温度值) xiaos=temp_l&0x0f; /* switch(xiaos) { case 0x00: xsxs=0; case 0x01: xsxs=0x06; break; case 0x02: xsxs=0x12; break; case 0x03: xsxs=0x19; break; case 0x04: xsxs=0x25; break; case 0x05: xsxs=0x31; break; case 0x06: xsxs=0x38; break; case 0x07: xsxs=0x44; break; case 0x08: xsxs=0x50; break; case 0x09: xsxs=0x56; break; case 0x0a: xsxs=0x63; break; case 0x0b: xsxs=0x69; break; case 0x0c: xsxs=0x75; break; case 0x0d: xsxs=0x81; break; case 0x0e: xsxs=0x88; break; case 0x0f: xsxs=0x94; break; } */ xsxs=tab2[xiaos]; if (flag) //如果温度是负数,只显示1位整数,1位符号,2位小数 { dat[0]=tab[11]; //显示符号 dat[1]=tab1[dis%10]; //显示1位整数和小数点 jh=(xsxs>>4); dat[2]=tab[jh]; //显示两位小数 dat[3]=tab[(xsxs&0x0f)]; } if((dis<10)&&(!flag)) //温度只1位整数值,最高位不显示 { dat[0]=tab[10]; //不显示 dat[1]=tab1[dis%10]; //显示1位整数和小数点 jh=(xsxs>>4); dat[2]=tab[jh]; //显示两位小数 dat[3]=tab[(xsxs&0x0f)]; } else { if ((dis<100)&&(!flag)) //显示2位整数 { dat[0]=tab[dis/10]; //整数十位 dat[1]=tab1[dis%10]; //显示整数个位和小数点 jh=(xsxs>>4); dat[2]=tab[jh]; //显示两位小数 dat[3]=tab[(xsxs&0x0f)]; } else //显示3位整数 {if ((dis>100)&&(!flag)) { dat[0]=tab1[(dis/10)%10]; //整数十位并标记百位 dat[1]=tab1[dis%100]; //显示整数个位和小数点 jh=(xsxs>>4); dat[2]=tab[jh]; //显示两位小数 dat[3]=tab[(xsxs&0x0f)]; } } } } //显示子程序 void disp() { uchar i1,wei; wei=0xfe; for (i1=0;i1<4;i1++) { P0=dat[i1]; P2=wei; Delay(); P2=0xff; wei=(wei<<1)|0x01; } } //----------------------------主函数-----------------------------// void main(void) { SP=0x70; /* EA=1; ET0=1; TMOD=0x02; // T0方式2计时 TH0=0x01; // 晶振:12MHz TL0=0x01; // 晶振:12MHz TR0=1; // 开中断,启动定时器 */ //DS18B20读取、转换、显示 while(1) { tmpchange(); /*启动温度转换*/ // Delay(); /*等待转换结束,可不用,会对显示产生影响*/ temp(); /*读取温度转换结果*/ disp(); /*温度显示和报警*/ /*ADC0809 ST=0; ST=1; ST=0; //启动转换 while(!EOC); //等待转换结束 OE=1; //允许输出 adc=P1; //取转换结果 //数据处理,已备显示 tmp=adc*196; //乘以19.6MV dat[3]=tmp/10000; dat[2]=tmp/1000%10; dat[1]=tmp/100%10; dat[0]=tmp/10%10; */ /* //数码管显示转换结果 LED1=0; P0=tab[dat[3]]+0x80; Delay(); LED1=1; LED2=0; P0=tab[dat[2]]; Delay(); LED2=1; LED3=0; P0=tab[dat[1]]; Delay(); LED3=1; LED4=0; P0=tab[dat[0]]; Delay(); LED4=1;*/ } // end while } // end main /* 定时计数器0的中断服务子程序 */ //* void timer0(void) interrupt 1 using 1 // 50mS中断一次 { CLOCK=~CLOCK; }
|
|
来自: 昵称49875672 > 《待分类》