求基于AT89C51单片机和DS18B20温度传感器和HS1101湿度传感器、Led显示的温湿度检测系统的汇编源程序代码
1个回答
展开全部
A_BIT EQU 20H
B_BIT EQU 21H
FLAG EQU 38H
DQ EQU P3.3
MAIN:
ACALL RE_TEMP
ACALL TURN
ACALL DISPLAY
JMP MAIN
RE_TEMP:
SETB DQ
ACALL RESET_1820
JB FLAG,ST
ST:
MOV A,#0CCH
ACALL WRITE_1820
MOV A,#44H
ACALL WRITE_1820
ACALL RESET_1820
MOV A,#0CCH
ACALL WRITE_1820
MOV A,#0BEH
ACALL WRITE_1820
ACALL READ_1820
RET
RESET_1820:
SETB DQ
NOP
CLR DQ
MOV R1,#3
DLY: MOV R0,#107
DJNZ R0,$
DJNZ R1,DLY
SETB DQ
NOP
NOP
NOP
MOV R0,#25
T2: JNB DQ,T3
DJNZ R0,T2
JMP T4
T3: SETB FLAG
JMP T5
T4: CLR FLAG
JMP T7
T5: MOV R0,#117
DJNZ R0,$
T7: SETB DQ
RET
WRITE_1820:
MOV R2,#8
CLR C
WR1: CLR DQ
MOV R3,#7
DJNZ R3,$
RRC A
MOV DQ,C
MOV R3,#23
DJNZ R3,$
SETB DQ
NOP
DJNZ R2,WR1
SETB DQ
RET
READ_1820:
MOV R4,#2
MOV R1,#29H
RE0: MOV R2,#8
RE1: CLR C
SETB DQ
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R3,#9
RE2: DJNZ R3,RE2
MOV C,DQ
MOV R3,#23
RE3: DJNZ R3,RE3
RRC A
DJNZ R2,RE1
MOV @R1,A
DEC R1
DJNZ R4,RE0
RET
TURN: MOV A,29H
MOV C,40H
RRC A
MOV C,41H
RRC A
MOV C,42H
RRC A
MOV C,43H
RRC A
MOV 29H,A
DISPLAY:
MOV A,29H
MOV B,#10
DIV AB
MOV B_BIT,A
MOV A_BIT,B
MOV R0,#4
DP1: MOV R1,#250
LOOP: MOV DPTR,#TABLE
MOV A,A_BIT
MOVC A,@A+DPTR
MOV P2,A
MOV P1,#0F7H
ACALL DELAY
MOV A,B_BIT
MOVC A,@A+DPTR
MOV P2,A
MOV P1,#0F6H
ACALL DELAY
DJNZ R1,LOOP
DJNZ R0,DP1
RET
DELAY:
MOV R7,#122
DJNZ R7,$
RET
TABLE:
DB 3FH,06H,5BH,4FH
DB 66H,6DH,7DH,07H,7FH
END
这个程序是DS18B20检测温度后,通过单片机驱动数码管显示,也就是你要求的LED显示。至于HS1101也特别简单我就不写了,我是无意中看到你的问题的,正好我以前也写过这个,我就回答了。我做单片机开发已经很多年了,针对这个程序给你几个建议:1用C语言写,简单、直观、可移植性好。2把DS18B20先搞出来,然后再把HS1101搞出来,然后整合。(当然,我已经给你了DS18B20的程序了)。顺便给你把C语言的也贴出来吧:#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P3^3; //定义DS18B20接口
int temp;
uchar flag1;
void display(unsigned char *lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数
void delay();//延时子函数,5个空指令
code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x08,0x00};
//共阴数码管 0-9 - _ 空 表
unsigned char l_tmpdate[8]={0,0,10,0,0,0,0,0};//定义数组变量,并赋值1,2,3,4,5,6,7,8,就是本程序显示的八个数
int tmp(void);
void tmpchange(void);
void tmpwritebyte(uchar dat);
uchar tmpread(void);
bit tmpreadbit(void);
void dsreset(void);
void delayb(uint count);
void main() //主函数
{
uchar i;
int l_tmp;
while(1)
{
tmpchange(); //温度转换
l_tmp=tmp();
if(l_tmp<0)
l_tmpdate[0]=10; //判断温度为负温度,前面加"-"
else
{
l_tmpdate[0]=temp/1000; //显示百位,这里用1000,是因为我们之前乖以10位了
if(l_tmpdate[0]==0)
l_tmpdate[0]=12;//判断温度为正温度且没有上百,前面不显示
}
l_tmp=temp%1000;
l_tmpdate[1]=l_tmp/100;//获取十位
l_tmp=l_tmp%100;
l_tmpdate[2]=l_tmp/10;//获取个位
l_tmpdate[3]=11;
l_tmpdate[4]=l_tmp%10;//获取小数第一位
for(i=0;i<10;i++){ //循环输出10次,提高亮度
display(l_tmpdate,5);
}
}
}
void display(unsigned char *lp,unsigned char lc)//显示
{
unsigned char i; //定义变量
P2=0; //端口2为输出
P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管
for(i=0;i<lc;i++){ //循环显示
P2=table[lp[i]]; //查表法得到要显示数字的数码段
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay(); //延时5个空指令
if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据
break;
P2=0; //清0端口,准备显示下位
P1++; //下一位数码管
}
}
void delay(void) //空5个指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
void delayb(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void) //DS18B20初始化
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) // 读一位
{
uint i;
bit dat;
DS=0;i++; //小延时一下
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void tmpwritebyte(uchar dat)
{ //写一个字节到DS18B20里
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; //写0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //发送温度转换命令
{
dsreset(); //初始化DS18B20
delayb(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}
int tmp() //获得温度
{
float tt;
uchar a,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp<<=8;
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20
//可以精确到0.0625度,所以读回数据的最低位代表的是
//0.0625度。
temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位
//也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
void readrom() //read the serial 读取温度传感器的序列号
{ //本程序中没有用到此函数
uchar sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms()
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
B_BIT EQU 21H
FLAG EQU 38H
DQ EQU P3.3
MAIN:
ACALL RE_TEMP
ACALL TURN
ACALL DISPLAY
JMP MAIN
RE_TEMP:
SETB DQ
ACALL RESET_1820
JB FLAG,ST
ST:
MOV A,#0CCH
ACALL WRITE_1820
MOV A,#44H
ACALL WRITE_1820
ACALL RESET_1820
MOV A,#0CCH
ACALL WRITE_1820
MOV A,#0BEH
ACALL WRITE_1820
ACALL READ_1820
RET
RESET_1820:
SETB DQ
NOP
CLR DQ
MOV R1,#3
DLY: MOV R0,#107
DJNZ R0,$
DJNZ R1,DLY
SETB DQ
NOP
NOP
NOP
MOV R0,#25
T2: JNB DQ,T3
DJNZ R0,T2
JMP T4
T3: SETB FLAG
JMP T5
T4: CLR FLAG
JMP T7
T5: MOV R0,#117
DJNZ R0,$
T7: SETB DQ
RET
WRITE_1820:
MOV R2,#8
CLR C
WR1: CLR DQ
MOV R3,#7
DJNZ R3,$
RRC A
MOV DQ,C
MOV R3,#23
DJNZ R3,$
SETB DQ
NOP
DJNZ R2,WR1
SETB DQ
RET
READ_1820:
MOV R4,#2
MOV R1,#29H
RE0: MOV R2,#8
RE1: CLR C
SETB DQ
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R3,#9
RE2: DJNZ R3,RE2
MOV C,DQ
MOV R3,#23
RE3: DJNZ R3,RE3
RRC A
DJNZ R2,RE1
MOV @R1,A
DEC R1
DJNZ R4,RE0
RET
TURN: MOV A,29H
MOV C,40H
RRC A
MOV C,41H
RRC A
MOV C,42H
RRC A
MOV C,43H
RRC A
MOV 29H,A
DISPLAY:
MOV A,29H
MOV B,#10
DIV AB
MOV B_BIT,A
MOV A_BIT,B
MOV R0,#4
DP1: MOV R1,#250
LOOP: MOV DPTR,#TABLE
MOV A,A_BIT
MOVC A,@A+DPTR
MOV P2,A
MOV P1,#0F7H
ACALL DELAY
MOV A,B_BIT
MOVC A,@A+DPTR
MOV P2,A
MOV P1,#0F6H
ACALL DELAY
DJNZ R1,LOOP
DJNZ R0,DP1
RET
DELAY:
MOV R7,#122
DJNZ R7,$
RET
TABLE:
DB 3FH,06H,5BH,4FH
DB 66H,6DH,7DH,07H,7FH
END
这个程序是DS18B20检测温度后,通过单片机驱动数码管显示,也就是你要求的LED显示。至于HS1101也特别简单我就不写了,我是无意中看到你的问题的,正好我以前也写过这个,我就回答了。我做单片机开发已经很多年了,针对这个程序给你几个建议:1用C语言写,简单、直观、可移植性好。2把DS18B20先搞出来,然后再把HS1101搞出来,然后整合。(当然,我已经给你了DS18B20的程序了)。顺便给你把C语言的也贴出来吧:#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P3^3; //定义DS18B20接口
int temp;
uchar flag1;
void display(unsigned char *lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数
void delay();//延时子函数,5个空指令
code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x08,0x00};
//共阴数码管 0-9 - _ 空 表
unsigned char l_tmpdate[8]={0,0,10,0,0,0,0,0};//定义数组变量,并赋值1,2,3,4,5,6,7,8,就是本程序显示的八个数
int tmp(void);
void tmpchange(void);
void tmpwritebyte(uchar dat);
uchar tmpread(void);
bit tmpreadbit(void);
void dsreset(void);
void delayb(uint count);
void main() //主函数
{
uchar i;
int l_tmp;
while(1)
{
tmpchange(); //温度转换
l_tmp=tmp();
if(l_tmp<0)
l_tmpdate[0]=10; //判断温度为负温度,前面加"-"
else
{
l_tmpdate[0]=temp/1000; //显示百位,这里用1000,是因为我们之前乖以10位了
if(l_tmpdate[0]==0)
l_tmpdate[0]=12;//判断温度为正温度且没有上百,前面不显示
}
l_tmp=temp%1000;
l_tmpdate[1]=l_tmp/100;//获取十位
l_tmp=l_tmp%100;
l_tmpdate[2]=l_tmp/10;//获取个位
l_tmpdate[3]=11;
l_tmpdate[4]=l_tmp%10;//获取小数第一位
for(i=0;i<10;i++){ //循环输出10次,提高亮度
display(l_tmpdate,5);
}
}
}
void display(unsigned char *lp,unsigned char lc)//显示
{
unsigned char i; //定义变量
P2=0; //端口2为输出
P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管
for(i=0;i<lc;i++){ //循环显示
P2=table[lp[i]]; //查表法得到要显示数字的数码段
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay();
delay(); //延时5个空指令
if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据
break;
P2=0; //清0端口,准备显示下位
P1++; //下一位数码管
}
}
void delay(void) //空5个指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
void delayb(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void) //DS18B20初始化
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) // 读一位
{
uint i;
bit dat;
DS=0;i++; //小延时一下
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //读一个字节
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
}
return(dat); //将一个字节数据返回
}
void tmpwritebyte(uchar dat)
{ //写一个字节到DS18B20里
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; //写0部分
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //发送温度转换命令
{
dsreset(); //初始化DS18B20
delayb(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}
int tmp() //获得温度
{
float tt;
uchar a,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp<<=8;
temp=temp|a; //两字节合成一个整型变量。
tt=temp*0.0625; //得到真实十进制温度值,因为DS18B20
//可以精确到0.0625度,所以读回数据的最低位代表的是
//0.0625度。
temp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位
//也转换为可显示数字,同时进行一个四舍五入操作。
return temp; //返回温度值
}
void readrom() //read the serial 读取温度传感器的序列号
{ //本程序中没有用到此函数
uchar sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms()
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询