通常,LM35温度传感器与微控制器一起使用以测量温度,因为它便宜且易于获得。但是 LM35 给出了模拟值,我们需要使用 ADC(模数转换器)将它们转换为数字值。但今天我们使用DS18B20温度传感器,不需要ADC转换即可获得温度。在这里,我们将使用带有DS18B20的PIC微控制器来测量温度。
因此,在这里,我们使用微芯片的PIC16F877A微控制器单元构建具有以下规格的温度计。
它将显示从 -55 度到 +125 度的全温度范围。
仅当温度变化 + / - .2 度时,它才会显示温度。
所需组件:-
Pic16F877A – PDIP40 封装
面包板
皮基特-3
5V 适配器
液晶显示器 JHD162A
DS18b20 温度传感器
用于连接外围设备的电线。
4.7k 电阻器 – 2 个
10k锅
20mHz 晶体
2 个 33pF 陶瓷电容器
DS18B20温度传感器:
DS18B20是一款出色的传感器,可准确检测温度。该传感器提供 9 位至 12 位的温度检测分辨率。该传感器仅与一根导线通信,不需要任何ADC即可获取模拟温度并将其转换为数字温度。
传感器的规格是:-
测量温度范围为 -55°C 至 +125°C(-67°F 至 +257°F)
-10°C 至 +85°C 范围内精度为 ±0.5°C
可编程分辨率从 9 位到 12 位
无需外部组件
传感器采用1-Wire®接口
如果我们查看数据表中的上述引脚排列图像,我们可以看到传感器看起来与 BC547 或 BC557 封装 TO-92 完全相同。第一个引脚是接地,第二个引脚是DQ或数据,第三个引脚是VCC。
以下是数据表中的电气规格,这是我们设计所需的。传感器的额定电源电压为+3.0V至+5.5V。它还需要上拉电源电压,该电压与上述电源电压相同。
此外,对于 -10 摄氏度到 +10 摄氏度的范围,精度裕度为 +-0.5 摄氏度,全范围裕度的精度会发生变化,对于 -55 度到 +125 度范围,精度裕度为 +-2 度。
如果我们再次查看数据表,我们将看到传感器的连接规格。我们可以在需要两根电线(DATA 和 GND)的寄生电源模式下连接传感器,或者可以使用外部电源连接传感器,其中需要三根单独的电线。我们将使用第二种配置。
由于我们现在熟悉传感器和连接相关区域的额定功率,我们现在可以专注于制作原理图。
电路图:-
如果我们看到电路图,我们将看到:-
16x2字符LCD通过PIC16F877A微控制器连接,其中RB0,RB1,RB2连接到LCD引脚RS,R/W和E。RB4、RB5、RB6 和 RB7 通过 LCD 的 4 针 D4、D5、D6、D7 连接。液晶屏以4位模式或半字节模式连接。
一个 20MHz 晶体振荡器和两个 33pF 陶瓷电容器连接在 OSC1 和 OSC2 引脚上。它将为微控制器提供恒定的20Mhz时钟频率。
DS18B20也按照引脚配置连接,如前所述,采用4.7k上拉电阻连接。我已经在面包板上连接了所有这些。
如果您不熟悉 PIC 微控制器,请按照我们的 PIC 微控制器教程进行操作,说明 PIC 微控制器入门。
步骤或代码流:-
设置微控制器的配置,包括振荡器配置。
设置LCD的所需端口,包括TRIS寄存器。
使用ds18b20传感器的每个周期都以复位开始,因此我们将复位ds18b20并等待存在脉冲。
编写暂存器并将传感器的分辨率设置为 12 位。
跳过ROM读取,然后跳过复位脉冲。
提交转换温度命令。
从暂存器读取温度。
检查温度值是负值还是正值。
在 16x2 LCD 上打印温度。
等待温度变化 +/-.20 摄氏度。
代码说明:
本教程末尾提供了此数字温度计的完整代码,并附有演示视频。您将需要一些头文件来运行该程序,可以从此处下载。
首先,我们需要在 pic 微控制器中设置配置位,然后从 void main 函数开始。
然后下面四行用于包括库头文件,lcd.h和ds18b20.h。 xc.h 用于微控制器头文件。
#include
#include
#include "supporting c files/ds18b20.h"
#include "supporting c files/lcd.h"
这些定义用于向温度传感器发送命令。这些命令列在传感器的数据表中。
#define skip_rom 0xCC
#define convert_temp 0x44
#define write_scratchpad 0x4E
#define resolution_12bit 0x7F
#define read_scratchpad 0xBE
传感器数据表中的表 3 显示了使用宏发送相应命令的所有命令。
仅当温度变化 +/- .20 度时,温度才会显示在屏幕上。我们可以从这个temp_gap宏观上改变这个温差。通过更改此宏中的值,规范将更改。
另外两个浮点变量用于存储显示的温度数据,并用温差区分它们
#define temp_gap 20
float pre_val=0, aft_val=0;
.
在void main()函数中,lcd_init();是一个初始化LCD的函数。此 lcd_init() 函数是从 lcd.h 库中调用的。
TRIS 寄存器用于选择 I/O 引脚作为输入或输出。两个无符号短变量 TempL 和 TempH 用于存储来自温度传感器的 12 位分辨率数据。
void main(void) {
TRISD = 0xFF;
TRISA = 0x00;
TRISB = 0x00;
//TRISDbits_t.TRISD6 = 1;
unsigned short TempL, TempH;
unsigned int t, t2;
float difference1=0, difference2=0;
lcd_init();
让我们看看 while 循环,这里我们将 while(1) 循环分解成小块。
这些线用于检测温度传感器是否连接。
while(ow_reset()){
lcd_com(0x80);
lcd_puts ("Please Connect ");
lcd_com (0xC0);
lcd_puts("Temp-Sense Probe");
}
通过使用这段代码,我们初始化传感器并发送命令来转换温度。
lcd_puts (" ");
ow_reset();
write_byte(write_scratchpad);
write_byte(0);
write_byte(0);
write_byte(resolution_12bit); // 12bit resolution
ow_reset();
write_byte(skip_rom);
write_byte(convert_temp);
此代码用于将 12 位温度数据存储在两个无符号短变量中。
while (read_byte()==0xff);
__delay_ms(500);
ow_reset();
write_byte(skip_rom);
write_byte(read_scratchpad);
TempL = read_byte();
TempH = read_byte();
然后,如果您检查下面的完整代码,我们将创建if-else条件来找出温度符号是正数还是负数。
通过使用 If 语句代码,我们操作数据并查看温度是否为负,并确定温度变化是否在 +/- .20 度范围内。在其他地方,我们检查温度是否为正和温度变化检测。
从DS18B20温度传感器获取数据:
让我们看看1-Wire®接口的时差。我们正在使用20Mhz晶体。如果我们查看 ds18b20.c 文件,我们会看到
#define _XTAL_FREQ 20000000
此定义用于 XC8 编译器延迟例程。20Mhz设置为晶体频率。
我们制作了五个功能
ow_reset
read_bit
read_byte
write_bit
write_byte
1-Wire协议需要严格的时序相关插槽进行通信。在数据表中,我们将获得完美的时隙相关信息。®
在下面的函数中,我们创建了确切的时间段。为保持和释放创建确切的延迟并控制相应传感器端口的TRIS位非常重要。
unsigned char ow_reset(void)
{
DQ_TRIS = 0; // Tris = 0 (output)
DQ = 0; // set pin# to low (0)
__delay_us(480); // 1 wire require time delay
DQ_TRIS = 1; // Tris = 1 (input)
__delay_us(60); // 1 wire require time delay
if (DQ == 0) // if there is a presence pluse
{
__delay_us(480);
return 0; // return 0 ( 1-wire is presence)
}
else
{
__delay_us(480);
return 1; // return 1 ( 1-wire is NOT presence)
}
} // 0=presence, 1 = no part
现在,根据以下读取和写入中使用的时隙描述,我们分别创建了读取和写入函数。
unsigned char read_bit(void)
{
unsigned char i;
DQ_TRIS = 1;
DQ = 0; // pull DQ low to start timeslot
DQ_TRIS = 1;
DQ = 1; // then return high
for (i=0; i<3; i++); // delay 15us from start of timeslot
return(DQ); // return value of DQ line
}
void write_bit(char bitval)
{
DQ_TRIS = 0;
DQ = 0; // pull DQ low to start timeslot
if(bitval==1) DQ =1; // return DQ high if write 1
__delay_us(5); // hold value for remainder of timeslot
DQ_TRIS = 1;
DQ = 1;
}// Delay provides 16us per loop, plus 24us. Therefore delay(5) = 104us
这就是我们如何利用DS18B20传感器通过PIC微控制器获得温度。
/*
* File: main.c
* Author: Sourav Gupta
*
* Created on 11 April 2018, 17:57
*/
/*
* Configuration Related settings. Specific for microcontroller unit.
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 20000000
/*
* System Header files inclusions
*/
#include
#include
#include "supporting c files/ds18b20.h"
#include "supporting c files/lcd.h"
/*
* Ds18b20 related definition
*/
#define skip_rom 0xCC
#define convert_temp 0x44
#define write_scratchpad 0x4E
#define resolution_12bit 0x7F
#define read_scratchpad 0xBE
/*
* User interface related definitions
*/
#define temp_gap 20
float pre_val=0, aft_val=0;
/*
* Program flow related functions
*/
void sw_delayms(unsigned int d);
/* Main function / single Thread*/
void main(void) {
TRISD = 0xFF;
TRISA = 0x00;
TRISB = 0x00;
//TRISDbits_t.TRISD6 = 1;
unsigned short TempL, TempH;
unsigned int t, t2;
float difference1=0, difference2=0;
lcd_init();
while(1){
float i=0;
/* This is for presence detection of temp-sensing probe*/
while(ow_reset()){
lcd_com(0x80);
lcd_puts ("Please Connect ");
lcd_com (0xC0);
lcd_puts("Temp-Sense Probe");
}
/*------------------------------------------------------*/
lcd_puts (" ");
ow_reset();
write_byte(write_scratchpad);
write_byte(0);
write_byte(0);
write_byte(resolution_12bit); // 12bit resolution
ow_reset();
write_byte(skip_rom);
write_byte(convert_temp);
while (read_byte()==0xff);
__delay_ms(500);
ow_reset();
write_byte(skip_rom);
write_byte(read_scratchpad);
TempL = read_byte();
TempH = read_byte();
/*This is for Negative temperature*/
/*If result (TempH [Bitwise and] 1000 0000) = not 0
*then this condition get true.
case1. -0.5 degree value = 1111 1111. [1111 1111 & 1000 0000 = 1000 0000 which is not 0.]
case2. -55 degree value = 1111 1100. [1111 1100 & 1000 0000 = 1000 0000 which is not 0]
0x80 = 1000 0000
Test Case -10.125 output 1111 1111 0101 1110*/
if((TempH & 0x80)!=0){ // If condition will execute as TempH = 1111 1111 & 1000 0000 = 1000 0000.
t=TempH;// Store tempH value in t = 1111 1111 .
t<<=8;//after bitwise left shift 8 times value in t will be 1111 1111 0000 0000.
t=t|TempL;// t = 1111 1111 0000 0000 | 0101 1110 [ result t = 1111 1111 0101 1110]
t=t-1;//t = t-1 in this case t = 1111 1111 0101 1101.
t=~t;// t = 0000 0000 1010 0010.
t>>=4;// t = 0000 0000 0000 1010.
t=t*100;// t = 10 * 100 = 1000.
t2=TempL; //Store tempL value = 0101 1110.
t2=t2-1;// t2= 0101 1101
t2=~t2;//t2 = 1010 0010
t2=t2&0x0f;// t2 = 1010 0010 | 0000 1111 = 0000 0010
t2=t2 * 6.25; // 0000 00010 = 2 x 6.25 = 12.50
i=((unsigned int)t ) + (unsigned int)t2; //put both value in one variable 1000 + 12.5 = 1012.5
/*This if-else condition done because LCD would not refresh till temperature change -.20 or +.20 degree*/
pre_val=aft_val;
difference1 = pre_val - i;
difference2 = i - pre_val;
if(difference1 > temp_gap || difference2 > temp_gap){
aft_val = i;
lcd_com (0x80);
lcd_puts ("Circuit Digest");
lcd_com (0xc0);
lcd_puts("-");
lcd_bcd (5,aft_val);
lcd_data(223);
lcd_puts("C ");
}
else{
lcd_com (0x80);
lcd_puts ("Circuit Digest");
lcd_com (0xc0);
lcd_puts("-");
lcd_bcd (5,pre_val);
lcd_data(223);
lcd_puts("C ");
}
}
/*This is for positive Temperature*/
else {
i=((unsigned int)TempH << 8 ) + (unsigned int)TempL; //put both value in one variable
i = i * 6.25; //calculations used from the table provided in the data sheet of ds18b20
/*This if-else condition done because LCD would not refresh till temperature change -.20 or +.20 degree*/
pre_val=aft_val;
difference1 = pre_val - i;
difference2 = i - pre_val;
if(difference1 > temp_gap || difference2 > temp_gap){
aft_val = i;
lcd_com (0x80);
lcd_puts ("Circuit Digest");
lcd_com (0xc0);
lcd_bcd (5,aft_val);
lcd_data(223);
lcd_puts("C ");
}
else{
lcd_com (0x80);
lcd_puts ("Circuit Digest");
lcd_com (0xc0);
lcd_bcd (5,pre_val);
lcd_data(223);
lcd_puts("C ");
}
}
}
return;
}
void sw_delayms(unsigned int d){
int x, y;
for(x=0;x
for(y=0;y<=1275;y++);
}
全部0条评论
快来发表一下你的评论吧 !