前言
DS18B20是一个温度传感器模块,关于其配置原理可参见这篇文章:
https://blog.csdn.net/weixin_45419341/article/details/124210290
本人使用的单片机型号为STM32F103RC,语言为C语言,代码是由DS18B20的卖家给的适用于51单片机的代码修改而来。本人在stm32上使用DS18B20的目的仅为完成学校任务,只针对了一个DS18B20的情况,并且未针对温度为负值的情况进行改编。本人水平一般,代码仅供参考。
代码
ds18b20.c
/*
* DS18B20测试程序
*
* 用途:数码管模块测试程序
*
* 原作者 日期 备注
* Huafeng Lin 2012/04/21 新增
* Huafeng Lin 2012/04/21 修改
*
* 改编:shuangyueniao
*/
#include "stm32f10x_conf.h"
#include "stm32f10x_gpio.h"
#include "DataType.h"
#include "ds18b20.h"
static u8 DQ; //数据传输线接单片机的相应的引脚为PC6
unsigned char tempL=0; //设全局变量
unsigned char tempH=0;
//static u8 fg=1; //温度正负标志
void ConfigDQ(u8 mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(mode == 0)
{
//配置PC6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //设置引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置上拉输入类型
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据参数初始化GPIO
}
else if(mode == 1)
{
//配置PC6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //设置引脚
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置推挽输出类型
GPIO_Init(GPIOC, &GPIO_InitStructure); //根据参数初始化GPIO
}
}
void Init_DS18B20(void)
{
// unsigned char x=1;
ConfigDQ(1); //将PC6切换成推挽输出模式
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //DQ先置高
Delay_us(10); //稍延时
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET); //发送复位脉冲
Delay_us(600); //延时(>480us)
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //拉高数据线
Delay_us(50); //等待(15~60us)
ConfigDQ(0);
DQ=GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6); //读PC6
// x=DQ; //用X的值来判断初始化有没有成功,18B20存在的话X=0,否则X=1
Delay_us(500);
}
//读一个字节
unsigned char ReadOneChar(void) //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
{
unsigned char i=0; //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期
unsigned char dat=0;
for (i=8;i>0;i--) //一个字节有8位
{
ConfigDQ(1);
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET); //拉低数据线
dat>>=1;
Delay_us(1);
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //拉高数据线
Delay_us(10);
ConfigDQ(0);
DQ=GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6); //读PC6
if(DQ)
dat|=0x80;
Delay_us(45);
}
return(dat);
}
//写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0; //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,
ConfigDQ(1);
for(i=8;i>0;i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。
{
//在开始另一个写周期前必须有1us以上的高电平恢复期。
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET); //拉低数据线
Delay_us(15);
DQ=dat&0x01;
if(DQ==1){
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //拉高数据线
}
else if(DQ==0){
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET); //拉低数据线
}
Delay_us(60);
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //拉高数据线
dat>>=1;
}
Delay_us(10);
GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); //拉高数据线
}
//读温度值(低位放tempL;高位放tempH;)
void ReadTemperature(u32 *sdata, u8 *xiaoshu, u8 *xiaoshu1, u8 *xiaoshu2)
{
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0x44); //启动温度转换
Delay_us(5000); //转换需要一点时间,延时
Init_DS18B20(); //初始化
WriteOneChar(0xcc); //跳过读序列号的操作
WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)
tempL=ReadOneChar(); //读出温度的低位LSB
tempH=ReadOneChar(); //读出温度的高位MSB
if(tempH>0x7f) //最高位为1时温度是负
{
tempL=~tempL; //补码转换,取反加一
tempH=~tempH+1;
// fg=0; //读取温度为负时fg=0
}
*sdata = tempL/16+tempH*16; //整数部分
*xiaoshu1 = (tempL&0x0f)*10/16; //小数第一位
*xiaoshu2 = (tempL&0x0f)*100/16%10; //小数第二位
*xiaoshu=(*xiaoshu1)*10+(*xiaoshu2); //小数两位
}
ds18b20.h
#ifndef __DS18B20_H
#define __DS18B20_H
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "stm32f10x_gpio.h"
#include "delay.h"
#include "DataType.h"
void ConfigDQ(u8 mode); //配置PC6
void Init_DS18B20(void); //初始化ds18b20
unsigned char ReadOneChar(void); //读一个字节
void WriteOneChar(unsigned char dat); //写一个字节
void ReadTemperature(u32 *sdata, u8 *xiaoshu, u8 *xiaoshu1, u8 *xiaoshu2); //读温度值
#endif
DataType.h
/*********************************************************************************************************
* 模块名称:DataType.h
* 摘 要:数据类型定义
* 当前版本:1.0.0
* 作 者:SZLY(COPYRIGHT 2018 - 2020 SZLY. All rights reserved.)
* 完成日期:2020年01月01日
* 内 容:
* 注 意:
**********************************************************************************************************
* 取代版本:
* 作 者:
* 完成日期:
* 修改内容:
* 修改文件:
*********************************************************************************************************/
#ifndef _DATA_TYPE_H_
#define _DATA_TYPE_H_
/*********************************************************************************************************
* 包含头文件
*********************************************************************************************************/
/*********************************************************************************************************
* 宏定义
*********************************************************************************************************/
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short HWORD; //两个字节组成一个半字
typedef unsigned int WORD; //四个字节组成一个字
typedef long LONG;
#define LOHWORD(w) ((HWORD)(w)) //字的低半字
#define HIHWORD(w) ((HWORD)(((WORD)(w) >> 16) & 0xFFFF)) //字的高半字
#define LOBYTE(hw) ((BYTE)(hw) ) //半字的低字节
#define HIBYTE(hw) ((BYTE)(((WORD)(hw) >> 8) & 0xFF)) //半字的高字节
//两个字节组成一个半字
#define MAKEHWORD(bH, bL) ((HWORD)(((BYTE)(bL)) | ((HWORD)((BYTE)(bH))) << 8))
//两个半字组成一个字
#define MAKEWORD(hwH, hwL) ((WORD)(((HWORD)(hwL)) | ((WORD)((HWORD)(hwH))) << 16))
#define TRUE 1
#define FALSE 0
#define NULL 0
#define INVALID_DATA -100
/*********************************************************************************************************
* 枚举结构体定义
*********************************************************************************************************/
/*********************************************************************************************************
* API函数声明
*********************************************************************************************************/
#endif