基于LCD12864的温度传感器DS18b20的显示程序
基于Arduino的18B20+LCD12864温度显示
基于Arduino的18B20+LCD12864温度显示本帖最后由 greenfort 于 2012-8-13 01:49 编辑初学Arduino,制作的通过12864显示多个18B20温度的程序接线请参考本论坛中的18B20及LCD12864与Arduino接线,这里不再重复,只是强调一点,18B20的PIN1和PIN3要同时接地,否则会在返回若干值后出现一次错误值(85.00)不知道什么原因鉴于12864的显示大小,程序最多接9个18B20传感器,多了显示不了程序代码如下1. /*2. LCD Arduino3. PIN1 = GND4. PIN2 = 5V5. RS(CS) = 8;6. RW(SID)= 9;7. EN(CLK) = 3;8. PIN15 PSB = GND;9. */10. #include <OneWire.h>11. #include <DallasTemperature.h>12. #include <stdlib.h>13. #define ONE_WIRE_BUS 214. #include "LCD12864RSPI.h"15. #define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )16.17. OneWire oneWire(ONE_WIRE_BUS);18. DallasTemperature sensors(&oneWire);19.20. char str[4]; //定义温度值存储数组,4位,其中3位为数字,1位为小数点21. double temp =0; //定义中间变量,用于将获取的float型温度值转变为unsigned char数组22. unsigned char show[]={23. 0xB5,0xB1,0xC7,0xB0,0xBB,0xB7,0xBE,0xB3,0xCE,0xC2,0xB6,0xC8};//当前环境温度24. int numberOfDevices;25. void setup()26. {27. Serial.begin(9600);28. sensors.begin(); //传感器初始化29. numberOfDevices = sensors.getDeviceCount();30. LCDA.Initialise(); // 屏幕初始化31. LCDA.DisplayString(0,0,show,AR_SIZE(show));//第一行第1格开始,显示文字“当前环境温度”32. }33.34. void loop()35. {36. sensors.requestTemperatures(); //获取温度值37. for(int i=0;i<numberOfDevices; i++) //逐个获取传感器的温度38. {39. temp=sensors.getTempCByIndex(i); //使用索引序号获得摄氏度数值40. dtostrf(temp,4,2,str); //将获取的数值转换为字符型数组41. if (i<=2)42. {43. LCDA.DisplayString(1,i*3,(unsigned char *)str,sizeof(str));。
DS18B20数码管显示程序
void LED7_Init()
{
DDRA|=(1<<3)|(1<<4);
DDRB=0xff;
DDRA=0x18;
DDRB=0xff;
}
void Number_Show(unsigned int num)
{
PORTB=Number[num/1000%10];
PORTA|=(1<<3); //PA3=1;
PORTA|=BIT(DQ); //释放总线
_delay_us(1); //稍微延迟
Data>>=1;
}
}
//DS1302读字节函数
unsigned char DS1302_Read()
{
unsigned char i,Temp=0;
for(i=0;i<8;i++)
PORTA&=~BIT(DQ); //输出低电平
_delay_us(500); //延迟500微妙
PORTA|=BIT(DQ); //示范总线
_delay_us(60); //延迟60微妙
DDRA&=~BIT(DQ); //DQ位输出状态
while(PINA&BIT(DQ)); //等待从机DS18B20应答(低电平有效)
PORTA&=~(1<<3); //PA3=0;
PORTB=0xf7;
PORTA|=(1<<4); //PA3=1;
PORTA&=~(1<<4)//DS1302复位函数
void DS1302_Reset()
DS18B20温测 12864显示
#include<reg52.h>#include<intrins.h> //包含_nop_()函数定义的头文件#define uint unsigned int#define uchar unsigned charsbit ds=P3^3; //DS18B20接口uint temp;float f_temp;//12864端口定义sbit LCD12864_RS=P2^0;sbit LCD12864_WR=P2^1;sbit LCD12864_E=P2^2;sbit LCD12864_PSB=P2^3;sbit LCD12864_busy=P0^7;#define LCD12864_dat P0void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--) ;}//****************************************//以下为12864液晶显示部分子程序模块//****************************************//函数定义void wr_d_lcd(uchar content);void wr_i_lcd(uchar content);void clrram_lcd (void);void init_lcd(void);void busy_lcd(void);void rev_row_lcd(uchar row);void rev_co_lcd(uchar row,uchar col,uchar mode);void clr_lcd(void);void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);void wr_row_lcd(uchar row,char *p);//延时子程序模块//**********************************************void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<80;i++) //1ms延时.{;}}}//***********************************//填充液晶DDRAM全为空格//**********************************void clrram_lcd (void){wr_i_lcd(0x30);wr_i_lcd(0x01);}//***********************************//对液晶写数据//content为要写入的数据//***********************************//*********************写数据函数void wr_d_lcd(uchar content){busy_lcd();LCD12864_RS=1;LCD12864_WR=0;LCD12864_dat=content;LCD12864_E=1;;LCD12864_E=0;}//********************************//对液晶写指令//content为要写入的指令代码//*****************************//**************************写命令函数void wr_i_lcd(uchar content){busy_lcd();LCD12864_RS=0;LCD12864_WR=0;LCD12864_dat=content;LCD12864_E=1;;LCD12864_E=0;}//********************************//液晶检测忙状态//在写入之前必须执行//********************************void busy_lcd(void){LCD12864_dat=0xff;LCD12864_RS=0;LCD12864_WR=1;LCD12864_E =1;while(LCD12864_busy==1);LCD12864_E=0;}//**********************************//液晶初始化//**********************************void init_lcd(void){wr_i_lcd(0x30);wr_i_lcd(0x06); /*光标的移动方向*/wr_i_lcd(0x0c); /*开显示,关游标*/wr_i_lcd(0x01); //清屏}//********************************//指定要显示字符的坐标//*******************************void LCD12864_pos(unsigned char y, unsigned char x){if(y==1)wr_i_lcd(0x80|x);if(y==2)wr_i_lcd(0x90|x);if(y==3)wr_i_lcd((0x80|x)+8);if(y==4)wr_i_lcd((0x90|x)+8);}//**********************************//液晶显示字符串程序//**********************************void LCD12864print(uchar *str){while(*str!='\0'){wr_d_lcd(*str);str++;}}//**********************************//液晶显示位置、字符串、显示间隔时间//**********************************//LCD12864_display1(1,3,500,"中国CHN")//意思为在第1行第4列显示"中国CHN",每个字显示间隔为500ms LCD12864_display1(unsigned char y, unsigned char x,uint t, uchar *str) {LCD12864_pos(y,x);while(*str!='\0'){wr_d_lcd(*str);str++;delay(t);}}LCD12864_display2(unsigned char y, unsigned char x,uchar n){LCD12864_pos(y,x);wr_d_lcd(0x30+n);}//此函数是显示变量的,比如要在第1行第2列显示一个不断变化的变量a代表的值,//就用LCD12864_display2(1,2,a);//****************************************//以上为12864液晶显示部分子程序模块//****************************************/*****************************************************以下为DS18B20模块语句***************************************************//*void delay(uint z)//延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}*/void dsreset(void) //18B20复位,初始化函数{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit tempreadbit(void) //读1位函数{uint i;bit dat;ds=0;i++; //i++ 起延时作用ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return (dat);}uchar tempread(void) //读1个字节{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DA T里}return(dat);}void tempwritebyte(uchar dat) //向18B20写一个字节数据{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb) //写1{ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0; //写0i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) //DS18B20 开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc); // 写跳过读ROM指令tempwritebyte(0x44); // 写温度转换指令}uint get_temp() //读取寄存器中存储的温度数据{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread(); //读低8位b=tempread(); //读高8位temp=b;temp<<=8; //两个字节组合为1个字temp=temp|a;f_temp=temp*0.0625; //温度在寄存器中为12位分辨率位0.0625°temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入f_temp=f_temp+0.05;return temp; //temp是整型}/*****************************************************以上为DS18B20模块语句***************************************************/void dis_temp(uint t){uchar shi,ge,xiao;shi=t/100;//十位ge=t%100/10;//个位xiao=t%100%10;//小数位LCD12864_display1(1,0,0,"当前温度为:");LCD12864_display1(3,0,0,"摄氏度");LCD12864_display2(3,3,shi);LCD12864_display2(3,4,ge);LCD12864_display1(3,5,0,".");LCD12864_display2(3,6,xiao);LCD12864_display1(3,7,0,"C");}main(){init_lcd();while(1){tempchange();dis_temp(get_temp());}}。
用DS18B20测温度并用LCD12864液晶屏显示
本程序实现的功能:用DS18B20测温度,并用LCD12864液晶屏显示#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charsbit rs=P1^1;sbit rw=P1^2;sbit en=P1^3;sbit psb=P1^4;sbit ds=P1^5;uchar code table0[]="Current temp:";uchar code table1[]="当前温度:";uchar code table2[]="摄氏度";uchar table[4];uint temp;float f_temp;void delay(uint tms){uint i,j;for(i=tms;i>0;i--)for(j=110;j>0;j--);}void init_ds(){uint i;ds=0;i=103;while(i>0)ds=1;i=4;while(i>0)i--;}void tempwritebyte(uchar )//由时序图知,向DS18B20写入数据时,写0和写1的时序恰好相反{ //所以如下程序用if和else分别写入0和1;而当从DS18B20读数据时,uint i,j; //读0和读1的时序根本一样,所以读0和读1的程序合二为一,不用分别写出bit bb;for(i=0;i<8;i++){bb=&0x01;//最低位开始写入DS18B20=>>1;if(bb){ds=0;j++;j++;ds=1;j=8;while(j>0)j--;}else{j=8;while(j>0)j--;ds=1;j++;j++;}}}void tempchange(){init_ds();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uchar tempreadbyte()//由时序图知,向DS18B20写入数据时,写0和写1的时序恰好相反{ //所以如下程序用if和else分别写入0和1;而当从DS18B20读数据时,uchar i,j,m,n; //读0和读1的时序根本一样,所以读0和读1的程序合二为一,不用分别写出bit dat;for(i=0;i<8;i++){ds=0;j++;j++;ds=1;j++;j++;dat=ds;j=8;while(j>0)j--;m=dat;//把一位数据赋给一个字节,且从最低位开始读数n=(m<<7)|(n>>1);}return n; //必须将n值返回去,以赋给a和b}void get_temp(){uchar a,b;init_ds();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempreadbyte();b=tempreadbyte();temp=b;temp<<=8;temp=temp|a;f_temp=temp*0.0625*10+0.5;//保存一位小数,且最低位四舍五入temp=f_temp;//return temp;}void wr_data(date) {rs=1;rw=0;en=0;P0=date;delay(3);en=1;delay(3);en=0;}void wr_(uchar ) {rs=0;rw=0;en=0;P0=;delay(3);en=1;delay(3);en=0;}void lcd_init() {psb=1;wr_(0x30);delay(3);wr_(0x0c);delay(3);wr_(0x06);delay(3);// wr_(0x01);// delay(3);}void lcd_pos(uchar X,uchar Y){if(X==0)X=0x80;else if(X==1)X=0x90;else if(X==2)X=0x88;else if(X==3)X=0x98;wr_(X+Y);}void display()//显示第一行为 current temp: { //第二行为当前温度:uchar i; //第三行为 xxx摄氏度table[0]=temp/100+'0';table[1]=temp/10%10+'0';table[2]='.';table[3]=temp%10+'0';lcd_pos(2,2);for(i=0;i<4;i++)wr_data(table[i]);lcd_pos(2,4);i=0;while(table2[i]!='\0'){wr_data(table2[i]);i++;}lcd_pos(0,0);i=0;while(table0[i]!='\0'){wr_data(table0[i]);i++;}lcd_pos(1,0);i=0;while(table1[i]!='\0'){wr_data(table1[i]);i++;}}void main(){lcd_init();while(1){tempchange();get_temp();display();}}。
12864_ds18b20
Init_DS18B20();
WriteOneChar(0xcc);//发跳过ROM命令
WriteOneChar(0x44);//发读开始转换命令
Init_DS18B20();
WriteOneChar(0xcc);//发跳过ROM命令
WriteOneChar(0xbe);//读寄存器,共九字节,前两字节为转换值
0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,
/*-- 文字: 度 --*/
/*-- 新宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
/*-- 文字: . --*/
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时3微秒。
(5)将数据线拉高“1”。
(6)延时5微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时60微秒。
*/
uchar ReadOneChar(void)
{
uchar i;
uchar dat=0;
x3=temp%100/10; //个位
x4=temp%10; //小数
/* P2 = 0xf1; P0 = table[x1]; delay(x);//百
P2 = 0xf2; P0 = table[x2]; delay(x);//十
P2 = 0xf4; P0 = table1[x3]; delay(x);//个
12864串行显示DS18B20测得的温度
uchar start_data,Hdata,Ldata;
if(start==0)
start_data=0xf8; //写指令
else
start_data=0xfa; //写数据
Hdata=onedata&0xf0; //取高四位
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DS1820_DQ = 0; //将总线拉低,要在1us之后释放总线
dat>>=1; //让从总线上读到的位数据,依次从高位移动到低位。
DS1820_DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上
temp1=DS1820_ReadByte(); //读取温度值低位
temp2=DS1820_ReadByte(); //读取温度值高位
DS1820_Reset(); //DS1302 复位,表示读取结束
tt=((temp2<<8)|temp1)*6.25; //得到真实十进制温度值 //0.0625=xx, 0.625=xx.x, 6.25=xx.xx
delay(10); //延时是必须的
}
void initinal() //LCD字库初始化程序
{
write(0,0x30); //8 位介面,基本指令集
write(0,0x0c); //显示打开,光标关,反白关
write(0,0x01); //清屏,将DDRAM的地址计数器归零
Ldata=(onedata<<4)&0xf0; //取低四位
ds18b20详解及程序
d s18b20详解及程序(总1页) -CAL-FENGHAI.-(YICAI)-Company One1
-CAL-本页仅作为文档封面,使用请直接删除
最近都在学习和写单片机的程序, 今天有空又模仿DS18B20温度测量显示实验写了一个与DS18B20基于单总线通信的程序.
DS18B20 数字温度传感器(参考:智能温度传感器DS18B20的原理与应用)是DALLAS 公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计。
DS18B20 产品的特点:
(1)、只要求一个I/O 口即可实现通信。
(2)、在DS18B20 中的每个器件上都有独一无二的序列号。
(3)、实际应用中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55 到+125℃之间; 在-10 ~ +85℃范围内误差为
±5℃;
(5)、数字温度计的分辨率用户可以从9 位到12 位选择。
将12位的温度值转换为数字量所需时间不超过750ms;(6)、内部有温度上、下限告警设置。
DS18B20引脚分布图
DS18B20 详细引脚功能描述:
1、GND 地信号;
2、DQ数据输入出引脚。
开漏单总线接口引脚。
当被用在寄生电源下,此引脚可以向器件提供电源;漏极开路, 常太下高电平. 通常要求外接一个约5kΩ的上拉电阻.
3、VDD可选择的VDD 引脚。
电压范围:3~5.5V; 当工作于寄生电源时,此引脚必须接地。
DS18B20存储器结构图
暂存储器的头两个字节为测得温度信息的低位和高位字节;。
单片机DS18B20温度计(有程序)
;单片机DS18B20温度计C语言程序; 有程序#include<reg51.h>#include<intrins.h>#include <math.H> //要用到取绝对值函数abs()//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125度sbit wela = P2^7; //数码管位选sbit dula = P2^6; //数码管段选sbit ds = P2^2;int tempValue;//0-F数码管的编码(共阳极)unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//0-9数码管的编码(共阳极), 带小数点unsigned char code tableWidthDot[]={0x40, 0x79, 0x24, 0x30,0x19, 0x12, 0x02,0x78, 0x00, 0x10};//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.void delay(unsigned int i){unsigned int j;while(i--){for(j = 0; j < 125; j++);}}//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动 void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us unsigned int i;ds = 0;i = 100; //拉低约800us, 符合协议要求的480us以上while(i>0) i--;ds = 1; //产生一个上升沿, 进入等待应答状态i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds);while(~ds); //检测到应答脉冲i = 4;while(i > 0) i--;}//向DS18B20读取一位数据//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,//之后DS18B20则会输出持续一段时间的一位数据bit readBit(){unsigned int i;bit b;ds = 0;i++; //延时约8us, 符合协议要求至少保持1usds = 1;i++; i++; //延时约16us, 符合协议要求的至少延时15us以上b = ds;i = 8;while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求return b;}//读取一字节数据, 通过调用readBit()来实现unsigned char readByte(){unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}//向DS18B20写入一字节数据void writeByte(unsigned char dat){unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){ds = 0;i++; i++; //拉低约16us, 符号要求15~60us内ds = 1;i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120usds = 0;i = 8; while(i>0) i--; //拉低约64us, 符号要求ds = 1;i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us 了}}//向DS18B20发送温度转换命令void sendChangeCmd(){dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化dsWait(); //等待DS18B20应答delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0x44); //写入温度转换命令字Convert T}//向DS18B20发送读取数据命令void sendReadCmd(){dsInit();dsWait();delay(1);writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0xbe); //写入读取数据令字Read Scratchpad}//获取当前温度值int getTmpValue(){unsigned int tmpvalue;int value; //存放温度数值float t;unsigned char low, high;sendReadCmd();//连续读取两个字节数据low = readByte();high = readByte();//将高低两个字节合成一个整形变量//计算机中对于负数是利用补码来表示的//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的valuetmpvalue = high;tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度t = value * 0.0625;//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}unsigned char const timeCount = 3; //动态扫描的时间间隔//显示当前温度值, 精确到小数点后一位//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码void display(int v){unsigned char count;unsigned char datas[] = {0, 0, 0, 0, 0};unsigned int tmp = abs(v);datas[0] = tmp / 10000;datas[1] = tmp % 10000 / 1000;datas[2] = tmp % 1000 / 100;datas[3] = tmp % 100 / 10;datas[4] = tmp % 10;if(v < 0){//关位选, 去除对上一位的影响P0 = 0xff;wela = 0;//段选P0 = 0x40; //显示"-"号dula = 1; //打开锁存, 给它一个下降沿量dula = 0;//位选P0 = 0xfe;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}for(count = 0; count != 5; count++){//关位选, 去除对上一位的影响P0 = 0xff;wela = 1; //打开锁存, 给它一个下降沿量wela = 0;//段选if(count != 2){P0 = table[datas[count]]; //显示数字}else{P0 = tableWidthDot[datas[count]]; //显示带小数点数字}dula = 0;//位选P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管wela = 1; //打开锁存, 给它一个下降沿量wela = 0;delay(timeCount);}}void main(){unsigned char i;while(1){//启动温度转换sendChangeCmd();//显示5次for(i = 0; i < 40; i++){display(tempValue);}tempValue = getTmpValue();}以下是我编的程序,可用#include <reg52.h>#include <intrins.h>//-----------------------------------------------------------sbit DQ=P1^5;//-----------------------------------------------------------unsigned char number[10]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};//数字0~9unsigned char wei[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位循环unsigned char Flag;unsigned char Templ,Temph;unsigned int temp;//-----------------------------------------------------------//函数声明//-----------------------------------------------------------void delay(unsigned char i); //延时程序//----------------------------------void Int18b20(void); //18b20初始化void Write18b20(unsigned char dat); //向18b20写一字节unsigned char Read18b20(void); //从18b20读一字节void Start18b20(void); //开始转换温度void Get18b20(void); //读出温度void chinT(void); //数据转换//----------------------------------void display(void); //显示程序//-----------------------------------------------------------//函数功能:延时//-----------------------------------------------------------/*************精确延时函数*****************/void delay(unsigned char i){while(--i);}/*此延时函数针对的是12Mhz的晶振delay(0); //延时518us 误差:518-2*256=6delay(1); //延时7us (原帖写"5us"是错的)delay(10); //延时25us 误差:25-20=5delay(20); //延时45us 误差:45-40=5delay(100); //延时205us 误差:205-200=5delay(200); //延时405us 误差:405-400=5*///-----------------------------------------------------------//DS18b20的相关程序//-----------------------------------------------------------//初始化//-----------------------------------------------------------void Int18b20(void){DQ=1;_nop_();_nop_();DQ=0; //拉低delay(100); //延时205usdelay(200); //延时405us //等待400~960微秒,最短为480us DQ=1;delay(1); //延时7usdelay(20); //延时45us //等待15~60微秒(等待回复)if(DQ==1) //判断初始化的情况是否成功{Flag=0; //复位失败}else{Flag=1;while(!DQ); //等待回复完成}delay(200); //延时405us //等待完成初始化}//-----------------------------------------------------------//写一字节//-----------------------------------------------------------void Write18b20(unsigned char dat){unsigned char i;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7us //拉低后延时小于15usif(dat&0x01){DQ=1;}else{DQ=0;}dat=dat>>1;delay(20); //延时45usdelay(10); //延时25us //延时大于60usDQ=1;delay(1); //延时7us //延时大于1us}}//-----------------------------------------------------------//读一字节//-----------------------------------------------------------unsigned char Read18b20(void){unsigned char i,dat=0;for(i=0;i<8;i++){DQ=1;_nop_();DQ=0;delay(1); //延时7usdat=dat>>1;DQ=1;delay(1); //延时7us //确保在15us后60us前读数据if(DQ){dat|=0x80;}delay(20); //延时45us //确保读时续大于60us}return dat;}//-----------------------------------------------------------//开始转换温度//-----------------------------------------------------------void Start18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0x44); //温度转换指令}//-----------------------------------------------------------//读出温度//-----------------------------------------------------------void Get18b20(void){Int18b20();Write18b20(0xcc); //跳过ROM指令Write18b20(0xbe); //读暂存器指令Templ=Read18b20();Temph=Read18b20();}//-----------------------------------------------------------//数据转换//-----------------------------------------------------------void chinT(void){float Tt;temp=Temph; //先把高八位有效数据赋于temptemp=(temp<<8); //将数据从temp低八位移到高八位temp=temp|Templ; //将两字节合成一个整型变量Tt=temp*0.0625; //得到真实十进制温度值(因为DS18B20可以精确到0.0625度) temp=Tt*10+0.5; //放大十倍(将小数点后一位变成个位,个位变成十位,十位变成百位,并四舍五入)}//-----------------------------------------------------------//显示程序//-----------------------------------------------------------void display(void){unsigned int i;unsigned char A1,A2,A3;A1=temp/100; //百位(温度的十位)A2=temp%100/10; //十位(温度的个位)A3=temp%10; //个位(温度的小数点后一位)for(i=0;i<20;i++){P0=0x00;P2=0x00;P0=number[A1];P2=wei[0];delay(220);P0=0x00;P2=0x00;P0=number[A2];P2=wei[1];delay(220);P0=0x00;P2=0x00;P0=number[A3];P2=wei[2];delay(220);P0=0x00;P2=0x00;P0=0x80;P2=wei[1];delay(220);}}//-----------------------------------------------------------//----------------------------------------------------------- void main(void){while(1){Int18b20();if(Flag){Start18b20(); //开始转换温度Get18b20(); //得到温度chinT(); //数据转换display(); //显示}else P3=0x01;}}。
基于51单片机的12864显示温度(ds18b20)
#ifndef __LCD12864_H#define __LCD12864_H//---包含头文件---//#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif//---如果使用画图模式定义这个---//#define LCD12864_PICTURE//---定义使用的IO口---//#define LCD12864_DATAPORT P1 //数据IO口sbit LCD12864_RS = P2^6; //(数据命令)寄存器选择输入sbit LCD12864_RW = P2^5; //液晶读/写控制sbit LCD12864_EN = P2^7; //液晶使能控制sbit LCD12864_PSB = P3^2; //串/并方式控制sbit LCD12864_RST = P3^4; //复位端//---声明全局函数---//void LCD12864_Delay1ms(uint c);uchar LCD12864_Busy(void);void LCD12864_WriteCmd(uchar cmd);void LCD12864_WriteData(uchar dat);void LCD12864_Init();void LCD12864_ClearScreen(void);void LCD12864_SetWindow(uchar x, uchar y);void LCD12864_DrowPic(uchar *a);void LCD12864_DrowPoint(uchar x, uchar y);#endif#ifndef __TEMP_H_#define __TEMP_H_#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif//--定义使用的IO口--//sbit DSPORT=P3^3;//--声明全局函数--//void Delay1ms(uint );uchar Ds18b20Init();void Ds18b20WriteByte(uchar com);uchar Ds18b20ReadByte();void Ds18b20ChangTemp();void Ds18b20ReadTempCom();int Ds18b20ReadTemp();#endif#include"lcd12864.h"/****************************************************************************** ** 函数名: LCD12864_Delay1ms* 函数功能: 延时1MS* 输入: c* 输出: 无******************************************************************************* /void LCD12864_Delay1ms(uint c)uchar a,b;for(; c>0; c--){for(b=199; b>0; b--){for(a=1; a>0; a--);}}}/****************************************************************************** ** 函数名: LCD12864_Busy* 函数功能: 检测LCD是否忙* 输入: 无* 输出: 1或0(1表示不忙,0表示忙)******************************************************************************* /uchar LCD12864_Busy(void){uchar i = 0;LCD12864_RS = 0; //选择命令LCD12864_RW = 1; //选择读取LCD12864_EN = 1;LCD12864_Delay1ms(1);while((LCD12864_DA TAPORT & 0x80) == 0x80) //检测读取到的值{i++;if(i > 100){LCD12864_EN = 0;return 0; //超过等待时间返回0表示失败}}LCD12864_EN = 0;return 1;}/****************************************************************************** ** 函数名: LCD12864_WriteCmd* 函数功能: 写命令* 输入: cmd* 输出: 无******************************************************************************* /void LCD12864_WriteCmd(uchar cmd){uchar i;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return; //超过等待退出}}LCD12864_RS = 0; //选择命令LCD12864_RW = 0; //选择写入LCD12864_EN = 0; //初始化使能端LCD12864_DATAPORT = cmd; //放置数据LCD12864_EN = 1; //写时序LCD12864_Delay1ms(1);LCD12864_EN = 0;}/****************************************************************************** ** 函数名: LCD12864_WriteData* 函数功能: 写数据* 输入: dat* 输出: 无******************************************************************************* /void LCD12864_WriteData(uchar dat){uchar i;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return; //超过等待退出}}LCD12864_RS = 1; //选择数据LCD12864_RW = 0; //选择写入LCD12864_EN = 0; //初始化使能端LCD12864_DATAPORT = dat; //放置数据LCD12864_EN = 1; //写时序LCD12864_Delay1ms(1);LCD12864_EN = 0;}/****************************************************************************** ** 函数名: LCD12864_ReadData* 函数功能: 读取数据* 输入: 无* 输出: 读取到的8位数据******************************************************************************* /#ifdef LCD12864_PICTUREuchar LCD12864_ReadData(void){uchar i, readValue;i = 0;while( LCD12864_Busy() == 0){LCD12864_Delay1ms(1);i++;if( i>100){return 0; //超过等待退出}}LCD12864_RS = 1; //选择命令LCD12864_RW = 1;LCD12864_EN = 0;LCD12864_Delay1ms(1); //等待LCD12864_EN = 1;LCD12864_Delay1ms(1);readValue = LCD12864_DA TAPORT;LCD12864_EN = 0;return readValue;}#endif/****************************************************************************** ** 函数名: LCD12864_Init* 函数功能: 初始化LCD12864* 输入: 无* 输出: 无******************************************************************************* /void LCD12864_Init(){LCD12864_PSB = 1; //选择并行输入LCD12864_RST = 1; //复位LCD12864_WriteCmd(0x30); //选择基本指令操作LCD12864_WriteCmd(0x0c); //显示开,关光标LCD12864_WriteCmd(0x01); //清除LCD12864的显示内容}/****************************************************************************** ** 函数名: LCD12864_ClearScreen* 函数功能: 在画图模式下,LCD12864的01H命令不能清屏,所以要自己写一* * 屏函数* 输入: 无* 输出: 无******************************************************************************* /#ifdef LCD12864_PICTUREvoid LCD12864_ClearScreen(void){uchar i,j;LCD12864_WriteCmd(0x34); //开启拓展指令集for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次{LCD12864_WriteCmd(0x80+i); //先写入纵坐标Y的值LCD12864_WriteCmd(0x80); //再写入横坐标X的值for(j=0;j<32;j++) //横坐标有16位,每位写入两个字节的的数据,也{ //就写入32次以为当写入两个字节之后横坐标会自LCD12864_WriteData(0x00); //动加1,所以就不用再次写入地址了。
18B20温度采集LCD12864显示
实用文案基于单片机STC89C51的温度显示系统的设计引言随着电子技术,特别是随大规模集成电路的产生而出现的微型计算机技术的飞速发展,人类生活发生了根本性的改变。
如果说微型计算机的出现使现代科学研究得到了质的飞跃,那么可以毫不夸张地说,单片机技术的出现则是给现代工业测控领域带来了一次新的技术革命。
目前,单片机以其体积小、重量轻、抗干扰能力强、对环境要求不高、高可靠性、高性能价格比、开发较为容易,在工业控制系统、数据采集系统、智能化仪器仪表、办公自动化等诸多领域得到极为广泛的应用,并已走人家庭,从洗衣机、微波炉到音响、汽车,到处都可见到单片机的踪影。
因此,单片机技术开发和应用水平已逐步成为一个国家工业发展水平的标志之一。
本课题研究的内容就是以单片机为主要控制元件,通过温度传感器DS18B20实现对温度的测量,并通过LCD12864直接显示所测温度。
1、设计任务用温度传感器DS18b20检测空气中的温度,STC89C51采集DS18B20的数据并通过LCD12864显示实时温度。
2、系统硬件设计2.1 系统方框图见图2-1.图3-1 系统方框图2.2 各模块方案的选择2.2.1 温度检测方案选择方案一:采用热电偶或热敏电阻作感温元件,但热电偶需冷端补偿,电路设计复杂,热敏电阻虽然精度较高,但需要标准稳定电阻匹配才能使用,而且重复性、可靠性都比较差。
方案二:采用集成温度传感器 DS18B20 。
该传感器结构简单,不需外接电路,数据传输采用one-wire。
总线,可用一根 I/O数据线即供电又传输数据,在-10 ℃ --+85℃范围内精度为±0.5℃,分辨率较高,重复性和可靠性好。
故采用方案二。
2.2.2 显示模块方案的选择方案一:采用数码管显示。
数码管亮度高、体积小、重量轻,但其显示信息简单、有限,在本题目中应用受到很大的限制。
方案二:采用液晶显示。
液晶显示功耗低,轻便防震。
采用液晶显示界面友好清晰,操作方便,显示信息丰富。
51单片机测温18b20和LCD12864程序知道
基于STC89C52单片机的18b20测温程序主程序:/***************************************************************************** 使用单片机:STC89C52晶振频率:11.0592MHZ开发环境:Keil4.0功能简述:调试用12864LCD的显示功能,蜂鸣器报警装置******************************************************************************/ #include<reg52.h>#include<intrins.h>#include<stdio.h>#include <math.h>#define uchar unsigned char#define uint unsigned int#define lcd_data P0#include "lcd.h"#include "ds18b20.h"code uchar Display1[8]={"实际温度"};code uchar Display2[8]={"报警温度"};sbit sl=P0^3;sbit sr=P0^4;sbit su=P0^5;sbit sd=P0^6;char f=0; //定义标志位sbit beep=P1^7; //蜂鸣器uint temp,templa; //定义整形温度数据float f_temp; //定义浮点型得温度数据int Actual_Temp;int Alarm_Temp;unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint z) //延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void Key_Scan() //键盘扫描程序{if(sl==0) //实现光标的左移{delay(5); //消抖if(sl==0){while(!sl); //按键松手检测等待按键释放if(f==0)f=4;else f--; // 按键自减1}}if(sr==0) //实现光标的右移{delay(5); //消抖if(sr==0){while(!sr); //按键松手检测f++;if(f==4)f=0;}}if(su==0) //实现按键加的功能{delay(5); //消抖if(su==0){while(!su); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp+100;}if(f==2){Alarm_Temp=Alarm_Temp+10;}if(f==3){Alarm_Temp=Alarm_Temp+1;}}}if(sd==0) // 实现按键减的功能{delay(5); //消抖if(sd==0){while(!sd); //按键松手检测if(f==1){Alarm_Temp=Alarm_Temp-100;}if(f==2){Alarm_Temp=Alarm_Temp-10;}if(f==3){Alarm_Temp=Alarm_Temp-1;}}}Alarm_Temp= Alarm_Temp;}void LCD_Display(int value,char x,char y){uint abs_value;code uchar Display_Dot[1]={"."};code uchar Display_Unit[1]={"C"};if(value<0){LCD_Pos(x,y-1);LCD_SendData("-",1);}else{LCD_Pos(x,y-1);LCD_SendData("+",1);}abs_value=abs(value);LCD_Pos(x,y);LCD_Write(abs_value/100+0x30,1);LCD_Write(abs_value%100/10+0x30,1);LCD_SendData(Display_Dot,1); //显示小数点LCD_Write(abs_value%10+0x30,1);LCD_SendData(Display_Unit,1); //显示单位}void LCD_DisplayTemp() ////显示实际温度与报警温度值{LCD_Display(Actual_Temp ,0,5);LCD_Display(Alarm_Temp ,1,5);switch(f){case 0:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 1:LCD_Pos(2,5);LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 2: LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符break;case 3:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(24,1); //显示向上指针LCD_Write(32,1); //显示空白字符case 4:LCD_Pos(2,5);LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示空白字符LCD_Write(32,1); //显示向上指针LCD_Write(24,1); //显示空白字符}}void DS18B20_TempChange(void) //DS18B20 开始获取温度并转换{DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc); // 写跳过读ROM指令DS18B20_WriteByte(0x44); // 写温度转换指令}void DS18B20_GetTemp() // 从DS18B20读取寄存器中存储的温度数据{uchar a,b;DS18B20_Reset();delay(1);DS18B20_WriteByte(0xcc);DS18B20_WriteByte(0xbe);a=DS18B20_Read(); //读低8位b=DS18B20_Read(); //读高8位temp=b;temp<<=8; //两个字节组合为1个字temp=temp|a;if(temp&0x80==0x80) temp=-(~temp+1); //判断实测温度的正负f_temp=temp*0.0625; //温度在寄存器中为12位分辨率位0.0625°temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入 f_temp=f_temp+0.05;Actual_Temp=temp; //temp是整型}void Beep_Warn() //蜂鸣器报警{if(Actual_Temp>Alarm_Temp)beep=0; //蜂鸣器响elsebeep=1; //蜂鸣器不响}void main(){ uint i;LCD_init(); //初始化LCDLCD_Clear(); //LCD清屏LCD_Pos(0,0); //设置显示位置为第一行的第一个字符LCD_SendData(Display1,8); //显示:实际温度LCD_Pos(1,0); //设置显示位置为第二行的第一个字符LCD_SendData(Display2,8); //显示报警温度while(1){ DS18B20_TempChange( );for(i=0;i<10;i++){Beep_Warn ();DS18B20_GetTemp();LCD_DisplayTemp(); //调用显示函数}Key_Scan(); //调用键盘函数}}//程序很棒,仅供参考,不明白处可留言。
温度传感器DS18B20测试程序
;**************************************;温度传感器DS18B20测试程序供参考;**************************************DQ BIT P3.7 ;DS18B20的数据口位P3.3 TPL DA TA 50H ;存放温度值的高字节TPH DATA 51H ;存放温度值的低字节TPPL DATA 54H ;十进制TPPH DATA 55HORG 0JMP MAINORG 100HMAIN:CALL DS18B20_Reset ;设备复位MOV A,#0CCH ;跳过ROM命令CALL DS18B20_WriteByte ;送出命令MOV A,#044H ;开始转换CALL DS18B20_WriteByte ;送出命令JNB DQ,$ ;等待转换完成CALL DS18B20_Reset ;设备复位MOV A,#0CCH ;跳过ROM命令CALL DS18B20_WriteByte ;送出命令MOV A,#0BEH ;读暂存存储器CALL DS18B20_WriteByte ;送出命令CALL DS18B20_ReadByte ;读温度低字节MOV TPL,A ;存储数据CALL DS18B20_ReadByte ;读温度高字节MOV TPH,A ;存储数据CALL HZDL0CALL DISJMP MAIN;**************************************; 驱动LED显示器的程序;**************************************PDL BIT 20HDIS: MOV DPTR,#TABDIS1: MOV R0,#TPPLMOV R2,#0FBHMOV R3,#02HCLR PDLDIS2: MOV A,@R0 ;四位扫描显示ANL A, #0FH;SW AP AMOVC A,@A+DPTRORL P3,#3CHMOV A,R2ANL P3,ARL AMOV R2, A;INC R0LCALL DAYMOV A,@R0ANL A, #0F0HSW AP AMOVC A,@A+DPTRORL P3,#3CHJB PDL,DIS3SETB PDL;ORL A, #80HDIS3: MOV P1,AMOV A,R2ANL P3,ARL AMOV R2, ALCALL DAYINC R0DJNZ R3,DIS2RETTAB: DB 03FH,06H,05BH,4FH,66H,6DH,7DH,07H ;DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H,00H,40H ;共阴极代码DAY: MOV R4,#1D1: MOV R5,#248D2: NOPNOPDJNZ R5,D2DJNZ R4,D1RET;**************************************HZDL0: MOV TPPL, #00H ; 十六进制 -> 十进制MOV TPPH, #00HMOV TPPH+1, #00HMOV TPH+1, #00HMOV R3, #04HHZDL2: CLR CMOV A, TPLRLC AMOV TPL,AMOV A, TPHMOV TPH,AMOV A, TPH+1RLC AMOV TPH+1,ADJNZ R3, HZDL2HZDL021: MOV R3, #10HHZDL022: MOV R0, #TPLMOV R2, #03HHZDL026: MOV A, @R0RLC AMOV @R0, AINC R0DJNZ R2, HZDL026MOV R0, #TPPLMOV R2, #03HHZDL028: MOV A, @R0ADDC A, @R0DA AMOV @R0, AINC R0DJNZ R2, HZDL028DJNZ R3, HZDL022RET;**************************************;延时X*10微秒;**************************************DelayX0us: ;2 当改用1T的MCU时,请调整此延时函数NOP ;1NOP ;1NOP ;1NOP ;1NOP ;1NOP ;1NOP ;1NOP ;1DJNZ R7,DelayX0us ;2RET ;2;**************************************;复位DS18B20,并检测设备是否存在;**************************************DS18B20_Reset:CLR DQ ;送出低电平复位信号MOV R7,#48 ;延时至少480usCALL DelayX0usSETB DQ ;释放数据线MOV R7,#6 ;等待60usCALL DelayX0usMOV C,DQ ;检测存在脉冲MOV R7,#42 ;等待设备释放数据线CALL DelayX0usJC DS18B20_Reset ;如果设备不存在,则继续等待RET;**************************************;从DS18B20读1字节数据;**************************************DS18B20_ReadByte:CLR APUSH 0MOV 0,#8 ;8位计数器ReadNext:CLR DQ ;开始时间片NOPNOPSETB DQ ;准备接收NOPNOPMOV C,DQ ;读取数据RRC AMOV R7,#6 ;等待时间片结束CALL DelayX0usDJNZ 0,ReadNextPOP 0RET;**************************************;向DS18B20写1字节数据;**************************************DS18B20_WriteByte:PUSH 0MOV 0,#8 ;8位计数器WriteNext:CLR DQ ;开始时间片NOPNOPRRC A ;输出数据MOV DQ,CMOV R7,#6 ;等待时间片结束CALL DelayX0usSETB DQ ;准备送出下一位数据DJNZ 0,WriteNextPOP 0RETEND。
DS18B20温度传感器和数码管显示例程
//DS18B20温度传感器和数码管显示//编程时间:连线表: CPU=stc89C52 SysClock=12MHz// LEDLE= 控制位高电平有效 LEDSEG=P2 KEYBOARD=P3 LEDWEI=,LED高到底//**********************************************************//DS18B20//**********************************************************//连线表: CPU=stc89C52 SysClock=12MHz *//单总线: TMDAT=////**********************************************************#include <>#define uchar unsigned char#define uint unsigned intuchar discount=0;//显示扫描位计数uchar last=0;//最终温度值uchar itcount=0x13;//定时器延时计数uchar seg[4];//数码管显示暂存uchar tem[2];//读取温度暂存uchar flag=0;//温度正负标志位/********************LED引脚定义********************/sfr LEDSEG=0x80;//P2sfr LEDWEI=0xA0;//P3/********************DS18B20引脚定义********************/sbit TMDAT=P1^0; //温度传感器数据位/********************DS18B20函数定义*******************/void dmsec(uint count);//延时(count)毫秒void tmreset(void); //产生复位信号void tmpre(void); //检测器件应答信号bit tmrbit(void); //从总线读一个bituchar tmrbyte(void); //从总线读一个字节void mwbyte(uchar dat);//向总线写一个字节void tmstart(void); //启动一次温度转换uchar tmrtemp(void); //读取温度数据/********************LED函数定义*******************/uchar * uchartodectoseg(uchar unm);//字符转换为十进制然后转换为数码管段表void disp(uchar *seg);//显示函数void delay_ms(uint t); //延时函数/************************************************/uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0xc6};/*************数码表*******0 1 2 3 4 5 6 7 8 9 无显示 C**************/ /************************************************/uchar * uchartodectoseg(uchar unm){uchar x00,xx,x0,x,n;x00=unm/100;//取百位xx=unm%100;//取余x0=xx/10;//取十位x=xx%10;//取余即取个位n=0;seg[n]=table[x00];n++;seg[n]=table[x0];n++;seg[n]=table[x];n++;seg[n]=table[11];//最后一位显示摄氏度符号Cif(flag==1)seg[0]=0x40;//显示负号‘-’if(seg[0]==table[0])seg[0]=table[10]; //如果百位为零则不显示if((seg[0]==table[0])&(seg[1]==table[0]))seg[1]=table[10];//如果百位为零且十位为零则十位不显示return seg;}/***************************************************/ /******DELAY***************************/void delay_ms(uint t){uint m,n;for(m=0;m<t;m++){for(n=0;n<950;n++);}}/******************************************//*********************显示LEDSEG*****************************/void disp(uchar *seg){uchar wei[]={0x08,0x04,0x02,0x01};//位扫描码//LEDSEG=seg[10];LEDWEI =wei[discount];LEDSEG = seg[discount];delay_ms(1);discount++;if(discount==4){ delay_ms(1);discount=0;//LEDSEG=seg[10];LEDWEI=wei[discount];LEDSEG=seg[discount];}//检测是否扫描完,扫描完的话则重新置初值}/*********************************************************//*****************DS18B20函数体定义****************/void dmsec(uint count) {uint i;while(count--){for(i=0;i<125;i++){} }}void tmreset(void){uint i;TMDAT=0;i=103;while(i>0) i--;TMDAT=1;i=4;while(i>0) i--;}void tmpre(void){uint i;while(TMDAT);while(~TMDAT);i=4;while(i>0) i--;}bit tmrbit(void){uint i;bit dat;TMDAT=0;i++;TMDAT=1;i++;i++;dat=TMDAT;i=8;while(i>0) i--;return(dat);}uchar tmrbyte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){ j=tmrbit();dat=(j<<7)|(dat>>1); }return(dat);}void tmwbyte(uchar dat) {uint i;uchar j;bit testb;for(j=1;j<=8;j++){ testb=dat & 0x01; dat=dat>>1;if(testb){ TMDAT=0;i++; i++;TMDAT=1;i=8;while(i>0) i--; }else{ TMDAT=0;i=8;while(i>0) i--; TMDAT=1;i++; i++;}}}void tmstart(void){tmreset();tmpre();dmsec(1);tmwbyte(0xcc);tmwbyte(0x44);}uchar tmrtemp(void){uchar y1,y2,y3;tmreset();tmpre();dmsec(1);tmwbyte(0xcc);tmwbyte(0xbe);tem[0]=tmrbyte();tem[1]=tmrbyte();if(tem[1]>127){tem[1]=(255-tem[1]);tem[0]=(255-tem[0]);flag=1;} //负温度求补码y1=tem[0]>>4;y2=tem[1]<<4;y3=y1|y2;return(y3);}/*********************************************************/void main(){TMOD=0X01;TL0=0XB0;TH0=0X3C;EA=1;ET0=1;TR0=1;dmsec(1);tmstart();while(1){uchartodectoseg(last);disp(seg);}}void time0() interrupt 1{TL0=0XB0;TH0=0X3C;//定时50msitcount--;if(itcount==0){last=tmrtemp();dmsec(1);tmstart();itcount=0x13;}}。
数字温度传感器DS18B20(含程序)
数字温度传感器DS18B20摘要DS-18B20 数字温度传感器具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
应用范围广泛,适用于冷冻库,粮仓,储罐,电讯机房,电力机房,电缆线槽等测温和控制领域,轴瓦,缸体,纺机,空调,等狭小空间工业设备测温和控制和汽车空调、冰箱、冷柜、以及中低温干燥箱等。
一、引脚图DS18B20引脚定义:(1)DQ为数字信号输入/输出端;(2)GND为电源地;(3)VDD为外接供电电源输入端(在寄生电源接线方式时接地)二、DS18B20的主要特性1.1、电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电1.2、DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯1.3、多个DS18B20可以并联在唯一的三线上,实现组网多点测温1.4、DS18B20在使用中不需要任何外围元件1.5、温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃1.6、可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温1.7、在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快1.8、测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力1.9、负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
三、DS18B20的外形和内部结构DS18B20内部结构主要由四部分组成:64位光刻ROM 、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20内部结构图四、DS18B20工作原理DS18B20的温度转换时的延时时间由2s 减为750ms。
DS18B20测温原理如图3所示。
DS18B20的读写程序
DS18B20的读写程序以下是我为宾馆智能控制器所做的温度探测器DS18B20的一个程序。
在网上看到很多朋友想要DS18B20的读写程序却苦于找不到这样的程序,我把它贡献出来和大家分享。
这个程序取到的温度值范围为0-70(一般应用足够了),如需大于此温度值可自行在TAB中添加。
测温精度为0.5度,没有加校正,需要的朋友可自行查一些资料。
; FLAG1: 标志位,为"1"时表示检测到DS18B20; DQ: DS18B20的数据总线接脚; TEMPER_NUM:保存读出的温度数据; 本程序仅适合单个DS18B20和51单片机的连接,晶振为12MHZ左右TEMPER_L EQU 36HTEMPER_H EQU 35HDQ BIT P1.7; DS18B20初始化程序;//*****************************************//INIT_1820:SETB DQNOPCLR DQMOV R0,#06BHTSR1:DJNZ R0,TSR1 ; 延时SETB DQMOV R0,#25HTSR2:JNB DQ,TSR3DJNZ R0,TSR2LJMP TSR4 ; 延时TSR3:SETB FLAG1 ; 置标志位,表示DS1820存在LJMP TSR5TSR4:CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP TSR7TSR5:MOV R0,#06BHTSR6:DJNZ R0,TSR6 ; 延时TSR7:SETB DQRET;//*****************************************//; 重新写DS18B20暂存存储器设定值;//*****************************************//RE_CONFIG:JB FLAG1,RE_CONFIG1 ; 若DS18B20存在,转RE_CONFIG1 RETRE_CONFIG1:MOV A,#0CCH ; 发SKIP ROM命令LCALL WRITE_1820MOV A,#4EH ; 发写暂存存储器命令LCALL WRITE_1820MOV A,#00H ; TH(报警上限)中写入00HLCALL WRITE_1820MOV A,#00H ; TL(报警下限)中写入00HLCALL WRITE_1820MOV A,#1FH ; 选择9位温度分辨率LCALL WRITE_1820RET;//*****************************************//; 读出转换后的温度值;//*****************************************//GET_TEMPER:SETB DQ ; 定时入口LCALL INIT_1820JB FLAG1,TSS2RET ; 若DS18B20不存在则返回TSS2:MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820LCALL INIT_1820MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_1820MOV TEMPER_NUM,A ; 将读出的温度数据保存;//*****************************************//; 读DS18B20的程序,从DS18B20中读出一个字节的数据;//*****************************************// READ_1820:MOV R2,#8RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE1RET;//*****************************************//; 写DS18B20的程序;//*****************************************// WRITE_1820:MOV R2,#8CLR CWR1:CLR DQMOV R3,#6DJNZ R3,$RRC AMOV DQ,CMOV R3,#23DJNZ R3,$SETB DQNOPDJNZ R2,WR1SETB DQ;//*****************************************//; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据;//*****************************************//READ_18200:MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_H) RE00:MOV R2,#8RE01:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;//*****************************************//; 将从DS18B20中读出的温度数据进行转换;//*****************************************//TEMPER_COV:MOV A,#0F0HANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值SW AP AMOV TEMPER_NUM,AMOV A,TEMPER_LJNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值INC TEMPER_NUMTEMPER_COV1:MOV A,TEMPER_HANL A,#07HSW AP AORL A,TEMPER_NUMMOV TEMPER_NUM,A ; 保存变换后的温度数据LCALL BIN_BCDRET;//*****************************************//; 将16进制的温度数据转换成压缩BCD码;//*****************************************//BIN_BCD:MOV DPTR,#TEMP_TABMOV A,TEMPER_NUMMOVC A,@A+DPTRMOV TEMPER_NUM,ARETTEMP_TAB:DB 00H,01H,02H,03H,04H,05H,06H,07HDB 08H,09H,10H,11H,12H,13H,14H,15HDB 16H,17H,18H,19H,20H,21H,22H,23HDB 24H,25H,26H,27H,28H,29H,30H,31HDB 32H,33H,34H,35H,36H,37H,38H,39HDB 40H,41H,42H,43H,44H,45H,46H,47HDB 48H,49H,50H,51H,52H,53H,54H,55HDB 56H,57H,58H,59H,60H,61H,62H,63HDB 64H,65H,66H,67H,68H,69H,70H;//*****************************************//函数TEMPER_COV中的Bug所在:四舍五入进行得太早!当读入的温度是31.5度时,TEMPER_L中的数值为11111XXXTEMPER_H中的数值为00000001,按你的程序,在四舍五入完成时(INC TEMPER_NUM),TEMPER_NUM中为00010000,在后面和TEMPER_H中数据相或时,这个进位的1就给忽略了,造成转换结果是16度。
基于DS18B20温度显示仪--------程序
基于DS18B20温度显示仪--------程序#include <reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar BCD_7[12] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00} ; sbit DS18B20=P2^0 ;void saomiao( uint k );void Delay_ms(uchar t){uint i;for(;t>0;t--)for(i=0;i<124;i++);}uint d[4];uchar temp;void delay500us(unsigned int t){ unsigned int i;for(;t>0;t--)for(i=0;i<59;i++);}//--------------------------------------------------------------------------------void delay60us(void){ unsigned char i;for(i=0;i<18;i++);}//---------------------------------------------------------------------------------unsigned char Ds18b20_start () //返回0,总线上DS18B20{ unsigned char flag; //定义初始化成功或失败标志DS18B20=0; //总线产生下降沿,初始化开始delay500us(1); //总线保持低电平在480 - 960微秒之间DS18B20=1; //总线拉高,准备接收DS18B20的应答脉冲delay60us (); //读应答等待_nop_();_nop_();flag= DS18B20;while(!DS18B20);//等待复位成功return(flag);}//---------------------------------------------------------------------------------void ds18_send(unsigned char i) //向DS18B20写一字节函数{ unsigned char j=8; //设置读取的位数,一字节8位for(;j>0;j--){DS18B20=0; //总线拉低,启动"写时间片"_nop_();_nop_(); //大于1微妙if(i&0x01)DS18B20=1;delay60us (); //延时至少60微秒,使写入有效_nop_();_nop_();DS18B20=1; //准备启动下一个"写时间片"i>>=1;}}//---------------------------------------------------------------------------------unsigned char ds18_readChar() //从DS18B20读1个字节函数{unsigned char i=0,j=8;for(;j>0;j--){DS18B20=0; //总线拉低,启动读"时间片"_nop_();_nop_(); //大于1微妙DS18B20=1; //总线拉高,准备读取i>>=1;if(DS18B20)i|=0x80; //从总线拉低时算起,约15微秒后读取总线数据delay60us (); //延时至少60微秒_nop_();_nop_();}return(i);}//--------------------------------------------------------------------------------void Init_Ds18B20(void) //初始化DS18B20{if(Ds18b20_start()==0) //复位{ ds18_send (0xcc); //跳过ROM匹配ds18_send (0x4e); //设置写模式ds18_send (0x64); //设置温度上限100摄氏度ds18_send (0x8a); //设置温度下线-10摄氏度ds18_send (0x7f); //12bit(默认)}}//---------------------------------------------------------------------------------unsigned int Read_ds18b20(){unsigned char th,tl;if(Ds18b20_start ()) // Ds18b20_start ()为初始化函数return(0); //初始化失败,DS18B20出故障,返回ds18_send(0xcc); //发跳过序列号检测命令ds18_send(0x44); //发启动温度转换命令delay500us (5); //延时200ms等待转换完成。
DS18B20温度显示程序
DS18B20传感器温度数码管显示#include<reg51.h>#include<1820twj.h> //传感器DS18B20#include<intrins.h> //字符操作库sbit g1=P2^7;sbit g2=P2^6;sbit g3=P2^5;sbit g4=P2^4;sbit lv=P2^2;sbit jin=P3^3; //进sbit jia=P3^4; //加sbit jian=P3^5; //减uint shiwen;uint zuigao=30; //最高30度uint zuidi=20; //最低20度//*键盘调节/uchar flag=0; //记录第一个按键次数flag=0正常1最高2最低uchar flag2=0; //记录第四个按键次数flag2=0正常1调节小时2调节分钟uchar tableshu[]={0x28,0xeb,0x32,0xa2,0xe1,0xa4,0x24,0xea,0x20,0xe0,0xff ,0xf7 }; uchar tableshudi[]={0x08,0xcb,0x12,0x82,0xc1,0x84,0x04,0xca,0x00,0xc0,0xff };void main(){uchar TL; //储存暂存器的温度低位uchar TH; //储存暂存器的温度高位uint TN; //储存温度的整数部分uchar TD; //储存温度的小数部分uchar ba,sh,ge,di,ba1,sh1,ge1,di1;bit flag1; //判断显示正负0负1正delay1(5); //延时5ms给硬件一点反应时间while(1) //不断检测并显示温度{ init();//读温度准备if(flag1==1) dis(ba,sh,ge,di);else dis(11,sh,ge,di);TL=ReadOneChar(); //先读的是温度值低位TH=ReadOneChar(); //接着读的是温度值高位if((TH&0xf8)!=0x00)//判断高五位得到温度是负{ flag1=0; TL=~TL; //取反TH=~TH; //取反TL=TL+1; //低位加1TN=(TH*256+TL)*0.625; //实际温度值10倍=(TH*256+TL)*0.625,if(TN%160==0) TN=TN+160;sh=TN/100%10; ge=TN/10%10; di=TN%10;dis(ba,sh,ge,di); //显示温度}else//判断高五位得到温度是正{ flag1=1;TN=(TH*256+TL)*0.625; //实际温度值10倍=(TH*256+TL)*0.625, //这样前几位是温度的整数部分,最后一位是温度的小数部分ba=TN/1000; sh=TN/100%10; ge=TN/10%10; di=TN%10;dis(ba,sh,ge,di); //显示温度的整数部分}shiwen=TN; biaozhun(); tfz();if(flag1==1)dis(ba,sh,ge,di);else dis(11,sh,ge,di);kongzhi()//温度调整驱动程序}void kongzhi(){if((shiwen<zuigao)&&(shiwen>zuidi))lv=0; //控制P2口输出电平elselv=1;}void dis(uchar ba,uchar sh,uchar ge,uchar di){ g1=0;P0=tableshu[ba];delay1(5);g1=1;P0=tableshu[10];g2=0;P0=tableshu[sh];delay1(5);g2=1;P0=tableshu[10];g3=0;P0=tableshudi[ge];delay1(5);g3=1;P0=tableshudi[10];g4=0;P0=tableshu[di];delay1(5);g4=1;P0=tableshu[10];}void disdi(uchar ba,uchar sh,uchar ge,uchar di){ g1=0;P0=tableshudi[ba];delay1(5); g1=1;P0=tableshu[10]; g2=0;P0=tableshudi[sh];delay1(5); g2=1;P0=tableshu[10]; g3=0;P0=tableshudi[ge];delay1(5); g3=1;P0=tableshudi[10]; g4=0;P0=tableshudi[di];delay1(5); g4=1;P0=tableshu[10];}void biaozhun(){ if(jin==0){ delay1(5);if(jin==0){ while(!jin);flag++; if(flag==3) flag=0;} } } /*调幅值*/void tfz(){ uchar ba,sh,ge,di; if(flag==1){ while(1){ ba=zuigao/1000; sh=zuigao/100%10; ge=zuigao/10%10; di=zuigao%10; dis(ba,sh,ge,di); if(jia==0) delay1(5);if(jia==0) { zuigao=zuigao+10;while(!jia); dis(ba,sh,ge,di); }if(jian==0){ zuigao=zuigao-10;while(!jian);dis(11,sh,ge,di); }biaozhun();if(flag!=1) break; } }if(flag==2){ while(1){ ba=zuidi/1000; sh=zuidi/100%10; ge=zuidi/10%10; di=zuidi%10;dis(ba,sh,ge,di);if(jia==0) delay1(5);if(jia==0){ zuidi=zuidi+10; while(!jia); }if(jian==0) { zuidi=zuidi-10; while(!jian); }biaozhun();if(flag!=2)break;}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*由于DS18B20对延时的要求很高,所以要根据采用的晶振来确定延迟时间,以下程序待对时间都有明确标注,根据你选用的晶振来调节即可*/
#include <reg52.h> //
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD_data P0 //显示屏输出数据口
/*液晶控制端口*/
sbit LCD_RST = P1^4; //液晶复位端口
sbit LCD_RS = P1^5; //寄存器选择输入
sbit LCD_RW = P1^6; //液晶读/写控制
sbit LCD_EN = P1^7; //液晶使能控制
sbit DQ=P1^0;
uint a,b,i;
uchar str[16]={"--温度:000.0 M--"}; //定义数组
uchar k,m;
float temp;
//延时子函数1
void delay5us(uchar z)
{uchar i;
for(i=0;i<z;i++);
}
void delayNOP()
{_nop_();_nop_();_nop_();_nop_();}
void delay(uint z) //延时子函数1 ms
{
uint x,y;
for(x=z;x>0;x--)
for(y=200;y>0;y--);
}
bit lcd_busy() //检测液晶忙碌?
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return (result);
}
void lcd_wcmd(uchar cmd) //液晶屏写指令{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_wdat(uchar dat) //写数据
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
void lcd_init() //液晶初始化{
LCD_RST = 0; //液晶复位
delay(3);
LCD_RST = 1;
delay(3);
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //显示开,关光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容delay(5);
}
uchar ds18_init()
{
uchar i;
DQ = 0;//总线拉低
delay5us(100);//500us
DQ = 1;//总线拉高
delay5us(20);//延时100us
i=DQ;
delay5us(100);//500us
return i;
}
void write_18(uchar value)
{
uchar i,v1=0;
v1 = value;
for (i =0 ;i<8;i++)
{
DQ = 0;//总线拉低
delay5us(2);//延时10us
if(v1&0x01)
DQ = 1;
delay5us(20);//延时100us
DQ = 1;
v1=v1>>1;
}
}
uchar read_18()
{
uchar i,v2 = 0;
for (i=0;i<8;i++)
{
v2=v2>>1;
DQ = 0;
delay5us(2);//延时10us
DQ = 1;
if(DQ)
v2|=0x80;
delay5us(10);//延时50us
}
return v2;
}
void shujuhuansuan() //测温公式
{
temp = (m*256+k)*0.625;
str[8] = (uint)(temp)/100;
str[9] = (uint)(temp)%100/10;
str[11] = (uint)(temp)%10;
}
void LCD_xs() //如何在显示屏上显示计算的温度:采用写字符的形式{ uchar s;
lcd_wcmd(0x80);
for(s = 0;s < 8;s++)
{
lcd_wdat(str[s]);
}
for(s = 8;s < 10;s++)
lcd_wdat(0x30 + str[s]);
lcd_wdat(str[10]);
lcd_wdat(0x30 + str[11]);
for(s = 12;s < 16;s++)
lcd_wdat(str[s]);
}
void main()
{
delay(100); //上电,等待显示屏稳定
lcd_init(); //初始化LCD
while(1)
{
while(ds18_init()); //当DQ为高电平时,说明存在ROM 继续执行,若不存在就一直在此等
write_18(0xcc);
write_18(0x44);
delay(1000);
while(ds18_init());
write_18(0xcc);
write_18(0xbe);
k= read_18();
m=read_18();
shujuhuansuan();
delay(10);
LCD_xs();
delay(1000);
}
}。