Files
TencentOS-tiny/board/CSTX_STM32F103RE_DTU/BSP/Hardware/DS18B20/ds18b20.c
2020-08-30 13:20:40 +08:00

200 lines
3.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/********************************************************
*
* @file ds18b20.c
* @brief ds18b20驱动
* @author Mculover666
* @date 2020/08/29
* @note 此驱动中us级延时使用DWT
*
********************************************************/
#include "ds18b20.h"
#include <stdio.h>
/**
* @brief 发送复位信号
* @param none
* @retval none
*/
static void DS18B20_Send_Reset_Single(void)
{
DS18B20_OutPut_Mode();
/* 拉低总线 480 - 960 us*/
DS18B20_Out(0);
DS18B20_Delay_us(750);
/* 释放总线 15 - 60 us */
DS18B20_Out(1);
DS18B20_Delay_us(15);
}
/**
* @brief 检测DS18B20存在脉冲
* @param none
* @retval 0 DS18B20设备正常
* @retval 1 DS18B20设备响应复位信号失败
* @retval 2 DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Ready_Single(void)
{
uint8_t cnt = 0;
/* 1.检测存在脉冲 */
DS18B20_InPut_Mode();
//等待DS18B20 拉低总线 60~240 us 响应复位信号)
while (DS18B20_In() && cnt < 240) {
DS18B20_Delay_us(1);
cnt++;
}
if (cnt > 240) {
return 1;
}
/* 2.检测DS18B20是否释放总线 */
cnt = 0;
DS18B20_InPut_Mode();
//判断DS18B20是否释放总线60~240 us 响应复位信号之后会释放总线)
while ((!DS18B20_In()) && cnt<240) {
DS18B20_Delay_us(1);
cnt++;
}
if (cnt > 240) {
return 2;
} else {
return 0;
}
}
/**
* @brief 检测DS18B20设备是否正常
* @param none
* @retval 0 DS18B20设备正常
* @retval 1 DS18B20设备响应复位信号失败
* @retval 2 DS18B20设备释放总线失败
*/
static uint8_t DS18B20_Check_Device(void)
{
/*1.主机发送复位信号*/
DS18B20_Send_Reset_Single();
/*2.检测存在脉冲*/
return DS18B20_Check_Ready_Single();
}
/**
* @brief DS18B20初始化
* @param none
* @retval none
*/
void DS18B20_Init(void)
{
/* 1.DS18B20控制引脚初始化 */
//在main函数中已经初始化不需要再次重复。
/*2.检测DS18B20设备是否正常*/
switch (DS18B20_Check_Device()) {
case 0:
printf("DS18B20_Init OK!\n");
break;
case 1:
printf("DS18B20设备响应复位信号失败\n");
break;
case 2:
printf("DS18B20设备释放总线失败\n");
break;
}
}
/**
* @brief 向DS18B20写一个字节
* @param cmd 要写入的字节
* @retval none
*/
static uint8_t DS18B20_Write_Byte(uint8_t cmd)
{
uint8_t i = 0;
/* 1. 设置总线为输出模式 */
DS18B20_OutPut_Mode();
/* 2. 发送数据,低位在前 */
for (i = 0; i < 8; i++) {
DS18B20_Out(0);
DS18B20_Delay_us(2);
DS18B20_Out(cmd & 0x01);
DS18B20_Delay_us(60);
DS18B20_Out(1);
cmd >>= 1;
DS18B20_Delay_us(2);
}
return 0;
}
/**
* @brief 从DS18B20读一个字节
* @param none
* @retval 读取到的一个字节数据
*/
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i = 0;
uint8_t data = 0;
/* 读取数据 */
for (i =0; i < 8; i++) {
DS18B20_OutPut_Mode();
DS18B20_Out(0);
DS18B20_Delay_us(2);
DS18B20_Out(1);
DS18B20_InPut_Mode();
DS18B20_Delay_us(10);
data >>= 1 ;
if (DS18B20_In()) {
data |= 0x80;
}
DS18B20_Delay_us(60);
DS18B20_Out(1);
}
return data;
}
/**
* @brief 从DS18B20读取一次数据
* @param none
* @retval 读取到的温度数据
* @note 适用于总线上只有一个DS18B20的情况
*/
uint16_t DS18B20_Read_Temperature(void)
{
uint16_t temp = 0;
uint8_t temp_H, temp_L;
DS18B20_Check_Device();
DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
DS18B20_Write_Byte(0x44); //启动一次温度转换
//等待温度转换完成
while (DS18B20_Read_Byte() != 0xFF);
DS18B20_Check_Device(); //必须,不能省略
DS18B20_Write_Byte(0xCC); //跳过ROM序列检测
DS18B20_Write_Byte(0xBE); //读取温度
temp_L = DS18B20_Read_Byte(); //读取的温度低位数据
temp_H = DS18B20_Read_Byte(); //读取的温度高位数据
temp = temp_L | (temp_H << 8); //合成温度
return temp;
}