545 lines
16 KiB
C
545 lines
16 KiB
C
// SPDX-License-Identifier: GPL-3.0-only
|
||
/*
|
||
* Copyright (c) 2008-2023 100askTeam : Dongshan WEI <weidongshan@qq.com>
|
||
* Discourse: https://forums.100ask.net
|
||
*/
|
||
|
||
|
||
/* Copyright (C) 2008-2023 深圳百问网科技有限公司
|
||
* All rights reserved
|
||
*
|
||
*
|
||
* 免责声明: 百问网编写的文档,仅供学员学习使用,可以转发或引用(请保留作者信息),禁止用于商业用途!
|
||
* 免责声明: 百问网编写的程序,可以用于商业用途,但百问网不承担任何后果!
|
||
*
|
||
*
|
||
* 本程序遵循GPL V3协议,使用请遵循协议许可
|
||
* 本程序所用的开发板: DShanMCU-F103
|
||
* 百问网嵌入式学习平台:https://www.100ask.net
|
||
* 百问网技术交流社区: https://forums.100ask.net
|
||
* 百问网官方B站: https://space.bilibili.com/275908810
|
||
* 百问网官方淘宝: https://100ask.taobao.com
|
||
* 联系我们(E-mail): weidongshan@qq.com
|
||
*
|
||
* 版权所有,盗版必究。
|
||
*
|
||
* 修改历史 版本号 作者 修改内容
|
||
*-----------------------------------------------------
|
||
* 2023.08.04 v01 百问科技 创建文件
|
||
*-----------------------------------------------------
|
||
*/
|
||
|
||
|
||
#include "driver_ds18b20.h"
|
||
#include "driver_lcd.h"
|
||
#include "driver_timer.h"
|
||
#include "stm32f1xx_hal.h"
|
||
|
||
/* rom commands */
|
||
#define SEARCH_ROM 0xF0
|
||
#define READ_ROM 0x33
|
||
#define MATCH_ROM 0x55
|
||
#define SKIP_ROM 0xCC
|
||
#define ALARM_ROM 0xEC
|
||
|
||
/* functions commands */
|
||
#define CONVERT_TEAMPERATURE 0x44
|
||
#define WRITE_SCRATCHPAD 0x4E
|
||
#define READ_SCRATCHPAD 0xBE
|
||
#define COPY_SCRATCHPAD 0x48
|
||
#define RECALL_EEPROM 0xB8
|
||
#define READ_POWER_SUPPLY 0xB4
|
||
|
||
|
||
/* 先实现GPIO的基本操作 */
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinCfgAsOutput
|
||
* 功能描述: 把DS18B20的数据引脚配置为输出
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_PinCfgAsOutput(void)
|
||
{
|
||
/* 对于STM32F103, 已经把DS18B20的引脚配置为"open drain, pull-up" */
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinCfgAsInput
|
||
* 功能描述: 把DS18B20的数据引脚配置为输入
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_PinCfgAsInput(void)
|
||
{
|
||
/* 对于STM32F103, 已经把DS18B20的引脚配置为"open drain, pull-up"
|
||
* 让它输出1就不会驱动这个引脚, 并且可以读入引脚状态
|
||
*/
|
||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinSet
|
||
* 功能描述: 设置DS18B20的数据引脚的输出值
|
||
* 输入参数: val - 输出电平
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_PinSet(int val)
|
||
{
|
||
if (val)
|
||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
|
||
else
|
||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinRead
|
||
* 功能描述: 读取DS18B20的数据引脚
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 1-高电平, 0-低电平
|
||
* 修改日期 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_PinRead(void)
|
||
{
|
||
if (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1))
|
||
return 1;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinSetForTime
|
||
* 功能描述: 设置DS18B20的数据引脚,并维持一定时间
|
||
* 输入参数: val - 输出电平
|
||
* us - 维持多少us
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_PinSetForTime(int val, int us)
|
||
{
|
||
DS18B20_PinCfgAsOutput();
|
||
DS18B20_PinSet(val);
|
||
udelay(us);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_PinRelease
|
||
* 功能描述: 释放引脚,就是不再驱动引脚,配置为输入即可
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_PinRelease(void)
|
||
{
|
||
DS18B20_PinCfgAsInput();
|
||
}
|
||
|
||
/* ds18b20的代码 */
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_Start
|
||
* 功能描述: 给DS18B20发出启动信号,并返回响应值
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 1-无响应, 0-有响应
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_Start(void)
|
||
{
|
||
int val;
|
||
|
||
DS18B20_PinSetForTime(0, 500);
|
||
DS18B20_PinRelease();
|
||
udelay(80);
|
||
|
||
val = DS18B20_PinRead();
|
||
udelay(250);
|
||
return val;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_WriteBit
|
||
* 功能描述: 给DS18B20发送1bit数据
|
||
* 输入参数: val - 数据
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_WriteBit(int val)
|
||
{
|
||
if (0 == val)
|
||
{
|
||
DS18B20_PinSetForTime(0, 60);
|
||
DS18B20_PinRelease();
|
||
udelay(2);
|
||
}
|
||
else
|
||
{
|
||
DS18B20_PinSetForTime(0, 2);
|
||
DS18B20_PinRelease();
|
||
udelay(60);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_ReadBit
|
||
* 功能描述: 读取DS18B20 1bit数据
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 1/0 - 数据
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_ReadBit(void)
|
||
{
|
||
int val;
|
||
|
||
DS18B20_PinSetForTime(0, 2);
|
||
DS18B20_PinRelease();
|
||
udelay(10);
|
||
val = DS18B20_PinRead();
|
||
udelay(50);
|
||
return val;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_WriteByte
|
||
* 功能描述: 给DS18B20发送1 byte数据
|
||
* 输入参数: data - 数据
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_WriteByte(unsigned char data)
|
||
{
|
||
int i;
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
|
||
DS18B20_WriteBit(data & (1<<i));
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_ReadByte
|
||
* 功能描述: 读取DS18B20 1 byte数据
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 数据
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static unsigned char DS18B20_ReadByte(void)
|
||
{
|
||
int i;
|
||
unsigned char data = 0;
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
if (DS18B20_ReadBit() == 1)
|
||
data |= (1<<i);
|
||
}
|
||
|
||
return data;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_WriteRomCmd
|
||
* 功能描述: 发送ROM命令
|
||
* 输入参数: cmd - ROM命令
|
||
* 输出参数: 无
|
||
* 返 回 值: 数据
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_WriteRomCmd(unsigned char cmd)
|
||
{
|
||
DS18B20_WriteByte(cmd);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_WriteFunctionCmd
|
||
* 功能描述: 发送Function命令
|
||
* 输入参数: cmd - Function命令
|
||
* 输出参数: 无
|
||
* 返 回 值: 数据
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static void DS18B20_WriteFunctionCmd(unsigned char cmd)
|
||
{
|
||
DS18B20_WriteByte(cmd);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_WaitReady
|
||
* 功能描述: 等待DS18B20就绪
|
||
* 输入参数: timeout_us - 超时时间(单位us)
|
||
* 输出参数: 无
|
||
* 返 回 值: 0 - 就绪, (-1) - 失败
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_WaitReady(int timeout_us)
|
||
{
|
||
while (timeout_us--)
|
||
{
|
||
if (DS18B20_ReadBit() == 1)
|
||
return 0; /* ok */
|
||
udelay(1);
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_StartConvert
|
||
* 功能描述: 启动DS18B20的温度转换
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 0 - 成功, (-1) - 失败
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_StartConvert(void)
|
||
{
|
||
if (DS18B20_Start() != 0)
|
||
{
|
||
//printf("DS18B20_Start err!\n\r");
|
||
return -1;
|
||
}
|
||
|
||
DS18B20_WriteRomCmd(SKIP_ROM);
|
||
DS18B20_WriteFunctionCmd(CONVERT_TEAMPERATURE);
|
||
|
||
/* 等待/判断转换成功 */
|
||
if (0 != DS18B20_WaitReady(1000000))
|
||
{
|
||
//printf("DS18B20_WaitReady err!\n\r");
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_Read_RAM
|
||
* 功能描述: 读取DS18B20的内存数据(9字节)
|
||
* 输入参数: 无
|
||
* 输出参数: ram - 用于保存输出数据的buffer
|
||
* 返 回 值: 0 - 成功, (-1) - 失败
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
static int DS18B20_Read_RAM(unsigned char ram[])
|
||
{
|
||
int i;
|
||
|
||
if (DS18B20_Start() != 0)
|
||
{
|
||
//printf("DS18B20_Start err!\n\r");
|
||
return -1;
|
||
}
|
||
|
||
DS18B20_WriteRomCmd(SKIP_ROM);
|
||
DS18B20_WriteFunctionCmd(READ_SCRATCHPAD);
|
||
|
||
for (i = 0; i < 9; i++)
|
||
{
|
||
ram[i] = DS18B20_ReadByte();
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* 实际操作函数 */
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_Init
|
||
* 功能描述: DS18B20的初始化函数
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 返 回 值: 无
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
void DS18B20_Init(void)
|
||
{
|
||
DS18B20_PinRelease();
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_ReadROM
|
||
* 功能描述: 读取DS18B20的ROM ID
|
||
* 输入参数: 无
|
||
* 输出参数: rom - 用于保存输出数据的buffer
|
||
* 返 回 值: 0 - 成功, (-1) - 失败
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
int DS18B20_ReadROM(unsigned char rom[])
|
||
{
|
||
int i;
|
||
|
||
if (DS18B20_Start() != 0)
|
||
{
|
||
//printf("DS18B20_Start err!\n\r");
|
||
return -1;
|
||
}
|
||
|
||
DS18B20_WriteRomCmd(READ_ROM);
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
rom[i] = DS18B20_ReadByte();
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_Read_Temperature
|
||
* 功能描述: 读取DS18B20的温度值
|
||
* 输入参数: 无
|
||
* 输出参数: temp - 用于保存温度值
|
||
* 返 回 值: 0 - 成功, (-1) - 失败
|
||
* 修改日期: 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
int DS18B20_Read_Temperature(double *temp)
|
||
{
|
||
int err;
|
||
unsigned char ram[9];
|
||
double val[] = {0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64};
|
||
double sum = 0;
|
||
int i;
|
||
|
||
err = DS18B20_StartConvert();
|
||
if (err)
|
||
return err;
|
||
|
||
err = DS18B20_Read_RAM(ram);
|
||
if (err)
|
||
return err;
|
||
|
||
/* 计算温度 */
|
||
|
||
/* 先判断精度 */
|
||
if (ram[4] & (3<<5) == 0) /* 精度: 9bit */
|
||
i = 3;
|
||
else if (ram[4] & (3<<5) == (1<<5)) /* 精度: 10bit */
|
||
i = 2;
|
||
else if (ram[4] & (3<<5) == (2<<5)) /* 精度: 11bit */
|
||
i = 1;
|
||
else
|
||
/* 精度是 12 bit */
|
||
i = 0;
|
||
|
||
for (; i < 8; i++)
|
||
{
|
||
if (ram[0] & (1<<i))
|
||
sum += val[i];
|
||
}
|
||
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
if (ram[1] & (1<<i))
|
||
sum += val[8+i];
|
||
}
|
||
|
||
if (ram[1] & (1<<3))
|
||
sum = 0 - sum;
|
||
|
||
*temp = sum;
|
||
return 0;
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* 函数名称: DS18B20_Test
|
||
* 功能描述: DS18B20测试程序
|
||
* 输入参数: 无
|
||
* 输出参数: 无
|
||
* 无
|
||
* 返 回 值: 无
|
||
* 修改日期 版本号 修改人 修改内容
|
||
* -----------------------------------------------
|
||
* 2023/08/03 V1.0 韦东山 创建
|
||
***********************************************************************/
|
||
void DS18B20_Test(void)
|
||
{
|
||
unsigned char rom[8];
|
||
|
||
int i;
|
||
double temp;
|
||
int m,n,len;
|
||
|
||
DS18B20_Init();
|
||
|
||
//while (1)
|
||
{
|
||
if (DS18B20_ReadROM(rom) == 0)
|
||
{
|
||
LCD_PrintString(0, 0, "ds18b20 rom:");
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
LCD_PrintHex(i*2, 2, rom[i], 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
LCD_PrintString(0, 4, "Temperature:");
|
||
while (1)
|
||
{
|
||
if (0 == DS18B20_Read_Temperature(&temp))
|
||
{
|
||
m = (int)temp; /* 3.01, m = 3 */
|
||
temp = temp - m; /* 小数部分: 0.21 */
|
||
n = temp * 10; /* n = 2 */
|
||
|
||
/* 在LCD上打印 */
|
||
//printf("ds18b20 temperature: %d.%04d\n\r", m, n); /* 3.010v */
|
||
len = LCD_PrintSignedVal(0, 6, m);
|
||
LCD_PutChar(len, 6, '.');
|
||
LCD_PrintSignedVal(len+1, 6, n);
|
||
}
|
||
}
|
||
}
|
||
|
||
|