赞
踩
本案例讲解如何从18B20传感器获取温度信息并显示在LCD上。
可以看到18B20有两根引脚负责供电,一根引脚负责数据交换。18B20就是通过数据线和单片机进行数据交换的。
1)18B20工作时序
2)初始化信号
#define DQ P44 /** * @brief 初始化方法 * * @return 1代表存在,0代表不存在 */ static bit Int_DS18B20_Init() { bit result; // 主机拉低 DQ = 0; Delay60us(8); // 主机释放DQ DQ = 1; Delay60us(1); // 查看18B20状态 result = ~DQ; Delay60us(7); return result; }
3)写数据时序
写‘1’时序
写‘0’时序
写字节
让18B20测量温度,并将温度保存在RAM中。
根据说明书第五节“温度测量”,我们需要向18B20发送功能指令0x44,可以触发温度测量动作,根据上面的事件序列,我们可以得知,这一步的通信流程如下:
发送初始化信号。
发送跳过ROM命令的指令(因为我们不需要ROM命令),查询ROM命令列表可得知,我们需要向18B20发送0xCC。
发送温度测量指令,查询功能命令列表可得知,我们需要向18B20发送0x44。
4)读数据时序
5)从18B20中读取刚刚测量的温度。
查询说明书的命令指令可得知,如果我们想读取18B20寄存器,需要向18B20发送功能指令0xBE,再从18B20中连续接收9字节数据。这9字节数据中,只有前两个字节是我们需要的温度数据。所以我们在接收两个字节后,需要再发送一次复位(初始化)信号,打断接下来的数据传输。整个通信流程如下:
发送初始化信号。
发送跳过ROM命令的指令0xCC。
发送读取寄存器的命令0xBE。
接收两个字节。
发送初始化信号打断传输。
1)Util.h
在Util.h中加入新的延时函数声明。
/** * @brief 延时10us * */ void Delay10us(); /** * @brief 延时50us * */ void Delay50us(); /** * @brief 延时60us * * @param n 倍数 */ void Delay60us(u8 n);
2)Util.c
void Delay60us(u8 n) //@11.0592MHz { unsigned char data i; while (n--) { i = 25; while (--i) ; } } void Delay10us() //@11.0592MHz { unsigned char data i; i = 2; while (--i) ; } void Delay50us() //@11.0592MHz { unsigned char data i; _nop_(); i = 20; while (--i) ; }
3)Int_DS18B20.h
在Int目录下创建Int_DS18B20.h,写入以下内容。
#ifndef __INT_DS18B20_H__
#define __INT_DS18B20_H__
#include <STC89C5xRC.H>
#include "Util.h"
/**
* @brief 获取温度
*
* @return u8
*/
u8 Int_DS18B20_GetTemperature();
#endif
4)Int_DS18B20.c
在Int目录下创建Int_DS18B20.c,写入以下内容。
#include "Int_DS18B20.h" #define DQ P44 /** * @brief 初始化方法 * * @return 1代表存在,0代表不存在 */ static bit Int_DS18B20_Init() { bit result; // 主机拉低 DQ = 0; Delay60us(8); // 主机释放DQ DQ = 1; Delay60us(1); // 查看18B20状态 result = ~DQ; Delay60us(7); return result; } /** * @brief 向18B20发送字节 * * @param dat 要发送的字节 */ static void Int_DS18B20_SendByte(u8 dat) { u8 i; for (i = 0; i < 8; i++) { // 首先拉低总线 DQ = 0; // 延时10us Delay10us(); // 根据要发送的bit决定是高是低 DQ = dat & 0x1; dat >>= 1; // 延时50us Delay50us(); // 释放总线 DQ = 1; } } /** * @brief 从18B20读取字节 * * @return u8 读取的字节 */ static u8 Int_DS18B20_RecvByte() { u8 i, result = 0; // 8个bit for (i = 0; i < 8; i++) { // 主机初始化读时段 DQ = 0; result >>= 1; DQ = 1; // 等待10us Delay10us(); // 采样 if (DQ == 1) { result |= 0x80; } // 等待整个读时段过去 Delay50us(); } return result; } u8 Int_DS18B20_GetTemperature() { u8 ls_byte, ms_byte; // 初始化 Int_DS18B20_Init(); // 发送跳过ROM指令的指令(0xCC) Int_DS18B20_SendByte(0xCC); // 发送温度转换指令(0x44) Int_DS18B20_SendByte(0x44); // 初始化 Int_DS18B20_Init(); // 发送0xCC Int_DS18B20_SendByte(0xCC); // 发送读取暂存器指令(0xBE) Int_DS18B20_SendByte(0xBE); // 收字节,总共9个,只要两个 ls_byte = Int_DS18B20_RecvByte(); ms_byte = Int_DS18B20_RecvByte(); // 初始化 Int_DS18B20_Init(); // 将读取到的两字节转化成温度返回 ls_byte >>= 4; ms_byte <<= 4; return ms_byte | ls_byte; }
5)Main.c
在Main.c文件中,写入以下内容。
#include <STC89C5xRC.H>
#include "Int_LCD1602.h"
#include "Int_DS18B20.h"
void main()
{
Int_LCD1602_Init();
while (1)
{
Int_LCD1602_ShowNum(0, 0, Int_DS18B20_GetTemperature());
Delay1ms(500);
}
}
s_byte | ls_byte;
}
**5)Main.c** 在Main.c文件中,写入以下内容。 ```c #include <STC89C5xRC.H> #include "Int_LCD1602.h" #include "Int_DS18B20.h" void main() { Int_LCD1602_Init(); while (1) { Int_LCD1602_ShowNum(0, 0, Int_DS18B20_GetTemperature()); Delay1ms(500); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。