温度传感器可以选用ds18b20
我把电路图发上来了这是程序,希望对你有用
#include reg52.h
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2; //define interface
uint temp; // variable of temperature
uchar flag1; // sign of the result positive or negative
sbit dula=P2^6;
sbit wela=P2^7;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};
void delay(uint count) //delay
{
uint i;
while(count)
{
i=200;
while(i0)
i--;
count--;
}
}
///////功能:串口初始化,波特率9600,方式1///////
void Init_Com(void)
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
void dsreset(void) //send reset and initialization command
{
uint i;
DS=0;
i=103;
while(i0)i--;
DS=1;
i=4;
while(i0)i--;
}
bit tmpreadbit(void) //read a bit
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i0)i--;
return (dat);
}
uchar tmpread(void) //read a byte date
{
uchar i,j,dat;
dat=0;
for(i=1;i=8;i++)
{
j=tmpreadbit();
dat=(j7)|(dat1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j=8;j++)
{
testb=dat0x01;
dat=dat1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i0)i--;
}
else
{
DS=0; //write 0
i=8;while(i0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20 begin change
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // address all drivers on bus
tmpwritebyte(0x44); // initiates a single temperature conversion
}
uint tmp() //get the temperature
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom() //read the serial
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a0;a--)
for(b=60;b0;b--);
}
void display(uint temp) //显示程序
{
uchar A1,A2,A2t,A3,ser;
ser=temp/10;
SBUF=ser;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
A3=A2t%10;
dula=0;
P0=table[A1]; //显示百位
dula=1;
dula=0;
wela=0;
P0=0x7e;
wela=1;
wela=0;
delay(1);
dula=0;
P0=table1[A2]; //显示十位
dula=1;
dula=0;
wela=0;
P0=0x7d;
wela=1;
wela=0;
delay(1);
P0=table[A3]; //显示个位
dula=1;
dula=0;
P0=0x7b;
wela=1;
wela=0;
delay(1);
}
void main()
{
uchar a;
Init_Com();
do
{
tmpchange();
// delay(200);
for(a=10;a0;a--)
{
display(tmp());
}
}while(1);
}
51单片机连接多个数码管,不使用锁存器等附加元件,需要进行扫描来显示。八个数据口,每个数码管再占用一个使能位选。给你一张图片看看。图上的三极管是增加驱动能力的,用普通数码管时可以不加。
18b20是单线的,就是说加个两条电源线,和一条单条数据线(自己选51单片机的一个引脚就可以了)。连接非常简单,但对时序要求非常严格哦,建议你参考几份程序,手边在对照18b20的器件手册来看。
我给你提供方法吧 你自己去实现
一个温度传感器 一个比较器 当你设定的值超过 比较器设定的80度时的值,就输出驱动蜂鸣器工作 就这么简单
汇编语言程序:
;*********************************************************************
;程序适合单个DS18B20和MCS-51单片机的连接,晶振为12MHz
;测量的温度范围-55℃~+99℃,温度精确到小数点后一位
;*********************************************************************
TEMPER_L EQU 30H ;存放从DS18B20中读出的高、低位温度值
TEMPER_H EQU 31H
TEMPER_NUM EQU 32H ;存放温度转换后的整数部分
TEMPER_POT EQU 33H ;存放温度转换后的小数部分
FLAG0 EQU 34H ;FLAG0存放温度的符号
DQ EQU P1.0 ;DS18B20数据线
RS BIT P1.7 ;LCD1602控制线定义
RW BIT P1.6
E BIT P1.5
SkipDs18b20 EQU 0CCH ;DS18B20跳过ROM命令
StartDs18b20 EQU 44H ;DS18B20温度变换命令
ReadDs EQU 0BEH ;DS18B20读暂存器命令
ORG 0000H
SJMP MAIN
ORG 0040H
MAIN:MOV SP,#60H
ACALL LCD_INIT
MOV A,#80H ;lcd第1行第1列开始显示temperature:
ACALL WC51R
MOV A,#'t'
ACALL WC51DDR
MOV A,#'e'
ACALL WC51DDR
MOV A,#'m'
ACALL WC51DDR
MOV A,#'p'
ACALL WC51DDR
MOV A,#'e'
ACALL WC51DDR
MOV A,#'r'
ACALL WC51DDR
MOV A,#'a'
ACALL WC51DDR
MOV A,#'t'
ACALL WC51DDR
MOV A,#'u'
ACALL WC51DDR
MOV A,#'r'
ACALL WC51DDR
MOV A,#'e'
ACALL WC51DDR
MOV A,#':'
ACALL WC51DDR
REP:LCALL GET_TEMPER ;读出转换后的温度值
LCALL TEMPER_COV
MOV A,#0c6H ;lcd第2行第7列开始显示温度
ACALL WC51R
MOV A,FLAG0 ;显示符号
ACALL WC51DDR
MOV A,TEMPER_NUM ;温度整数拆分成十位和个位显示
MOV B,#10
DIV AB
ADD A,#30H
CJNE A,#30H,REP1 ;如果十位为0不显示
MOV A,#20H
REP1:ACALL WC51DDR
MOV A,B
ADD A,#30H
ACALL WC51DDR
MOV A,#'.' ;显示小数点
ACALL WC51DDR
MOV DPTR,#TABLE
MOV A,TEMPER_POT ;显示小数部分
MOVC A,@A+DPTR
ACALL WC51DDR
LJMP REP
;DS18B20复位程序
DS18B20_INIT:SETB DQ
NOP
NOP
CLR DQ
MOV R7,#9
INIT_DELAY: CALL DELAY60US
DJNZ R7,INIT_DELAY
SETB DQ
CALL DELAY60US
CALL DELAY60US
MOV C,DQ
JC ERROR
CALL DELAY60US
CALL DELAY60US
CALL DELAY60US
CALL DELAY60US
RET
ERROR:CLR DQ
SJMP DS18B20_INIT
RET
;读DS18B20一个字节到累加器A程序
READ_BYTE: MOV R7,#08H
SETB DQ
NOP
NOP
LOOP:CLR DQ
NOP
NOP
NOP
SETB DQ
MOV R6,#07H
DJNZ R6,$
MOV C,DQ
CALL DELAY60US
RRC A
SETB DQ
DJNZ R7,LOOP
CALL DELAY60US
CALL DELAY60US
RET
;累加器A写到DS18B20程序
WRITE_BYTE: MOV R7,#08H
SETB DQ
NOP
NOP
LOOP1:CLR DQ
MOV R6,#07H
DJNZ R6,$
RRC A
MOV DQ,C
CALL DELAY60US
SETB DQ
DJNZ R7,LOOP1
RET
DELAY60US:MOV R6,#1EH
DJNZ R6,$
RET
;读温度程序
GET_TEMPER: CALL DS18B20_INIT ;DS18B20复位程序
MOV A,#0CCH ;DS18B20跳过ROM命令
CALL WRITE_BYTE
CALL DELAY60US
CALL DELAY60US
MOV A,#44H ;DS18B20温度变换命令
CALL WRITE_BYTE
CALL DELAY60US
CALL DS18B20_INIT ;DS18B20复位程序
MOV A,#0CCH ;DS18B20跳过ROM命令
CALL WRITE_BYTE
CALL DELAY60US
MOV A,#0BEH ;DS18B20读暂存器命令
CALL WRITE_BYTE
CALL DELAY60US
CALL READ_BYTE ;读温度低字节
MOV TEMPER_L,A
CALL READ_BYTE ;读温度高字节
MOV TEMPER_H,A
RET
;将从DS18B20中读出的温度拆分成整数和小数
TEMPER_COV:
MOV FLAG0,#'+' ;设当前温度为正
MOV A,TEMPER_H
SUBB A,#0F8H
JC TEM0 ;看温度值是否为负?不是,转
MOV FLAG0,#'-' ;是,置FLAG0为'-'
MOV A,TEMPER_L
CPL A
ADD A,#01
MOV TEMPER_L,A
MOV A,TEMPER_H
CPL A
ADDC A,#00
MOV TEMPER_H,A
TEM0:
MOV A,TEMPER_L ;存放小数部分到TEMPER_POT
ANL A,#0FH
MOV TEMPER_POT,A
MOV A,TEMPER_L ;存放小数部分到TEMPER_NUM
ANL A,#0F0H
SWAP A
MOV TEMPER_NUM,A
MOV A,TEMPER_H
SWAP A
ORL A,TEMPER_NUM
MOV TEMPER_NUM,A
RET
;LCD初始化子程序
LCD_INIT:MOV A,#00000001H ;清屏
ACALL WC51R
MOV A,#00111000B ;使用8位数据,显示两行,使用5×7的字型
LCALL WC51R
MOV A,#00001100B ;显示器开,光标关,字符不闪烁
LCALL WC51R
MOV A,#00000110B ;字符不动,光标自动右移一格
LCALL WC51R
RET
;检查忙子程序
F_BUSY:PUSH ACC ;保护现场
MOV P2,#0FFH
CLR RS
SETB RW
WAIT: CLR E
SETB E
JB P2.7,WAIT ;忙,等待
POP ACC ;不忙,恢复现场
RET
;写入命令子程序
WC51R: ACALL F_BUSY
CLR E
CLR RS
CLR RW
SETB E
MOV P2,ACC
CLR E
RET
;写入数据子程序
WC51DDR:ACALL F_BUSY
CLR E
SETB RS
CLR RW
SETB E
MOV P2,ACC
CLR E
RET
TABLE: DB 30H,31H,31H,32H,33H,33H,34H,34H
DB 35H,36H,36H,37H,38H,38H,39H,39H ;小数温度转换表
END
C语言程序:
//程序适合单个DS18B20和MCS-51单片机的连接,晶振为12MHz
//测量的温度范围-55℃~+99℃,温度精确到小数点后一位
#include REG52.H
#define uchar unsigned char
#define uint unsigned int
sbit DQ =P1^0; //定义端口
sbit RS=P1^7;
sbit RW=P1^6;
sbit EN=P1^5;
union{
uchar c[2];
uint x;
}temp;
uchar flag;//flag为温度值的正负号标志单元, "1"表示为负值,"0"时表示为正值。
uint cc,cc2;//变量cc中保存读出的温度值
float cc1;
uchar buff1[13]={"temperature:"};
uchar buff2[6]={"+00.0"};
//检查忙函数
void fbusy()
{
P2 = 0xff;
RS = 0;
RW = 1;
EN = 1;
EN = 0;
while((P2 0x80))
{
EN = 0;
EN = 1;
}
}
//写命令函数
void wc51r(uchar j)
{
fbusy();
EN = 0;
RS = 0;
RW = 0;
EN = 1;
P2 = j;
EN = 0;
}
//写数据函数
void wc51ddr(uchar j)
{
fbusy(); //读状态;
EN = 0;
RS = 1;
RW = 0;
EN = 1;
P2 = j;
EN = 0;
}
void init()
{
wc51r(0x01); //清屏
wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型
wc51r(0x0c); //显示器开,光标开,字符不闪烁
wc51r(0x06); //字符不动,光标自动右移一格
}
void delay(uint useconds) //延时程序
{
for(;useconds0;useconds--);
}
uchar ow_reset(void) //复位
{
uchar presence;
DQ = 0; // DQ 低电平
delay(50); // 480ms
DQ = 1; // DQ 高电平
delay(3); // 等待
presence = DQ; // presence 信号
delay(25);
return(presence); // 0允许, 1禁止
}
uchar read_byte(void) //从单总线上读取一个字节
{
uchar i;
uchar value = 0;
for (i=8;i0;i--)
{
value=1;
DQ = 0;
DQ = 1;
delay(1);
if(DQ)value|=0x80;
delay(6);
}
return(value);
}
void write_byte(uchar val) //向单总线上写一个字节
{
uchar i;
for (i=8; i0; i--) // 一次写一字节
{
DQ = 0;
DQ = val0x01;
delay(5);
DQ = 1;
val=val/2;
}
delay(5);
}
void Read_Temperature(void) //读取温度
{
ow_reset();
write_byte(0xCC); // 跳过 ROM
write_byte(0xBE); // 读
temp.c[1]=read_byte();
temp.c[0]=read_byte();
ow_reset();
write_byte(0xCC);
write_byte(0x44); // 开始
return;
}
void main() //主程序
{
uchar k;
delay(10);
EA=0;
flag=0;
init();
wc51r(0x80); //写入显示缓冲区起始地址为第1行第1列
for (k=0;k13;k++) //第一行显示提示信息"current temp is:"
{ wc51ddr(buff1[k]);}
while(1)
{
delay(10000);
Read_Temperature(); //读取双字节温度
cc=temp.c[0]*256.0+temp.c[1];
if (temp.c[0]0xf8) {flag=1;cc=~cc+1;}else flag=0;
cc1=cc*0.0625; //计算出温度值
cc2=cc1*100; //放大100倍,放在整型变量中便于取数字
buff2[1]=cc2/1000+0x30;if ( buff2[1]==0x30) buff2[1]=0x20;//取出十位,转换成字符,如果十位是0不显示。
buff2[2]=cc2/100-(cc2/1000)*10+0x30;//取出个位,转换成字符
buff2[4]=cc2/10-(cc2/100)*10+0x30;//取出小数点后一位,转换成字符
if (flag==1) buff2[0]='-';else buff2[0]='+';
wc51r(0xc5); //写入显示缓冲区起始地址为第2行第6列
for (k=0;k6;k++) //第二行显示温度
{ wc51ddr(buff2[k]);}
}
}
明显调用函数出错了,writedata的入参又不是指针,你给一堆的字符串有什么用?
下面入参是数组里面的每一个元素,这个用对了,可是你知道ASCII和十进制数据的区别么?
知道数据3要在1602上显示字符'3'是要加0x30么?
所以你的要这么改writedata( tempbuf[q] + 0x30 );
找不到你自己的原因,给你对的,你永远也不会知道自己为什么出错
1、单片机热敏电阻测温首先要设计电路原理图,如图所示:
上图R3为上拉电阻,T1为接热敏电阻端,TC1为单片机AD采集口、电阻R4和电热C6为阻容滤波电路。
2、上拉电阻R3的选择:根据所用温度的范围,选择热敏电阻对应阻值范围的中间值最好,这样检测的温度偏差较小。
3、上拉电阻选定后,根据热敏电阻阻值表,算出温度真值表,用于软件查表,计算出温度值。在算温度真值表前,首先要确定单片机AD模块的分辨率。
4、单片机软件编程,滤波方法一般采用多次采集求累加和,去最大值和最小值,最后求平均。
5、单片机选择:一般选用8位单片机就够。但是,单片机自带的温度采集AD模块,最好选用10位分辨率,10位的AD模块分辨率高,温度采集精确。
6、以上为单片机热敏电阻测温的一般流程。
测量温度单片机电路图的介绍到此就结束了,感谢您耐心阅读,谢谢。
本文标签:测量温度单片机电路图