单片机 ds18b20温度测量 proteus仿真

合集下载

ds18b20 C程序proteus仿真

ds18b20 C程序proteus仿真

DS18B20测温显示,proteus仿真。

Written by jinsongliang具体程序如下Main、c:#include<reg51、h>#include"lib51v3、c"#include"18b20、c"#include"segv3、c"void main (void){unsigned char disp[5]={10,0,0,14,2};signed char temp=0;while(1){/*1、读取温度值*/temp=Get_Temputer();//2、显示前处理*/if(temp<0){disp[0]=13;temp=-temp;disp[1]=temp/10;disp[2]=temp%10;}else{disp[0]=temp/100;disp[1]=temp/10-disp[0]*10;disp[2]=temp%10;if(!disp[0]) //百位数不为0则显示,若要显示0,可将其注释掉disp[0]=10;}//3、显示*/Seg_Display(disp);}}Lib51v3、cvoid Delay_Nus (unsigned char n) {while(n--);//for (;n>0;n--);}18b20、c:/****************************************************************** 时序很重要,移植时注意延时函数******************************************************************/#define B20_PORT P1 //此处可以设置I/O口#define B20_CHANNEL 0#define R_B20_CHANNEL() B20_PORT&(1<<B20_CHANNEL)#define W_B20_CHANNEL_1() B20_PORT|=(1<<B20_CHANNEL)#define W_B20_CHANNEL_0() B20_PORT&=~(1<<B20_CHANNEL)#define SKIP_ROM 0xCC#define TEMPUTER_CONVERT 0x44#define READ_ROM 0xBE//one/*初始化函数,失败会返回1,初始化过程见注释若单片机读到了数据线上的低电平“0”后,还要做延时,其延时的时间从单片机发出的高电平算起最少要480微秒。

以51单片机为核心的DS18B20的数码管显示温度程序Proteus仿真

以51单片机为核心的DS18B20的数码管显示温度程序Proteus仿真

<TEXr>严********************************************************************文件名:温度采集DS1SB20.C*描述 :该文件实现了用温度传感器件DS18B2O 对温度的采集,并在数码管上显示出 来。

*创建人:谢宜腾,2011年4月6 口 *版本号:1.0***********************************************************************/ /*#iiiclude <reg52.h> #inc lude <intrins.h> #define uchai unsigned char #define umt unsigned mt #define jump_ROM OxCC #define start 0x44 #define read_EEROM OxBE unsigned char TMPHHMPL;uchai code table[10] = {0x3f 、0x06・0x5b 、0x4f,0x66,0x6d,0x7d,0x07,0x7f 、0x6f}; sbit DQ = P2A 3; //OS 18B20 数据口sbit P30=P3A0; sbit P31=P3A 1;*/ /riiic lude<reg52.h> ^include <intriiis.h> #define uchar unsigned char #define uiiit unsisned intsbit DATA = P2A3; /.DS18B20 接入 I 丨uchai codevTExT-I |S-:X1> .・一 一Ml昭TT.I 「勺.丄卫; -- 丄閔:ia<AC4 4P !Of. 士土丄土一f y i XTAL2KUUIAUU P0.VAD1 P02^AD2 P03AD3 RSIPO 4JAD4 POS 认 D5 POS^ADB P0.7/AD7 P2.0/A8 P2.1/ASP22ZA1O PSHMP2 3/A11 ALE P2QM2P2.WM3 cAP26/A14 P1.0/T2 P1.1/T2EXPl.2P2 7/A1S P3.0.RBD P3.1HXD卜y iiPI .3IT Pi .4 PI .5 P3.4/T0 P35/T1 Pl .6P3.6A/<Jr?PI .7 P3.7W"U1189lfi 30 3? 3321丄1314 运至35迫_7i12 ■ ■ ■ .■*f U2DS1333J <TEXT>GND • •table[]={0x3f0x06,0x5b,0x4f,0x66.0x6d.0x7d.0x07.0x7f,0x6f,0x77.0x7c.0x39.0x5e.0x790x71}; char5bai,shi,ge; 〃定义变量/*延时子函数*/void delay(uint num){while(num-);}Iiut.DS 18B20(void) 〃传感器初始化{uchar x=0;DATA= 1; //DQ 复位delay(lO); 〃稍做延时DATA= 0; 〃单片机将DQ拉低delay(80); //精确延时人于480us //450DATA=1; 〃拉高总线delay(20);x=DATA; 〃稍做延时后如果x=0则初始化成功x=l则初始化失败delay(30);}〃读一个字节ReadOneChai(void){uchar 1=0;uchar dat = 0;for (i=8;i>0;i~){DATA = 0; //给脉冲信号dat»=l;DATA=1;//给脉冲信号if(DATA)dat|=0x80; delav(8);}retuin(dat);}〃写一个字节WnteOneChai(unsigned chai dat) uchar 1=0; for (i=8; i>0; i—)DATA=O;DATA= dat&OxOl; delay(lO);DATA= 1;dat»=l;} delay(8);}〃读取温度mt ReadTemperature(void)uchar a=0;uchar b=0;mt t=0;float tt=O;Ink_DS18E20();WnteOneCliai-(OxCC); U跳过读序号列号的操作WnteOneCliai(Ox44); 〃启动温度转换Iiut_DS18B20();WnteOneCliai-(OxCC); 〃跳过读序号列号的操作WiiteOneCliaf(OxBE); 〃读取温度寄存器等(共可读9个寄存器)前两个就是温度a=ReadOneChai();// 低位b=ReadOneChai();//高位t=b;t«=8;t=t|a;tt=t*0.0625;t= tt*10+0.5;retuin(t);}/*显示子函数*/void display(int bai,int shi,mt ge)PO=table[bai];〃显示T•位delay(5O);//—小段延时动态显示P3=table[slu];〃显示百位delay(5O);void maiiiQint temp;while(l){temp=ReadTemperature();// 读温度bai=temp% 1000/100;// 显示百位slii=temp% 100/10;//显示十位ge=temp% 10;//显示个位display(bai,shi,ge);// 显示函数}}。

protues仿真DS18B20温度显示

protues仿真DS18B20温度显示
DQ=dat&0x01; //利用与运算取出要写的某位二进制数据,
//并将其送到数据线上等待DS18B20采样
for(time_DS18B20=0;time_DS18B20<10;time_DS18B20++)
;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1; //释放数据线
{
bit flag_DS18B20; //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在
DQ = 1; //先将数据线拉高
for(time_DS18B20=0;time_DS18B20<2;time_DS18B20++) //略微延时约6微秒
;
DQ = 0; //再将数据线从高拉低,要求保持480~960us
{
jdq=1;
}
else
{
jdq=0;
}
}
}
P3=0x04;
}
else
{
P3=0x10;
}
delaynms(1);
P3=0;
flag=0;
}
delaynms(25);//延时一段时间
}
void main(void)
{
while(1) //不断检测并显示温度
{
ReadyReadTemp(); //读温度准备
display();
if((temp<25)||(temp>35))//如果温度超出范围继电器工作控制温度
电路图
仿真图
温控范围25到35度之间
源程序
#include<reg51.h> //包含单片机寄存器的头文件

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图).docx

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图).docx

TEMP_ZH EQU 24H ; 实测温度值存放单元TEMPL EQU 25HTEMPH EQU 26H高温报警值存放单元TEMP_TH EQU 27H ;低温报警值存放单元TEMP_TL EQU 28H ;正、负温度值标记TEMPHC EQU 29H ;TEMPLC EQU 2AHTEMPFC EQU 2BHK1 EQU P1.4 ; 查询按键K2 EQU P1.5 ; 设置/ 调整键调整键K3 EQU P1.6 ;K4 EQU P1.7 ; 确定键BEEP EQU P3.7 ; 蜂鸣器RELAY EQU P1.3 ; 指示灯LCD_X EQU FH ;LCD 字符显示位置寄存器选择信号LCD_RS EQU P2.0 ;LCD读写信号LCD_RW EQU P2.1 ;LCD允许信号LCD_EN EQU P2.2 ;LCD是否存在标志FLAG1 EQU 20H.0 ;DS18B20KEY_UD EQU 20H.1 5 设定按键的增、减标志DQ EQU P3.3 ;DS18B20 数据信号ORG 0000HLJMP MAINORG 0030H MAIN: MOV SP,#60HMOV A,#00HMOV R0,#20HMOV R1,#10HCLEAR: MOV @R0,AINC R0DJNZ R1,CLEARLCALL SET_LCDLCALL RE_18B20 START: LCALL RSTJNB FLAG1,START1LCALL MENU_OK 信息子程序MOV TEMP_TH,#055HMOV TEMP_TL,#019HLCALL RE_18B20ALCALL WRITE_E2 ;LCALL TEMP_BJ ;JMP START2;将20H~2FH单元清零;调用18B20复位子程序;DS 1 820不存在;DS1820 存在,调用显示正确;设置TH初值85度;设置TL初值25度; 调用暂存器操作子程序写入DS18B20显示温度标记LCALL TEMP_BJSJMP $START2: LCALL RSTJNB FLAG1,START1 MOV A,#0CCH LCALL WRITE MOV A,#44H LCALL WRITE LCALL RST MOV A,#0CCH LCALL WRITE MOV A,#0BEH LCALL WRITE LCALL READ 子程序LCALL CONVTEMP 程序LCALL DISPBCD LCALL CONV LCALLTEMP_COMP 值比较子程序显示温度标记;调用DS18B2(复位子程序QS18B20不存在;跳过RoM E配命令; 温度转换命令START1: LCALL MENU_ERROR ; 调用显示出错信息子程序;跳过ROM E配; 读温度命令;调用DS18B20数据读取操作;调用温度数据BCD码处理子; 调用温度数据显示子程序;调用LCD显示处理子程序; 调用实测温度值与设定温度调用键扫描子程序 ;循环 键扫描子PROC_KEY:JB K1,PROC_K1LCALL BEEP_BL JNB K1,$MOV DPTR,#M_ALAX1 MOV A,#1LCALL LCD_PRINT LCALL LOOK_ALARM JB K3,$LCALL BEEP_BL JMP PROC_K2PROC_K1: JB K2,PROC_ENDLCALL BEEP_BL JNB K2,$MOV DPTR,#RST_A1 MOV A,#1LCALL LCD_PRINT LCALL SET_ALARMLCALL RE_18B20 将设定的 TH,TL 值写入LCALL PROC_KEYSJMP START2・ ***************************5*****************************程序DS18B20LCALL WRITE_E2PROC_K2: LCALL MENU_OKLCALL TEMP_BJPROC_END:RET・ *************************** 设定温度报警值TH、TL ***************************SET_ALARM:LCALL LOOK_ALARMAS0: JB K1,AS00LCALL BEEP_BLJNB K1,$CPL 20H.1 ;UP/DOWN 标记AS00: JB 20H.1,ASZ01 ;20H.1=1 ,增加JMP ASJ01 ;20H.1=0 ,减小ASZ01: JB K2,ASZ02 ;TH 值调整(增加)LCALL BEEP_BLINC TEMP_THMOV A,TEMP_THCJNE A,#120,ASZ011MOV TEMP_TH,#0ASZ011: LCALL LOOK_ALARMMOV R5,#10 LCALL DELAY JMP ASZ01ASZ02: JB K3,ASZ03LCALL BEEP_BLINC TEMP_TLMOV A,TEMP_TLCJNE A,#99,ASZ021MOV TEMP_TL,#00H ASZ021: LCALL LOOK_ALARM MOV R5,#10LCALL DELAYJMP ASZ02ASZ03: JB K4,AS0LCALL BEEP_BLJNB K4,$RETASJ01: JB K2,ASJ02LCALL BEEP_BLDEC TEMP_THMOV A,TEMP_THCJNE A,#0FFH,ASJ011 ;TL 值调整(增加); 确定调整;TH 值调整(减少)JMP ASJ022ASJ011: LCALL LOOK_ALARMMOV R5,#10LCALL DELAYJMP AS0ASJ02: JB K3,ASJ03 ;TL 值调整(减少)LCALL BEEP_BLDEC TEMP_TLMOV A,TEMP_TLCJNE A,#0FFH,ASJ021JMP ASJ022ASJ021: LCALL LOOK_ALARM ;MOV R5,#10LCALL DELAYJMP AS0ASJ022: CPL 20H.1JMP ASZ01ASJ03: JMP ASZ03RETRST_A1: DB " SET ALERT CODE " ,0・ *********************** 实测温度值与设定温度值比较子程序**********************TEMP_COMP:MOV A,TEMP_TH SUBB A,TEMP_ZH JCCHULI1MOV A,TEMPFCCJNE A,#0BH,COMP SJMPCHULI2COMP: MOV A,TEMP_ZHSUBB A,TEMP_TL ; JCCHULI2 ;MOV DPTR,#BJ5 LCALLTEMP_BJ3 CLR RELAYRETCHULI1: MOV DPTR,#BJ3 LCALL TEMP_BJ3 SETB RELAY ;LCALL BEEP_BL RET CHULI2: MOV DPTR,#BJ4 LCALL TEMP_BJ3SETB RELAY; 减数>被减数,则;借位标志位C=I,转减数>被减数,则借位标志位C=I ,转; 点亮指示灯熄灭指示灯; 蜂鸣器响熄灭指示灯LCALL BEEP_BL ; 蜂鸣器响RETTEMP_BJ3: MOV A,#0CEHLCALL WCOMMOV R1,#0MOV R0,#2BBJJ3: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ3RETBJ3: DB ">H"BJ4: DB "<L"BJ5: DB " !"・ **************************** 显示温度标记子程序***************************TEMP_BJ: MOV A,#0CBHLCALL WCOMMOV DPTR,#BJ1 ; 指针指到显示消息MOV R1,#0MOV R0,#2BBJJ1: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ1RETBJ1: DB 00H,"C"・ ********************************5***************************MENU_OK: MOV DPTR,#M_O MOV A,#1 ;LCALL LCD_PRINT MOVDPTR,#M_OK2 MOVA,#2 ;LCALL LCD_PRINTRETM_OK1: DB " DS18B20 OK显示正确信息子程序; 指针指到显示消息显示在第一行; 指针指到显示消息显示在第一行",0M_OK2: DB " TEMP: ",0・ ******************************** 显示出错信息子程序***************************MENU_ERROR:MoV DPTR,#M_ERROR针指到显示消息MOV A,#1 ; 显示在第一行LCALL LCD_PRINTMoV DPTR,#M_ERRoR2 ; 指针指到显示消息1MoV A,#2 ; 显示在第一行LCALL LCD_PRINTRETM_ERRoR1: DB " DS18B20 ERRoR ",0M_ERRoR2: DB " TEMP: ------ ",0;**************************** DS18B20 复位子程序*****************************RST: SETB DQNoPCLR DQMoV R0,#6BH ; 主机发出延时复位低脉冲MoV R1,#04HTSR1: DJNZ R0,$MoV R0,#6BHDJNZ R1,TSR1SETB DQ ; 拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3DJNZ R0,TSR2JMP TSR4 ;TSR3: SETB FLAG1JMP TSR5TSR4: CLR FLAG1JMP TSR7TSR5: MOV R0,#06BH TSR6: DJNZ R0,$ TSR7: SETB DQRET・ ************************ 5***************************RE_18B20:JB FLAG1,RE_18B20A RET延时置1标志位,表示DS1820存在清0标志位,表示DS1820不存在时序要求延时一段时间RE_18B20A:;等待DS18B20回应DS18B20 暂存器操作子程序LCALL RSTMOV A,#0CCH LCALL WRITE WR_SCRAPD:MOV A,#4EH LCALL WRITE MOV A,TEMP_TH LCALL WRITE MOV A,TEMP_TL LCALL WRITE MOV A,#7FH LCALL WRITERET;跳过RoME 配; 写暂器;TH ( 报警上限);TL ( 报警下限);12 位精度复制暂存器子程序;跳过ROM E 配; 把暂存器里的温度报警值拷贝到 LCALL WRITE・ ************************5*******************************WRITE_E2:LCALL RSTMoV A,#0CCH LCALL WRITE MoV A,#48H EERoM********************************READ_E2:LCALL RSTMOV A,#0CCH LCALL WRITE MOV A,#0B8H暂存器LCALL WRITE RET ;跳过RoM E 配;把EEROMl 的温度报警值拷贝回*********************STORE_DATA:MOV A,#40H LCALL WCOM MOV R2,#08H MOV DPTR,#D_DATA MOV R3,#00H S_DATA: MOV A,R3MOVC A,@A+DPTRRET・ ***********************重 读 EEROM 子 程 序・ ************************将自定义字符写入 LCD 的CGRAM 中INC R3DJNZ R2,S_DATA RETD_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00HDS18B20 数 据 写 入 操 作 子 程 序************************CLR CWR1: CLR DQ;开始写入DS18B20总线要处于复位(低)状态MOV R3,#07DJNZ R3,$ 总线复位保持 1 6微妙以上 RRC A把一个字节DATA 分成8个BlT环移给 CMOV DQ,C ; 写入一位MOV R3,#3CH DJNZ R3,$ 等待 100 微妙SETB DQ ; 重新释放总线NOPDJNZ R2,WR1 写入下一位SETB DQLCALL WDATA; 写入数据・ ***********************WRITE: MOV R2,#8一共 8 位数据RET・ ********************** DS18B20 数据读取操作子程序**************************READ: MOV R4,#4DS18B2冲读出MOV R1,#TEMPL 元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#09DJNZ R3,$MOV C,DQ; 将温度低位、高位、TH、TL 从; 存入25H、26H、27H、28H 单; 读前总线保持为低; 开始读总线释放; 延时18 微妙;从DS18B2(总线读得一位DJNZ R3,$ ; 等待 100 微妙RRC A ; 把读得的位值环移给 A DJNZ R2,RE01; 读下一位MOV @R1,AINC R1DJNZ R4,RE00RET*************************CONVTEMP: MOV A,TEMPHANL A,#08H JZ TEMPC1 ; CLR CMOV A,TEMPL ; CPL A ; ADD A,#01H MOV TEMPL,A MOV A,TEMPH CPL A ADDC A,#00H MOV TEMPH,A・ ************************温 度 值 BCD 码 处 理 子 程 序判温度是否零下温度零上转二进制数求补(双字节) 取反加 1MOV TEMPHC,#0BH ; 负温度标志MOV TEMPFC,#0BHSJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ; 正温度标志MOV TEMPFC,#0AHTEMPC11: MOV A,TEMPHCSWAP AMOV TEMPHC,AMOV A,TEMPLANL A,#0FH ; 乘0.0625MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分BCD整数部分MOV A,TEMPL ;取出高四位ANL A,#0F0H ;SWAP AMOV TEMPL,A取出低四位MOV A,TEMPH ;ANL A,#0FHSWAP AORL A,TEMPL ; 重新组合ORL A,TEMPLC MOV TEMPLC,A MOV A,R4 JZ TEMPC12 ANL A,#0FH SWAP A MOV R4,A MOV A,TEMPHC;TEMPHC HI = 百位数BCDANL A,#0FHBCDBCDMOV TEMP_ZH,A LCALL HEX2BCD1 MOV TEMPL,A ANL A,#0F0H SWAP AORL A,TEMPHC ;TEMPHCMOV TEMPHC,A MOV A,TEMPL ANL A,#0FH SWAP A;TEMPLC HI =LOW= 十位数个位数ORL A,R4MOV TEMPHC,ATEMPC12: RET・ ************************ 二-十进制转换子程序*****************************HEX2BCD1: MOV B,#064HDIV ABMOV R4,AMOV A,#0AHXCH A,BDIV ABSWAP AORL A,BRETTEMPDOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H ; 小数部分码表DB 05H,05H,06H,06H,07H,08H,08H,09H・ ********************** 查询温度报警值子程序***************************LOOK_ALARM: MOV DPTR,#M_ALAX2 指; 针指到显示信息区M_ALAX1: DB " LOOK ALERT CODE",0 M_ALAX2: DB "TH: TL: ",0 TEMP_BJ1: LCALL WCOMMOV DPTR,#BJ2 ; 指针指到显示信息区MOV R1,#0 MOV R0,#2 BBJJ2: MOV A,R1MOVC A,@A+DPTR LCALL WDATALCALL LCD_PRINTMOV A,#0C6HLCALL TEMP_BJ1MOV A,TEMP_TH ; 加载 TH 数据 MOV LCD_X,#3 ; 设置显示位置LCALL SHOW_DIG2H ;显示数据MOV A,#0CEHLCALL TEMP_BJ1MOV A,TEMP_TL ; 加载 TL 数据 MOV LCD_X,#12 ; 设置显示位置LCALL SHOW_DIG2L ;显示数据RETMOV A,#2; 显示在第二行INC R1DJNZ R0,BBJJ2RETBJ2: DB 00H,"C"POP B・ ************************** LCD 显示子程序**********************************SHOW_DIG2H: MOV B,#100DIV ABADD A,#30HPUSH BMOV B,LCD_XLCALL LCDP2POP BMOV A,#0AHXCH A,BDIV ABADD A,#30HINC LCD_XPUSH BMOV B,LCD_XLCALL LCDP2INC LCD_X MOV A,BMOV B,LCD_XADD A,#30HLCALL LCDP2RETSHOW_DIG2L:MOV B,#100 DIV ABMOV A,#0AHXCH A,B DIV ABADD A,#30H PUSH BMOV B,LCD_XLCALL LCDP2 POP B INC LCD_XMOV A,BMOV B,LCD_XADD A,#30HLCALL LCDP2RET;************************ 显示区BCD 码温度值刷新子程序**********************DISPBCD: MOV A,TEMPLCANL A,#0FHMOV 70H,A ; 小数位MOV A,TEMPLCSWAP AANL A,#0FHMOV 71H,A ; 个位MOV A,TEMPHCANL A,#0FHMOV 72H,A ; 十位MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,A ; 百位DISPBCD2: RET・ *************************** LCD 显示数据处理子程序*************************CONV: MOV A,73HMOV LCD_X,#6CJNE A,#1,CONV1JMP CONV2CONV1: CJNE A,#0BH,CONV11MOV A,#"-"JMP CONV111 CONV11: MOV A,#" " CONV111: MOV B,LCD_X LCALL LCDP2JMP CONV3CONV2: LCALL SHOW_DIG2CONV3: INC LCD_XMOV A,72HLCALL SHOW_DIG2INC LCD_XMOV A,71H LCALLSHOW_DIG2INC LCD_XMOV A,#'.'; 加载百位数据; 设置位置;"-" 号显示;"+" 号不显示; 显示数据; 十位; 个位第二行显示数字子程序设置显示地址设置LCD 的第二行地址写入命令 由堆栈取出 A; 写入数据MOV B,LCD_X LCALL LCDP2 MOV A,70H INC LCD_XLCALL SHOW_DIG2 RET; 加载小数点位 ; 设置显示位置 ; 显示数据第二行显示数字子程序・ ***************************5*************************SHOW_DIG2:ADD A,#30HMOV B,LCD_XLCALL LCDP2RET・ ***************************5*************************LCDP2: PUSH ACC MOVA,B ; ADD A,#0C0H ; LCALL WCOM ; POP ACC ;LCALL WDATARETLCALL WCOM・ ***************************5*************************SET_LCD: CLR LCD_ENLCALL INIT_LCD ; LCALL STORE_DATA ; RET・ ******************************5***********************************INIT_LCD: MOV A,#38H ;2LCALL WCOM LCALL DELAY1 MOV A,#38H LCALL WCOM LCALL DELAY1 MOV A,#38H LCALL WCOM LCALL DELAY1 MOV A,#0CH ;对 LCD 做 初 始 化 设 置 及 测 试初始化 LCD将自定义字符存入LCD 的CGRAMLCD 初 始 化开显示,显示光标,光标不闪烁LCALL DELAY1MOV A,#01H ; 清除 LCD 显示屏 LCALL WCOM LCALL DELAY1 RET清 除 LCD 的 第 一 行 字 符设置 LCD 的第一行地址 设置计数值载入空格符至 LCD 输出字符至 LCD 计数结束LCD 的 第一 行或第二行 显 示字符LCD_PRINT:CJNE A,#1,LINE2 ; 判断是否为第一行LINE1: MOV A,#80H ; 设置 LCD 的第一行地址LCALL WCOM ; 写入命令LCALL CLR_LINE ; 清除该行字符数据・ *****************************5**************************CLR_LINE1:MOV A,#80HLCALL WCOM MOV R0,#24 ;C1: MOV A,#' ' ; LCALLWDATA DJNZ R0,C1 ; RET・ *************************5**********************MOV A,#80H 设置 LCD 的第一行地址LCALL WCOM ; JMP FILL LINE2: MOV A,#0C0H LCALLWCOM ; LCALL CLR_LINEMOV A,#0C0H ;LCALL WCOMFILL: CLR A ;MOVC A,@A+DPTR CJNEA,#0,LC1 ;RETLC1: LCALL WDATA INCDPTR ; JMP FILL ; RET・ ***************************5****************************CLR_LINE: MOV R0,#24 CL1: MOV A,#' 'LCALL WDATA DJNZR0,CL1写入命令设置LCD 的第二行地址写入命令清除该行字符数据设置LCD 的第二行地址填入字符由消息区取出字符判断是否为结束码写入数据指针加1继续填入字符清除1 行LCD 的字符RET DE: MOV R7,#250DJNZ R7,$ RET・ ****************************5*************************WCOM: MOV P0,ACLR LCD_RS ;RS=L,RW=L,D0-D7= 指令码,E= 高脉冲CLR LCD_RW SETB LCD_EN LCALL DELAY1 CLR LCD_EN RETLCALL DELCD 间接控制方式命令写入写入命令・ ****************************5*************************WDATA: MOV P0,ASETB LCD_RS CLR LCD_RW SETB LCD_ENLCD 间接控制方式数据写 入写入数据CLR LCD_EN LCALL DE RET・ **************************5在LCD 的第一行显示字符**************************LCDP1: PUSH ACCMOV A,B ;设置显示地址ADD A,#80H ;设置LCD的第一行地址LCALL WCOM ;写入命令POP ACC ; 由堆栈取出ALCALL WDATA ; 写入数据RET・ ******************************5声光报警子程序*******************************BEEP_BL: MOV R6,#100BL2: LCALL DEX1CPL BEEPCPL RELAYDJNZ R6,BL2MOV R5,#10LCALL DELAYRETDEX1: MOV R7,#180DE2: NOPDJNZ R7,DE2RET・ ****************************** 延时子程序*******************************DELAY: MOV R6,#50DL1: MOV R7,#100DJNZ R7,$DJNZ R6,DL1DJNZ R5,DELAYRETDELAY1: MOV R6,#25 ; 延时5 毫秒DL2: MOV R7,#100DJNZ R7,$DJNZ R6,DL2RETENDLCDlLMOT6LDS18B2Θ OK TEMP : 82.0O C8sS23Sδ≥CRYSLUIXTALIXTAL2RSTPQOfAa) P0.1∕AD1PO2∕AD2 P0.3∕ACGP0.4∕ACU PO5∕AD6P0 6∕ACePO7∕AD7 ,°u∙远2QX 'KliS BP1 5 PI 6 Pl 7 ΘO5Γ <TEXT>K3K2 PSENALE EAP1.0 PII P1 2P2ΓUAfl P2.1)W P22∕A10 P23∕A11 P24∕A12 P25∕A13 P26∕A14 P27∕A15 P3.Q∕RXD P3.1∕7XD P3.2∕iF∏D P3 3∕INT1P3 4/TD P3 5f∏ P3 6Λ⅛5 P3 7WI ■■39■ 屮 ■ g■ 卜■ ■σ∙ O■ ■ ■ J■ --■↑2・ ■ 383" ■ 374・5" ■356"7" ■338∙■ 22 ....................... ...............................9・■51•■ 22•■ 23221 ∆2i * ±2& ■2Z. ■28 ,Ir蚩工n s: ∙ inJTDS1ΘB2D <TEXT>, ∙GND ∙ ∙2・ U2。

protues DS18B20仿真

protues DS18B20仿真

程序代码#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define nops(); {_nop_();_nop_();_nop_();_nop_();} sbit DQ=P3^0;uchar code led []={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};uchar code leddg []={ 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc} ;void display (double x);void delayms(uint z);void delay1(uint z);uint ds18b20();uchar reset18b20();void main (){double a;while(1){a=ds18b20();display(a);}}/////////////////////////////////////////////////////void delayms(uint z) //延时函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}///////////////////////////////void delay1(uint z){while(--z);}/////////////////////////////////////////////////void display (double x) //显示函数{ uint a,b,d,e;int c;double g,h;if (x<=128){ c=(int)x;//45 10.12a=c/100; //提取个位,百位b=c%100/10;d=c%100%10;g=x-c;//0.119999 有误差/* if((((int)(g*100)+1)-g*100)<=0.0001 ) //判断下消除误差g=g+0.01;d=(int)(g*10);h=10*g-d;e=(int)(h*10);*/e=(int)(10*g);P2=0xfe;P0=led[a];delayms(10);P2=0xfd;P0=led[b];delayms(10);P2=0xfb;P0=leddg[d];delayms(10);P2=0xf7;P0=led[e];delayms(10);}else{c=(int)(256-x);b=c/10;d=c%10;e=0;P2=0xfe;P0=0x40;delayms(10);P2=0xfd;P0=led[b];delayms(10);P2=0xfb;P0=leddg[d];delayms(10);P2=0xf7;P0=led[e];delayms(10);}}////////////////////////////////////////////////////uchar reset18b20() //复位18B20{uchar a;DQ=1;_nop_();_nop_();DQ=0;delay1(80);DQ=1;nops();a=DQ;delay1(20);return a ;}////////////////////////////////////////void write (uchar dat) //向18B20里写{uchar i;DQ=1;_nop_();for(i=0;i<8;i++){DQ=0;DQ=dat&0x01;delay1(51);DQ=1;dat>>=1;}}/////////////////////////////////////uchar read() //读取18b20{uchar i,dat=0;DQ=1;_nop_();for(i=0;i<8;i++){DQ=0;nops();dat>>=1;DQ=1;nops();if(DQ){dat|=0x80;}delay1(30);DQ=1;}return dat;}/////////////////////////////////////////////uint ds18b20() //启动18B20温度传感器{uint a,b;reset18b20();write(0xcc); //跳过ID地址write(0x44); //启动温度转换reset18b20();write(0xcc);write(0xbe); //读取温度a=read();b=read();b=b&0x0f;b<<=4;b+=(a&0xf0)>>4 ; //取出A的低4位在和B相加刚好B中存的温度的高低值return b;}。

DS18B20温度测量电路的设计与仿真

DS18B20温度测量电路的设计与仿真

151Digital technology and application 数字技术与应用·学术论坛·1、引言温度是日常生活和工农业生产中经常需要测试的重要参数。

传统的方式一般采用热电偶或热电阻,其输出的模拟信号,需经A/D 转换后才能送入单片机等微处理器,这样的硬件电路结构复杂,制作成本较高。

近年来,各种新型温度传感器和测量方法大量出现并成功应用。

单总线数字式智能型传感器技术彻底改变了传统的温度测量方法,直接将温度物理量转化为数字信号并以总线方法传送到微处理器进行数据处理。

其中以美国DALLAS 公司生产的DS18B20为代表的数字式智能温度传感器凭借其突出优点广泛使用于各种环境的自动化测量及控制系统中。

本文根据某温控设备的控制要求设计了以DS18B20作为温度采集器的温度测量电路,可实现温度的实时显示、超限报警等功能,并借助PROTUES 电路分析与实物仿真软件展示电路功能效果。

2、电路结构及工作原理基于DS18B20的温度测量电路主要由四部分组成:AT89C51单片机、DS18B20温度传感器、四位一体的共阴数码管、发光二极管构成的报警指示模块。

其结构框图如图1所示。

DS18B20工作电压为3~5V,测量温度范围为一55~+ 125℃,用户设置的报警温度存储在芯片内部EEPROM 中,可掉电保持。

它具有3引脚,当采用外部电源供电时,GND 脚接地,VCC 脚接电源,DQ 脚作为信号端接单片机I/O 口,电源脚和DQ 脚间还需要外接一个约4.7k 的上拉电阻,保证总线闲置时其状态为高电平。

DS18B20可以将所采集到的温度转换为数字信号,然后通过D Q 传送至单片机,单片机从而启动程序存储器中的控制程序,驱动数码管显示温度值,并控制高、低温报警指示二极管的亮灭。

3、软件设计电路是在程序的控制下,完成对温度测量、显示和超限报警。

软件程序设计包含DS 18B20温度测量、数码管显示、超限报警程序、主程序四部分。

DS18B20仿真

DS18B20仿真

1-Wire总线的基本通信协议作为一种单主机多从机的总线系统,在一条1-Wire总线上可挂接的从器件数量几乎不受限制。

为了不引起逻辑上的冲突,所有从器件的1-Wire总线接口都是漏极开路的,因此在使用时必须对总线外加上拉电阻(一般取5kΩ左右)。

主机对1-Wire总线的基本操作分为复位、读和写三种,其中所有的读写操作均为低位在前高位在后。

复位、读和写是1-Wire 总线通信的基础,下面通过具体程序详细介绍这3种操作的时序要求。

(程序中DQ代表1-Wire总线,定义为P1.0,uchar定义为unsigned char)1 1-Wire总线的复位复位是1-Wire总线通信中最为重要的一种操作,在每次总线通信之前主机必须首先发送复位信号。

如程序1.1所示,产生复位信号时主机首先将总线拉低480~960μs然后释放,由于上拉电阻的存在,此时总线变为高电平。

1-Wire总线器件在接收到有效跳变的15~60μs内会将总线拉低60~240μs,在此期间主机可以通过对DQ采样来判断是否有从器件挂接在当前总线上。

函数Reset()的返回值为0表示有器件挂接在总线上,返回值为1表示没有器件挂接在总线上。

程序1.1 总线复位uchar Reset(void){uchar tdq;DQ=0; //主机拉低总线delay480μs(); //等待480μsDQ=1; //主机释放总线delay60μs(); //等待60μstdq=DQ; //主机对总线采样delay480μs(); //等待复位结束return tdq; //返回采样值}2 1-Wire总线的写操作由于只有一条I/O线,主机1-Wire总线的写操作只能逐位进行,连续写8次即可写入总线一个字节。

如程序1.2所示,当MCS-51单片机的时钟频率为12MHz时,程序中的语句_nop_();可以产生1μs的延时,调用此函数时需包含头文件“intrins.h”。

以51单片机为核心的DS18B20的数码管显示温度程序+Proteus仿真

以51单片机为核心的DS18B20的数码管显示温度程序+Proteus仿真

//DS18B20的读写程序,数据脚P3.3 ////温度传感器18B20汇编程序,采用器件默认的12位转化////最大转化时间750微秒,显示温度-55到+125度,显示精度////为0.1度,显示采用4位LED共阳显示测温值////P0口为段码输入,P24~P27为位选///***************************************************/#include "reg51.h"#include "intrins.h" //_nop_();延时函数用#define Disdata P0 //段码输出口#define discan P2 //扫描口#define uchar unsigned char#define uint unsigned intsbit DQ=P3^3; //温度输入口sbit DIN=P0^7; //LED小数点控制uint h;uchar flag;//**************温度小数部分用查表法***********//uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};//uchar code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};//共阳LED段码表"0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-" uchar code scan_con[4]={0x7f,0xbf,0xdf,0xef}; //列扫描控制字uchar data temp_data[2]={0x00,0x00}; //读出温度暂放uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据和一个运算暂用///////***********11微秒延时函数**********///void delay(uint t){for(;t>0;t--);}///***********显示扫描函数**********/scan(){char k;for(k=0;k<4;k++) //四位LED扫描控制{Disdata=0xff;Disdata=dis_7[display[k]];if(k==1){DIN=0;}discan=scan_con[k];delay(90);discan=0xff;}}/////***********18B20复位函数**********/ow_reset(void){char presence=1;while(presence){while(presence){DQ=1;_nop_();_nop_();DQ=0; //delay(50); // 550usDQ=1; //delay(6); // 66uspresence=DQ; // presence=0继续下一步}delay(45); //延时500uspresence = ~DQ;}DQ=1;}/////**********18B20写命令函数*********///向1-WIRE 总线上写一个字节void write_byte(uchar val){uchar i;for (i=8; i>0; i--) //{DQ=1;_nop_();_nop_();DQ = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us DQ = val&0x01; //最低位移出delay(6); //66usval=val/2; //右移一位}DQ = 1;delay(1);}///*********18B20读1个字节函数********///从总线上读取一个字节uchar read_byte(void){uchar i;uchar value = 0;for (i=8;i>0;i--){DQ=1;_nop_();_nop_();value>>=1;DQ = 0; //_nop_();_nop_();_nop_();_nop_(); //4usDQ = 1;_nop_();_nop_();_nop_();_nop_(); //4us if(DQ)value|=0x80;delay(6); //66us}DQ=1;return(value);}///***********读出温度函数**********///read_temp(){ow_reset(); //总线复位write_byte(0xCC); // 发Skip ROM命令write_byte(0xBE); // 发读命令temp_data[0]=read_byte(); //温度低8位temp_data[1]=read_byte(); //温度高8位ow_reset();write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令}///***********温度数据处理函数**********/ void work_temp(){uchar n=0;uchar doth,dotl;uchar flag3=1,flag2=1; //数字显示修正标记if((temp_data[1]&0xf8)!=0x00){temp_data[1]=~(temp_data[1]);temp_data[0]=~(temp_data[0])+1;n=1;flag=1;}//负温度求补码if(temp_data[0]>255){temp_data[1]++;}display[4]=temp_data[0]&0x0f;display[0]=ditab[display[4]];doth=display[0]/10;dotl=display[0]%10;display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x07)<<4); display[3]=display[4]/100;display[2]=display[4]/10%10;display[1]=display[4]%10;if(!display[3]){display[3]=0x0a;flag3=0;if(!display[2]){display[2]=0x0a;flag2=0;}}//最高位为0时都不显示if(n){display[3]=0x0b;//负温度时最高位显示"-"flag3=0;}}/////**************主函数****************/main(){Disdata=0xff; //初始化端口discan=0xff;for(h=0;h<4;h++){display[h]=8;}//开机显示8888ow_reset(); // 开机先转换一次write_byte(0xCC); // Skip ROMwrite_byte(0x44); // 发转换命令for(h=0;h<500;h++){scan();} //开机显示"8888"2秒while(1){read_temp(); //读出18B20温度数据work_temp(); //处理温度数据scan(); //显示温度值2秒}}////*********************结束**************************//。

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图)

基于51单片机——Ds18B20温度采集,LCD显示汇编程序(附带proteus仿真图)

TEMP_ZH EQU 24H ;实测温度值存放单元TEMPL EQU 25HTEMPH EQU 26HTEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU 28H ;低温报警值存放单元TEMPHC EQU 29H ;正、负温度值标记TEMPLC EQU 2AHTEMPFC EQU 2BHK1 EQU P1.4 ;查询按键K2 EQU P1.5 ;设置/调整键K3 EQU P1.6 ;调整键K4 EQU P1.7 ;确定键BEEP EQU P3.7 ;蜂鸣器RELAY EQU P1.3 ;指示灯LCD_X EQU 2FH ;LCD 字符显示位置LCD_RS EQU P2.0 ;LCD 寄存器选择信号 LCD_RW EQU P2.1 ;LCD 读写信号LCD_EN EQU P2.2 ;LCD 允许信号FLAG1 EQU 20H.0 ;DS18B20是否存在标志 KEY_UD EQU 20H.1 ;设定按键的增、减标志 DQ EQU P3.3 ;DS18B20数据信号ORG 0000HLJMP MAINORG 0030HMAIN: MOV SP,#60HMOV A,#00HMOV R0,#20H ;将20H~2FH 单元清零MOV R1,#10HCLEAR: MOV @R0,AINC R0DJNZ R1,CLEARLCALL SET_LCDLCALL RE_18B20START: LCALL RST ;调用18B20复位子程序JNB FLAG1,START1 ;DS1820不存在LCALL MENU_OK ;DS1820存在,调用显示正确信息子程序MOV TEMP_TH,#055H ;设置TH初值85度MOV TEMP_TL,#019H ;设置TL初值25度LCALL RE_18B20A ;调用暂存器操作子程序LCALL WRITE_E2 ;写入DS18B20LCALL TEMP_BJ ;显示温度标记JMP START2START1: LCALL MENU_ERROR ;调用显示出错信息子程序 LCALL TEMP_BJ ;显示温度标记SJMP $START2: LCALL RST ;调用DS18B20复位子程序JNB FLAG1,START1 ;DS18B20不存在MOV A,#0CCH ;跳过ROM匹配命令LCALL WRITEMOV A,#44H ;温度转换命令LCALL WRITELCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0BEH ;读温度命令LCALL WRITELCALL READ ;调用DS18B20数据读取操作子程序LCALL CONVTEMP ;调用温度数据BCD 码处理子程序LCALL DISPBCD ;调用温度数据显示子程序LCALL CONV ;调用LCD显示处理子程序LCALL TEMP_COMP ;调用实测温度值与设定温度值比较子程序LCALL PROC_KEY ;调用键扫描子程序SJMP START2 ;循环;*************************** 键扫描子程序*****************************PROC_KEY:JB K1,PROC_K1LCALL BEEP_BLJNB K1,$MOV DPTR,#M_ALAX1MOV A,#1LCALL LCD_PRINTLCALL LOOK_ALARMJB K3,$LCALL BEEP_BLJMP PROC_K2PROC_K1: JB K2,PROC_ENDLCALL BEEP_BLJNB K2,$MOV DPTR,#RST_A1MOV A,#1LCALL LCD_PRINTLCALL SET_ALARMLCALL RE_18B20 ;将设定的TH,TL值写入DS18B20LCALL WRITE_E2PROC_K2: LCALL MENU_OKLCALL TEMP_BJPROC_END:RET;*************************** 设定温度报警值TH、TL ***************************SET_ALARM:LCALL LOOK_ALARMAS0: JB K1,AS00LCALL BEEP_BLJNB K1,$CPL 20H.1 ;UP/DOWN 标记AS00: JB 20H.1,ASZ01 ;20H.1=1,增加JMP ASJ01 ;20H.1=0,减小ASZ01: JB K2,ASZ02 ;TH值调整(增加)LCALL BEEP_BLINC TEMP_THMOV A,TEMP_THCJNE A,#120,ASZ011MOV TEMP_TH,#0ASZ011: LCALL LOOK_ALARMLCALL DELAYJMP ASZ01ASZ02: JB K3,ASZ03 ;TL值调整(增加) LCALL BEEP_BLINC TEMP_TLMOV A,TEMP_TLCJNE A,#99,ASZ021MOV TEMP_TL,#00HASZ021: LCALL LOOK_ALARMMOV R5,#10LCALL DELAYJMP ASZ02ASZ03: JB K4,AS0 ;确定调整LCALL BEEP_BLJNB K4,$RETASJ01: JB K2,ASJ02 ;TH值调整(减少) LCALL BEEP_BLDEC TEMP_THMOV A,TEMP_THCJNE A,#0FFH,ASJ011ASJ011: LCALL LOOK_ALARMMOV R5,#10LCALL DELAYJMP AS0ASJ02: JB K3,ASJ03 ;TL值调整(减少)LCALL BEEP_BLDEC TEMP_TLMOV A,TEMP_TLCJNE A,#0FFH,ASJ021JMP ASJ022ASJ021: LCALL LOOK_ALARM ;MOV R5,#10LCALL DELAYJMP AS0ASJ022: CPL 20H.1JMP ASZ01ASJ03: JMP ASZ03RETRST_A1: DB " SET ALERT CODE " ,0;*********************** 实测温度值与设定温度值比较子程序**********************TEMP_COMP:MOV A,TEMP_THSUBB A,TEMP_ZH ;减数>被减数,则JC CHULI1 ;借位标志位C=1,转 MOV A,TEMPFCCJNE A,#0BH,COMPSJMP CHULI2COMP: MOV A,TEMP_ZHSUBB A,TEMP_TL ;减数>被减数,则JC CHULI2 ;借位标志位C=1,转MOV DPTR,#BJ5LCALL TEMP_BJ3CLR RELAY ;点亮指示灯RETCHULI1: MOV DPTR,#BJ3LCALL TEMP_BJ3SETB RELAY ;熄灭指示灯LCALL BEEP_BL ;蜂鸣器响RETCHULI2: MOV DPTR,#BJ4LCALL TEMP_BJ3SETB RELAY ;熄灭指示灯LCALL BEEP_BL ;蜂鸣器响RET;-----------------------------------------TEMP_BJ3: MOV A,#0CEHLCALL WCOMMOV R1,#0MOV R0,#2BBJJ3: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ3RETBJ3: DB ">H"BJ4: DB "<L"BJ5: DB " !";;**************************** 显示温度标记子程序***************************TEMP_BJ: MOV A,#0CBHLCALL WCOMMOV DPTR,#BJ1 ;指针指到显示消息MOV R1,#0MOV R0,#2BBJJ1: MOV A,R1MOVC A,@A+DPTRLCALL WDATAINC R1DJNZ R0,BBJJ1RETBJ1: DB 00H,"C";******************************** 显示正确信息子程序***************************MENU_OK: MOV DPTR,#M_OK1 ;指针指到显示消息MOV A,#1 ;显示在第一行LCALL LCD_PRINTMOV DPTR,#M_OK2 ;指针指到显示消息MOV A,#2 ;显示在第一行LCALL LCD_PRINTRETM_OK1: DB " DS18B20 OK ",0M_OK2: DB " TEMP: ",0;******************************** 显示出错信息子程序***************************MENU_ERROR:MOV DPTR,#M_ERROR1 ;指针指到显示消息MOV A,#1 ;显示在第一行LCALL LCD_PRINTMOV DPTR,#M_ERROR2 ;指针指到显示消息1MOV A,#2 ;显示在第一行LCALL LCD_PRINTRETM_ERROR1: DB " DS18B20 ERROR ",0M_ERROR2: DB " TEMP: ---- ",0;****************************DS18B20复位子程序*****************************RST: SETB DQNOPCLR DQMOV R0,#6BH ;主机发出延时复位低脉冲MOV R1,#04HTSR1: DJNZ R0,$MOV R0,#6BHDJNZ R1,TSR1SETB DQ ;拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3 ;等待DS18B20回应DJNZ R0,TSR2JMP TSR4 ; 延时TSR3: SETB FLAG1 ; 置1标志位,表示DS1820存在JMP TSR5TSR4: CLR FLAG1 ; 清0标志位,表示DS1820不存在 JMP TSR7TSR5: MOV R0,#06BHTSR6: DJNZ R0,$ ; 时序要求延时一段时间TSR7: SETB DQRET;************************ DS18B20暂存器操作子程序***************************RE_18B20:JB FLAG1,RE_18B20ARETRE_18B20A:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEWR_SCRAPD:MOV A,#4EH ;写暂器LCALL WRITEMOV A,TEMP_TH ;TH(报警上限)LCALL WRITEMOV A,TEMP_TL ;TL(报警下限)LCALL WRITEMOV A,#7FH ;12位精度LCALL WRITERET;************************ 复制暂存器子程序*******************************WRITE_E2:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#48H ;把暂存器里的温度报警值拷贝到EEROMLCALL WRITERET;*********************** 重读EEROM子程序********************************READ_E2:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0B8H ;把EEROM里的温度报警值拷贝回暂存器LCALL WRITERET;************************ 将自定义字符写入LCD的CGRAM中*********************STORE_DATA:MOV A,#40HLCALL WCOMMOV R2,#08HMOV DPTR,#D_DATAMOV R3,#00HS_DATA: MOV A,R3MOVC A,@A+DPTRLCALL WDATA ;写入数据INC R3DJNZ R2,S_DATARETD_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00H;*********************** DS18B20数据写入操作子程序************************WRITE: MOV R2,#8 ;一共8位数据CLR CWR1: CLR DQ ;开始写入DS18B20总线要处于复位(低)状态MOV R3,#07DJNZ R3,$ ;总线复位保持16微妙以上RRC A ;把一个字节DATA 分成8个BIT 环移给CMOV DQ,C ;写入一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙SETB DQ ;重新释放总线NOPDJNZ R2,WR1 ;写入下一位SETB DQRET;********************** DS18B20数据读取操作子程序**************************READ: MOV R4,#4 ;将温度低位、高位、TH、TL从DS18B20中读出MOV R1,#TEMPL ;存入25H、26H、27H、28H单元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQ ;读前总线保持为低NOPNOPNOPSETB DQ ;开始读总线释放MOV R3,#09 ;延时18微妙DJNZ R3,$MOV C,DQ ;从DS18B20总线读得一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙RRC A ;把读得的位值环移给ADJNZ R2,RE01 ;读下一位MOV @R1,AINC R1DJNZ R4,RE00RET;************************ 温度值BCD 码处理子程序*************************CONVTEMP: MOV A,TEMPH ;判温度是否零下ANL A,#08HJZ TEMPC1 ;温度零上转CLR CMOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,AMOV TEMPHC,#0BH ;负温度标志MOV TEMPFC,#0BHSJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ;正温度标志MOV TEMPFC,#0AHTEMPC11: MOV A,TEMPHCSWAP AMOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;乘0.0625MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分 BCDMOV A,TEMPL ;整数部分ANL A,#0F0H ;取出高四位SWAP AMOV TEMPL,AMOV A,TEMPH ;取出低四位ANL A,#0FHSWAP AORL A,TEMPL ;重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0HSWAP AORL A,TEMPHC ;TEMPHC LOW = 十位数BCDMOV TEMPHC,AMOV A,TEMPLANL A,#0FHSWAP A ;TEMPLC HI = 个位数BCDORL A,TEMPLCMOV TEMPLC,AMOV A,R4JZ TEMPC12ANL A,#0FHSWAP AMOV R4,AMOV A,TEMPHC ;TEMPHC HI = 百位数BCDANL A,#0FHORL A,R4MOV TEMPHC,ATEMPC12: RET;************************ 二-十进制转换子程序*****************************HEX2BCD1: MOV B,#064HDIV ABMOV R4,AMOV A,#0AHXCH A,BDIV ABSWAP AORL A,BRETTEMPDOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H ; 小数部分码表DB 05H,05H,06H,06H,07H,08H,08H,09H;********************** 查询温度报警值子程序***************************LOOK_ALARM: MOV DPTR,#M_ALAX2 ;指针指到显示信息区MOV A,#2 ;显示在第二行LCALL LCD_PRINTMOV A,#0C6HLCALL TEMP_BJ1MOV A,TEMP_TH ;加载TH数据MOV LCD_X,#3 ;设置显示位置LCALL SHOW_DIG2H ;显示数据MOV A,#0CEHLCALL TEMP_BJ1MOV A,TEMP_TL ;加载TL数据MOV LCD_X,#12 ;设置显示位置LCALL SHOW_DIG2L ;显示数据RETM_ALAX1: DB " LOOK ALERT CODE",0M_ALAX2: DB "TH: TL: ",0TEMP_BJ1: LCALL WCOMMOV DPTR,#BJ2 ;指针指到显示信息区 MOV R1,#0MOV R0,#2BBJJ2: MOV A,R1MOVC A,@A+DPTRLCALL WDATADJNZ R0,BBJJ2RETBJ2: DB 00H,"C";************************** LCD显示子程序**********************************SHOW_DIG2H: MOV B,#100DIV ABADD A,#30HPUSH BMOV B,LCD_XLCALL LCDP2POP BMOV A,#0AHXCH A,BDIV ABADD A,#30HINC LCD_XPUSH BMOV B,LCD_XLCALL LCDP2INC LCD_XMOV A,BMOV B,LCD_XADD A,#30HLCALL LCDP2RETSHOW_DIG2L: MOV B,#100DIV ABMOV A,#0AHXCH A,BDIV ABADD A,#30HPUSH BMOV B,LCD_XLCALL LCDP2POP BINC LCD_XMOV A,BMOV B,LCD_XADD A,#30HLCALL LCDP2RET;************************ 显示区BCD 码温度值刷新子程序**********************DISPBCD: MOV A,TEMPLCANL A,#0FHMOV 70H,A ;小数位MOV A,TEMPLCSWAP AANL A,#0FHMOV 71H,A ;个位MOV A,TEMPHCANL A,#0FHMOV 72H,A ;十位MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,A ;百位DISPBCD2: RET;*************************** LCD 显示数据处理子程序*************************CONV: MOV A,73H ;加载百位数据MOV LCD_X,#6 ;设置位置CJNE A,#1,CONV1JMP CONV2CONV1: CJNE A,#0BH,CONV11MOV A,#"-" ;"-"号显示JMP CONV111CONV11: MOV A,#" " ;"+"号不显示CONV111: MOV B,LCD_XLCALL LCDP2JMP CONV3CONV2: LCALL SHOW_DIG2 ;显示数据CONV3: INC LCD_XMOV A,72H ;十位LCALL SHOW_DIG2INC LCD_XMOV A,71H ;个位LCALL SHOW_DIG2INC LCD_XMOV A,#'.'MOV B,LCD_XLCALL LCDP2MOV A,70H ;加载小数点位INC LCD_X ;设置显示位置LCALL SHOW_DIG2 ;显示数据RET;*************************** 第二行显示数字子程序*************************SHOW_DIG2:ADD A,#30HMOV B,LCD_XLCALL LCDP2RET;*************************** 第二行显示数字子程序*************************LCDP2: PUSH ACCMOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址LCALL WCOM ;写入命令POP ACC ;由堆栈取出ALCALL WDATA ;写入数据RET;*************************** 对LCD 做初始化设置及测试*************************SET_LCD: CLR LCD_ENLCALL INIT_LCD ;初始化 LCDLCALL STORE_DATA ;将自定义字符存入LCD的CGRAM RET;****************************** LCD初始化***********************************INIT_LCD: MOV A,#38H ;2行显示,字形5*7点阵LCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#38HLCALL WCOMLCALL DELAY1MOV A,#0CH ;开显示,显示光标,光标不闪烁 LCALL WCOMLCALL DELAY1MOV A,#01H ;清除 LCD 显示屏LCALL WCOMLCALL DELAY1RET;***************************** 清除LCD的第一行字符**************************CLR_LINE1:MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOMMOV R0,#24 ;设置计数值C1: MOV A,#' ' ;载入空格符至LCDLCALL WDATA ;输出字符至LCDDJNZ R0,C1 ;计数结束RET;************************* LCD的第一行或第二行显示字符**********************LCD_PRINT:CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOM ;写入命令LCALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址LCALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置 LCD 的第二行地址LCALL WCOM ;写入命令LCALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址LCALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: LCALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;*************************** 清除1行LCD 的字符****************************CLR_LINE: MOV R0,#24CL1: MOV A,#' 'LCALL WDATADJNZ R0,CL1RETDE: MOV R7,#250DJNZ R7,$RET;**************************** LCD 间接控制方式命令写入*************************WCOM: MOV P0,A ;写入命令CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR LCD_RWSETB LCD_ENLCALL DELAY1CLR LCD_ENRET;**************************** LCD 间接控制方式数据写入*************************WDATA: MOV P0,A ;写入数据SETB LCD_RSCLR LCD_RWSETB LCD_ENLCALL DELCALL DERET;************************** 在LCD的第一行显示字符**************************LCDP1: PUSH ACCMOV A,B ;设置显示地址ADD A,#80H ;设置LCD的第一行地址LCALL WCOM ;写入命令POP ACC ;由堆栈取出ALCALL WDATA ;写入数据RET;****************************** 声光报警子程序*******************************BEEP_BL: MOV R6,#100BL2: LCALL DEX1CPL BEEPCPL RELAYDJNZ R6,BL2MOV R5,#10RETDEX1: MOV R7,#180DE2: NOPDJNZ R7,DE2RET;****************************** 延时子程序*******************************DELAY: MOV R6,#50DL1: MOV R7,#100DJNZ R7,$DJNZ R6,DL1DJNZ R5,DELAYRETDELAY1: MOV R6,#25 ;延时5毫秒DL2: MOV R7,#100DJNZ R7,$DJNZ R6,DL2RETEND。

DS18B20的程序和proteus仿真

DS18B20的程序和proteus仿真

#include <reg52.h>#include <intrins.h>#define uchar unsigned char #define uint unsigned int sbit dula=P2^6;sbit wela=P2^7;sbit DQ=P2^2;uchar presence,n,t;uchar bai,shi,ge,shifenwei; uint temp;float wendu;uchar data a,b,;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40};uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};void delay(uint num);init_DS18B20(void){DQ=1;_nop_();_nop_();DQ=0;delay(50);//精确延时550us;DQ=1;//拉高总线(要求16~60us)delay(5);presence=DQ;//如果=0则初始化成功 =1则初始化失败 delay(15); //这段时间DQ为0,延时60~240us;DQ=1;return(presence);}ReadOneChar(void)//读一个字节{uchar i=0;uint data dat=0;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();dat>>=1;DQ=0;_nop_();_nop_();_nop_();_nop_();DQ=1;_nop_();_nop_();_nop_();_nop_();if(DQ){dat|=0x80;//从DQ=0到DQ=1,到主机读位有15us delay(8);//的时间,然后在60~240us内释放总线//这里延时88us;}}DQ=1;return(dat);}/************************/void WriteOneChar(uint data dat){uchar i;for(i=8;i>0;i--){DQ=1;_nop_();_nop_();DQ=0;_nop_();_nop_();_nop_();_nop_();_nop_();DQ=dat&0x01;delay(6);//DQ在为低电平后的15~60us内dat>>=1; //对总线电平采样,所以延时要大于60us} //以保证DQ能正常采样。

基于Proteus仿真实例DS18B20

基于Proteus仿真实例DS18B20

DS18B20之Proteus仿真使用分类:传感器AVR与C2010-05-22 12:20 886人阅读评论(0) 收藏举报对于数字单线温度传感器DS18B20可谓是久仰大名,但是一直都没有认真的去弄过。

曾经看过网络上流传的中文PDF文档,感到其对时序要求比较严格,其他倒无所谓。

这几天感到有必要把曾经弄过的以及没有弄过但是比较常用的传感器写个范例,以便于以后的工作。

就从这个18B20开始了。

结果。

第一天没搞定!第二天。

又没搞定!这下怒了,虽说不是什么高手,但是搞个温度传感器都要2天那还了得!于是在周末决定好好研究一下。

先来看18B20的时序。

-----K,竟然不能插入图片!好吧,口述。

一般要求DS18B20数据总线使用4.7K左右的电阻上拉,所以在MCU或者DS18B20没有强制将总线拉低的情况下,总线应该是高电平的。

复位的要求是持续拉低总线480us以上(小于960us),然后释放总线。

对于AVR之类的有数据方向存储器的MCU,将数据方向设置为输入即可。

这个时候总线应该会被上拉电阻拉高。

然后静静等待,如果DS18B20正常,那它应该会在15-60us之后将总线拉低60-240us。

我对这两个数据感到非常的不爽。

MCU什么时候采样电平最合适呢?只能在MCU释放总线60us后,才能保证此时DS18B20如果存在肯定是将总线拉低的,但是也不能再后了,因为DS18B20将总线拉低最短只有60us。

万一DS18B20在MCU释放总线后15us后就拉低了总线,且又仅拉低60us。

留给MCU采样的时间只有15us了!郁闷!这里要注意一条C的语句可能执行N多个机器周期,所以还要注意指令执行时间,如果你的MCU时钟比较慢,那就等死吧。

恩还有,从释放总线开始到开始执行其他操作这段时间最短也要480us。

(其实我没这么干也成功了)写时序:DS18B20以下降沿开始表示一次操作开始。

无论读写都是如此。

写操作有写“1”与写“0”(二进制就是好啊)。

DS18B20_proteus仿真(BCD数码管显示测试)

DS18B20_proteus仿真(BCD数码管显示测试)

TEMP_ZH EQU 24H ;实测温度值存放单元TEMPL EQU 25HTEMPH EQU 26HTEMP_TH EQU 27H ;高温报警值存放单元TEMP_TL EQU 28H ;低温报警值存放单元TEMPHC EQU 29H ;正、负温度值标记TEMPLC EQU 2AHTEMPFC EQU 2BHFLAG1 EQU 20H.0 ;DS18B20是否存在标志DQ EQU P3.3 ;DS18B20数据信号ORG 0000H;*************************** 主程序开始 ******************************;*************************** 主循环开始 ****************************** START: LCALL RST ;调用DS18B20复位子程序JNB FLAG1,START ;DS18B20不存在MOV A,#0CCH ;跳过ROM匹配命令LCALL WRITEMOV A,#44H ;温度转换命令LCALL WRITELCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEMOV A,#0BEH ;读温度命令LCALL WRITELCALL READ ;调用DS18B20数据读取操作子程序LCALL CONVTEMP ;调用温度数据BCD 码处理子程序;MOV P1,70H ;小数位;MOV P1,71H ;个位;MOV P1,72H ;十位;MOV P1,73H ;百位(正温度大于或等于100=1,小于100=A,负温度=B)MOV P2,TEMPLC ;个位+小数位MOV P1,TEMPHC ;百位+十位SJMP START ;循环;*************************** 主循环结束 ******************************;****************************DS18B20复位子程序 ***************************** RST: SETB DQNOPCLR DQMOV R0,#6BH ;主机发出延时复位低脉冲MOV R1,#04HTSR1: DJNZ R0,$MOV R0,#6BHDJNZ R1,TSR1SETB DQ ;拉高数据线NOPNOPNOPMOV R0,#32HTSR2: JNB DQ,TSR3 ;等待DS18B20回应DJNZ R0,TSR2JMP TSR4 ; 延时TSR3: SETB FLAG1 ; 置1标志位,表示DS1820存在JMP TSR5TSR4: CLR FLAG1 ; 清0标志位,表示DS1820不存在JMP TSR7TSR5: MOV R0,#06BHTSR6: DJNZ R0,$ ; 时序要求延时一段时间;************************ DS18B20暂存器操作子程序 *************************** RE_18B20:JB FLAG1,RE_18B20ARETRE_18B20A:LCALL RSTMOV A,#0CCH ;跳过ROM匹配LCALL WRITEWR_SCRAPD:MOV A,#4EH ;写暂器LCALL WRITEMOV A,TEMP_TH ;TH(报警上限)LCALL WRITEMOV A,TEMP_TL ;TL(报警下限)LCALL WRITEMOV A,#7FH ;12位精度LCALL WRITERET;*********************** DS18B20数据写入操作子程序 ************************ WRITE: MOV R2,#8 ;一共8位数据CLR CWR1: CLR DQ ;开始写入DS18B20总线要处于复位(低)状态MOV R3,#07DJNZ R3,$ ;总线复位保持16微妙以上RRC A ;把一个字节DATA 分成8个BIT环移给CMOV DQ,C ;写入一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙SETB DQ ;重新释放总线NOPDJNZ R2,WR1 ;写入下一位SETB DQRET;********************** DS18B20数据读取操作子程序 ************************** READ: MOV R4,#4 ;将温度低位、高位、TH、TL从DS18B20中读出MOV R1,#TEMPL ;存入25H、26H、27H、28H单元RE00: MOV R2,#8RE01: CLR CYSETB DQNOPNOPCLR DQ ;读前总线保持为低NOPNOPNOPSETB DQ ;开始读总线释放MOV R3,#09 ;延时18微妙DJNZ R3,$MOV C,DQ ;从DS18B20总线读得一位MOV R3,#3CHDJNZ R3,$ ;等待100微妙RRC A ;把读得的位值环移给ADJNZ R2,RE01 ;读下一位MOV @R1,AINC R1DJNZ R4,RE00RET;************************ 温度值 BCD 码处理子程序 ************************* CONVTEMP: MOV A,TEMPH ;判温度是否零下ANL A,#08HJZ TEMPC1 ;温度零上转CLR CMOV A,TEMPL ;二进制数求补(双字节)CPL A ;取反加1ADD A,#01HMOV TEMPL,AMOV A,TEMPHCPL AADDC A,#00HMOV TEMPH,AMOV TEMPHC,#0BH ;负温度标志MOV TEMPFC,#0BHSJMP TEMPC11TEMPC1: MOV TEMPHC,#0AH ;正温度标志MOV TEMPFC,#0AHTEMPC11: MOV A,TEMPHCSWAP AMOV TEMPHC,AMOV A,TEMPLANL A,#0FH ;乘0.0625MOV DPTR,#TEMPDOTTABMOVC A,@A+DPTRMOV TEMPLC,A ;TEMPLC LOW=小数部分 BCDMOV A,TEMPL ;整数部分ANL A,#0F0H ;取出高四位SWAP AMOV TEMPL,AMOV A,TEMPH ;取出低四位ANL A,#0FHSWAP AORL A,TEMPL ;重新组合MOV TEMP_ZH,ALCALL HEX2BCD1MOV TEMPL,AANL A,#0F0HSWAP AORL A,TEMPHC ;TEMPHC LOW = 十位数 BCDMOV TEMPHC,AMOV A,TEMPLANL A,#0FHSWAP A ;TEMPLC HI = 个位数 BCDORL A,TEMPLCMOV TEMPLC,AMOV A,R4JZ TEMPC12ANL A,#0FHSWAP AMOV R4,AMOV A,TEMPHC ;TEMPHC HI = 百位数 BCDANL A,#0FHORL A,R4MOV TEMPHC,ATEMPC12: RET;************************ 二-十进制转换子程序 ***************************** HEX2BCD1: MOV B,#064HDIV ABMOV R4,AMOV A,#0AHXCH A,BDIV AB;************************ 显示区 BCD 码温度值刷新子程序 ********************** DISPBCD: MOV A,TEMPLCANL A,#0FHMOV 70H,A ;小数位MOV A,TEMPLCSWAP AANL A,#0FHMOV 71H,A ;个位MOV A,TEMPHCANL A,#0FHMOV 72H,A ;十位MOV A,TEMPHCSWAP AANL A,#0FHMOV 73H,A ;百位RETEND。

数字体温计protues仿真图和程序

数字体温计protues仿真图和程序

系统程序#include<reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit BUFFER=P1^5;sbit DQ=P3^7 ;sbit lcdrs=P2^6;sbit lcden=P2^7;sbit lcdrw=P2^5;sbit AN=P2^0;sbit AM=P2^1;uchar code Temp_Disp_Title[]={Current Temp : };uchar temp_buffer[]={TEMP: };uchar code xs[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9} ;//小数位uchar Temp_value[]={0x00,0x00};//为DS18B20读取的字节分配地址uchar Display_Digit[]={0,0,0,0};uint T;void delay(uint);void delay1602(uint);void init_ds18b20();void write_byte(uchar date);void display_temp();void write_com(uchar);void write_2(uchar);void init1602();uchar read_byte();void read_temp();void main(){ bit zhi=0;AN=1;init1602(); //1602初始化read_temp(); //读取温度delay(50000);while(1){read_temp();if(zhi==0)display_temp(); // 按键没有按下时显示温度if(Display_Digit[2]>2) //设定报警温度if(zhi==0)BUFFER=0;delay(2000);BUFFER=1;delay1602(1);if(AN==0) // 检测按键{//去抖delay1602(5) ;按下按键if(AN==0) //zhi=~zhi;{// //while(1); 保持当前温度松手检测while(!AN); //}}}}void delay(uint t){while(t--);}void delay1602(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--) ;}/****************************初始化,检测DS18B20是否在线*****************************/void init_ds18b20(){DQ=1;delay(8);DQ=0;delay(85);DQ=1;delay(14);delay(5);}void write_byte(uchar date){uchar i;for(i=0;i<8;i++){写数据前将数据线拉低DQ=0; //DQ=date&0x01; // 从最低位开始写留出delay(5);// ds18b20采样时间采样完将数据拉高,等待下一次采样DQ=1;//右移一位date>>=1;//date}delay(5);}uchar read_byte(){uint i,value;for(i=0;i<8;i++){DQ=0;value>>=1;//右移一位,同时起延时作用DQ=1;if(DQ==1)value|=0x80;//从高位开始读delay(5);}return value;}void read_temp(){init_ds18b20();ROM write_byte(0xcc);//跳过启动温度测量write_byte(0x44);// delay(200);//给出温度测量时间init_ds18b20();ROM 跳过write_byte(0xcc);// 读取温度write_byte(0xbe);//} void display_temp(){uint i;Temp_value[0]=read_byte();Temp_value[1]=read_byte();//Display_Digit[0] = xs[Temp_value[0]&0x0f]; 显示小数位T=((Temp_value[0]&0xf0)>>4) | ((Temp_value[1]&0x07)<<4); Display_Digit[3] = T/100;//百位十位Display_Digit[2] = T_x0010_0/10; //Display_Digit[1] = T_x0010_;//个位temp_buffer[11]= Display_Digit[0]+'0' ;temp_buffer[10]='.';temp_buffer[9]=Display_Digit[1]+'0' ;temp_buffer[8]=Display_Digit[2]+'0' ;temp_buffer[7]=Display_Digit[3]+'0' ;if(Display_Digit[3] == 0)temp_buffer[7]=' ';//如果百位为0 ,则显示空格if(Display_Digit[2] == 0&&Display_Digit[3]==0),则十位处显示空格如果百位和十位同时为0 temp_buffer[8]=' ';//write_com(0x80);for(i=0;i<15;i++){write_2(Temp_Disp_Title[i]);write_com(0x80+0x40) ;for(i=0;i<12;i++){write_2(temp_buffer[i]);delay1602(10);}write_com(0x80+0x4d);write_2(0xdf);write_2('C'); }void write_com(uchar com){lcdrs=0;P0=com;delay1602(5);lcden=1;delay1602(5);lcden=0;}void write_2(uchar da){lcdrs=1;P0=da;delay1602(5);lcden=1;delay1602(5);lcden=0;}void init1602(){lcden=0;lcdrw=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x80);}仿真图程序清单#include<reg51.h>#define uchar unsigned char#define uint unsigned intuchar i;sbit lcdrs=P3^0;sbit lcdrw=P3^1;sbit lcden=P3^2;sbit d1=P1^0;sbit d2=P1^1;uchar code t0[]=he temperature ;uchar code t1[]= is ;uchar code wendu[]=3456789; 利用一个温度表解决温度显示// 乱码IO sbit DQ = P3^7;//定义ds18B20总线//液晶显示模块void delay(uint z){uint x,y;for(x=100;x>1;x--)for(y=z;y>1;y--);}void write_com(uchar com){lcdrs=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date){lcdrs=1;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void init_lcd(){lcden=0;lcdrw=0;write_com(0x38);write_com(0x01);write_com(0x0c);write_com(0x06);write_com(0x80);for(i=0;i<16;i++){write_date(t0[i]);delay(0);}write_com(0x80+0x40);for(i=0;i<16;i++){write_date(t1[i]);delay(0);}}//温度采集模块void tmpDelay(int num)//延时函数{while(num--) ;}/******************************************************************** **********/void Init_DS18B20()//初始化ds1820{unsigned char x=0;DQ = 1; //DQ复位tmpDelay(8); //稍做延时DQ = 0; //单片机将DQ拉低tmpDelay(80); //精确延时大于480usDQ = 1; //拉高总线tmpDelay(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败tmpDelay(20);}unsigned char ReadOneChar()//读一个字节{unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;tmpDelay(4);}return(dat);}void WriteOneChar(unsigned char dat)//写一个字节{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;tmpDelay(5);DQ = 1;dat>>=1;}}unsigned int Readtemp()//读取温度{unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器a=ReadOneChar(); //连续读两个字节数据//读低8位b=ReadOneChar(); //读高8位t=b;t=t|a; //两字节合成一个整型变量。

利用单片机控制18B20温度控制Proteus仿真

利用单片机控制18B20温度控制Proteus仿真

仿真图:程序:#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned char#define NOP() {_nop_();_nop_();_nop_();_nop_();}//------LCD引脚-----sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_EN=P2^2;sbit DQ=P3^3;uchar code table[]={"Temperature:"}; //LCD第一行显示uchar temp_dis[]={" C"}; //LCD第二行//-----温度字符-----uchar code Temperature[]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};/* ************* 温度小数部分表********** */uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};uchar Temp_value[]={0x00,0x00}; //从DS18B20读取的温度值uchar digital[]={0,0,0,0}; //各温度数位uchar Current_T=0; //当前温度的整数部分//--------延时-------void delay(uint ms){uint t;while(ms--)for(t=0;t<120;t++);}void Delayus(uint m){while(m--);}//-------读LCD状态-------uchar read_lcd_state(){uchar state;LCD_RS=0;LCD_RW=1;LCD_EN=1;_nop_();state=P0;LCD_EN=0;_nop_();return state;}//-------忙等待------void lcd_busy_wait(){while((read_lcd_state() & 0x80)==0x80);NOP();}//----------LCD写指令----------void lcd_write_com(uchar com){lcd_busy_wait();LCD_RS=0; //RS为0时,写指令,RS为1时,写数据LCD_RW=0;P0=com;NOP();LCD_EN=1;NOP();LCD_EN=0;}//----------LCD写数据----------void lcd_write_data(uchar dat){lcd_busy_wait();LCD_RS=1;LCD_RW=0;P0=dat;NOP(); //如果用delay()延时函数时,延时时间较长,导致LCD显示与电压表示数不同步LCD_EN=1;NOP();LCD_EN=0;}//-------LCD初始化-------void lcd_init(){LCD_EN=0;lcd_write_com(0x38); //LCD显示模式设置lcd_write_com(0x0c); //LCD显示开/关及光标设置lcd_write_com(0x06); //当写一个字符后地址指针加1,且光标加1lcd_write_com(0x01); //显示清屏}//---------设置液晶显示位置-----------void set_lcd_pos(uchar p){lcd_write_com(p | 0x80);}//---------液晶显示程序----------void lcd_print(uchar p,uchar *s,uint low){uint num;set_lcd_pos(p);for(num=0;num<low;num++){lcd_write_data(s[num]);delay(1);}}/* ******初始化DS18B20********/void Init_DS18B20(){uchar status=0;DQ=1; //DQ复位Delayus(8); //稍作延时DQ=0; //单片机将DQ拉低Delayus(80); //精确延时大于480usDQ=1; //拉高总线Delayus(8);status=DQ;Delayus(20);}/* ******* 从DS18B20读入数据******* */uchar ReadOneChar(){uchar i,dat = 0;for(i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;Delayus(4);}return(dat);}/* ******** 向DS18B20写命令******** */void WriteOneChar(uchar dat){uchar i=0;for(i=8;i>0;i--){DQ = 0;DQ = dat&0x01;Delayus(5);DQ = 1;dat>>=1;}}/* ******DS18B20程序读取温度********* */ void ReadTemperature(){Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x44); //启动温度转换Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等,前两个就是温度Temp_value[0]=ReadOneChar(); //低八位Temp_value[1]=ReadOneChar(); //高八位}//--------显示当前温度值-------void display_temp(){uchar ng=0; //负数标志// 高5位全为1则为负数,为负数时取反加1,并设置负数标志if((Temp_value[1] & 0xf8)==0xf8){Temp_value[1]=~Temp_value[1];Temp_value[0]=~Temp_value[0]+1;if(Temp_value[0]==0x00)Temp_value[1]++;ng=1;}digital[0]=ditab[Temp_value[0] & 0x0f]; //温度小数部分// 获取温度整数部分(高字节中的低3位和低字节中的高4位)Current_T=((Temp_value[0] & 0xf0)>>4)|((Temp_value[1] & 0x07)<<4);digital[3]=Current_T/100; //分解digital[2]=Current_T%100/10;digital[1]=Current_T%10;// LCD显示temp_dis[7]=digital[0]+'0';temp_dis[6]='.';temp_dis[5]=digital[1]+'0';temp_dis[4]=digital[2]+'0';temp_dis[3]=digital[3]+'0';if(digital[3]==0) //高位为0时不显示temp_dis[3]=' ';if(digital[2]==0&&digital[3]==0)temp_dis[4]=' ';if(ng){if(temp_dis[4]==' ')temp_dis[4]='-';else if(temp_dis[3]==' ')temp_dis[3]='-';elsetemp_dis[2]='-';}lcd_print(0x02,table,12);lcd_print(0x41,temp_dis,16); }//------------主程序----------- void main(){lcd_init();ReadTemperature();delay(20);while(1){ReadTemperature();display_temp();delay(20);}}。

#基于DS18B20温度传感器温控系统的Proteus仿真

#基于DS18B20温度传感器温控系统的Proteus仿真

基于DS18B20温度传感器温控系统的Proteus仿真DS18B20温度传感器是美国DALLAS半导体公司推出的支持“一线总线”接口的传感器。

具有功耗低、性能高、抗干扰能力强的特点,可以直接将温度转化为串行数字信号供处理器处理。

DS18B20传感器具有以下一些特性:(1)测温范围-55℃至+125℃,在-10℃至+85℃时的精度为正负0.5℃;(2)适应电压的范围在3.0至5.5V;(3)单线接口,只用一条口线就可以与微处理器的双向通信;(4)支持多点组网,多个DS18B20并接在一根口线上就可实现多点测温;(5)测量结果直接输出数字温度信号,通过单线串行传输给微处理器;(6)具有负压特性,电源极性接反芯片不会烧坏,只是不能正常工作;(7)可编程分辨率为9至12位,对应的分辨温度分别是0.5℃,0.25℃,0.125℃,0.0625℃,能够实现高精度测温。

(8)在9位分辨率时可在93.75ms内把温度值转换为数字;在12位分辨率时可在750us内把温度值转换为数字;(9)传送数据时可传送CRC校验码,抗干扰纠错能力强。

DS18B20的引脚封装图如下:各引脚定义如下:GND:电源地DQ:信号输入输出V DD:电源正极NC:空DS18B20单总线技术:DS18B20采用单条信号线,既可以传输数据,也可以传输时钟。

其数据传输是双向的,这种单总线技术线路简单,硬件开销小,成本低廉,便于总线扩展与维护。

单总线通常需要外接一个4.7K的上拉电阻。

它与处理器的连接非常简单,通常连接方式如下图:DQ端外接一个上拉电阻,与处理器的任一端口连接。

DS18B20工作原理1.ROM功能命令(1)[33H] Read ROM读ROM。

把DS18B20传感器的ROM中编码读出来。

(2)[55H] Match ROM匹配ROM。

发出该命令接着会发送64位包含具体DS18B20序列号的ROM编码,与该编码序列号相同的DS18B20就会做出响应,序列号不匹配的DS18B20继续等待,不做响应。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include<reg51.h>
sbit DQ=P3^0;
unsigned int temp;
unsigned char dis[4]={0,0,0,0};
unsigned char
led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0xff,0xbf};
//分别为0-9,不显示,负号
Unsigned char
led1[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//带小数点显示
void delay(unsigned int i) //如果i是unsigend char类型,则会出现错误结果{
while(i--);
}
void Init(void)//初始化
{
//unsigned char flag=0;
DQ = 0; //单片机将DQ拉低
delay(100); //精确延时大于480us小于960us
DQ = 1; //拉高总线
delay(30);
//flag=DQ; //稍做延时后如果flag=0则初始化成功flag=1则初始化失败//delay(20);
}
unsigned char Read(void)//读字节
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay(5);
}
return(dat);
}
void Write(unsigned char dat)//写字节
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
}
void Display(unsigned int temp) //显示程序
{
if(temp<=0x0800)
{ temp>>=4; //右移4位,相当于乘0.0625,将温度化为十进制temp*=10; //扩大10倍,显示一位小数
dis[0]=temp/1000; //千位
dis[1]=temp%1000/100; //百位
dis[2]=temp%1000%100/10; //十位
dis[3]=temp%1000%100%10; //个位
}
else
{
temp=~temp;
temp+=1;
temp>>=4;
dis[0]=0x0c; //负数
dis[1]=temp%100/10; //百位
dis[2]=temp%100%10; //十位
dis[3]=0; //个位
}
P2=0x01; //先片选,在段选,反过来就不能正常显示
P0=led[dis[0]];
delay(200);
delay(200);
P2=0x02;
P0=led[dis[1]];
delay(200);
delay(200);
P2=0x04;
P0=led1[dis[2]];
delay(200);
delay(200);
P2=0x08;
P0=led[dis[3]];
delay(200);
delay(200);
}
main()
{
unsigned char tl=0,th=0;
while(1)
{
Init();
Write(0xCC); // 跳过读序号列号的操作
Write(0x44); // 启动温度转换
delay(100);
Init();
Write(0xCC); //跳过读序号列号的操作
Write(0xBE); //读取温度寄存器等
delay(100);
tl=Read(); //读取温度值低位
th=Read(); //读取温度值高位
temp=th<<8;
temp|=tl;
Display(temp);
}
}。

相关文档
最新文档