|
|
临时起意作案: 不锈钢外壳探头,可以测液体温度,顺手做了木壳。左1数码管显示符号位“-”,正温度则不显示,没有考虑>=100摄氏度时进位的问题,所以量程-55~99.9℃. 作案工具,【小推兔】赞助的T12-C4大马蹄。 烧录用Esay 51 Pro V2.0(EP51),因为笔记本没有COM接口,所以用到了上次修好的CH340G USB-TTL小板。 STC快用完了,临时起意把还有很多的AT拿来换上,把EA引脚接高电平就可以代换。--------------------------------------------------------------------------------------------------------下面Po上代码: /*MCU = AT89S51CLOCK = 12MHzSensor = DS18B20*/#include <reg51.h>#include <intrins.h> #define uchar unsigned char sbit DS18B20_data = P1^0;//DS18B20数据线; uchar time;//精确延时专用变量;uchar code table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x7f};//数码管共阳极接法,负逻辑,0~9和小数点; void delay(uchar x);//延时x ms;void DS18B20_init();//初始化DS18B20;void write_byte(uchar dat);//写字节;void wait_to_read_byte();//准备读字节;uchar read_byte();//读字节;void display(uchar symbol, A, B, C);//显示结果; void main(){ uchar symbol;//符号位; uchar temp;//温度值临时变量; uchar TH, TL;//温度数据高低八位; uchar TN, TD;//温度值整数、小数部分; uchar A, B, C;//十位, 个位, 十分位; while(1){ wait_to_read_byte(); TL = read_byte(); TH = read_byte(); if((TH&0xf8)!= 0x00)//判断符号位; {symbol = 1;}//温度值为负; else {symbol = 0;}//温度值为正; if(symbol) { TL = ~TH; TH = ~TH; temp = TL + 1; TL = temp;//负温度时预处理; TN = TH<<4|TH>> 4;//温度值整数部分; TD = (((TL<<4) / 128*80) + ((TL<<5) / 128*40) + ((TL<<6) / 128*20) + ((TL<<7) / 128*10)) / 16;//温度值小数部分; } else { TN = TH<<4|TL>>4;//温度值整数部分; TD = (((TL<<4) / 128*80) + ((TL<<5) / 128*40) + ((TL<<6) / 128*20) + ((TL<<7) / 128*10)) / 16;//温度值小数部分; } A = TN / 10;//温度值十位; B = TN % 10;//温度值个位; C = TD;//温度值十分位; display(symbol, A, B, C);//显示结果 P1 = 0xff;//显示消隐;}} void delay(uchar x){ uchar i, j; for(i = x*2; i>0; i--) for(j = 250; j>0; j--);} void DS18B20_init(){ DS18B20_data = 1;//数据总线置高电平; for(time = 2; time>0; time --);//延时6us,去抖动; DS18B20_data = 0;//数据总线置低电平; for(time = 180; time>0; time--); for(time = 180; time>0; time--);//延时724us; DS18B20_data = 1;//数据总线置高电平; for(time = 180; time>0; time--); for(time = 180; time>0; time--);//延时724us;} void write_byte(uchar byte){ uchar i = 0; for(i = 8; i>0; i--){ DS18B20_data = 1;//释放数据总线; _nop_();//延时1us; DS18B20_data = 0;//数据总线置低电平; DS18B20_data = byte & 0x01;//按位与取出位值; for(time = 15; time>0; time--);//延时32us; DS18B20_data = 1;//释放数据总线; for(time = 1; time >0; time--);//延时3us; byte >>= 1;//byte右移1位; } for(time = 4; time>0; time--);//延时10us;} void wait_to_read_byte(){ DS18B20_init();//初始化DS18B20; write_byte(0xcc);//写命令,跳过ROM; write_byte(0x44);//写命令,启动温度转换; delay(1);//延时1ms; DS18B20_init();//初始化DS18B20; write_byte(0xcc);//写命令,跳过ROM; write_byte(0xbe);//写命令,读Cache;} uchar read_byte(){ uchar i = 8; uchar byte; for(i = 8; i>0; i--){ DS18B20_data = 1;//释放数据总线; _nop_();//延时1us; DS18B20_data = 0;//数据总线置低电平; _nop_();//延时1us,启动读时序; DS18B20_data = 1;//释放数据总线; for(time = 2; time>0; time--);//延时6us,等待采样; byte >>= 1;//byte右移一位,最高位缺省值为0; if(DS18B20_data) {byte |= 0x80;}//byte最高位赋值1; else {byte |= 0x00;}//byte最高位赋值0; for(time = 30; time>0; time--);//延时62us; } return byte;//返回byte的值} void display(uchar symbol, A, B, C){ P2 = 0xfe;//数码管第1位使能; if(symbol) {P0 = 0xbf; delay(1);//延时1ms; }//显示负号; P0 = 0xff;//显示消隐;/**********显示符号位**********/ P2 = 0xfd;//数码管第2位使能; P0 = table[A];//显示十位; delay(1);//延时1ms; P0 = 0xff;//显示消隐;/**********显示十位**********/ P2 = 0xfb;//数码管第3位使能; P0 = table;//显示个位; delay(1);//延时1ms; P0 = 0xff;//显示消隐;/**********显示个位**********/ P2 = 0xfb;//数码管第3位使能; P0 = table[10];//显示小数点; delay(1);//延时1ms; P0 = 0xff;//显示消隐;/**********显示小数点**********/ P2 = 0xf7;//数码管第4位使能; P0 = table[C];//显示小数; delay(1);//延时1ms; P0 = 0xff;//显示消隐;/**********显示小数**********/}---------------------------------注意:数码管我用了共阳极形式,4个9012 PNP二极管作位使能,很好的利用了P0的开漏输出能力,连上拉电阻都省了。更多作品见:51 + ADC0804【电压表】http://bbs.mydigit.cn/read.php?tid=2511907AT89C2051 + BH1750FVI【照度计】 http://bbs.mydigit.cn/read.php?tid=2513384 [ 此帖被小陈兔在2018-08-28 23:05重新编辑 ]
|