标题:
stm32驱动ds18b20温度读取源程序
[打印本页]
作者:
xu2509674896
时间:
2020-12-19 16:57
标题:
stm32驱动ds18b20温度读取源程序
发上来的程序是主要基于stm32f1的驱动程序,如果你需要清楚了解ds18b20的工作时序,寄存器配置,那么在论坛上找找看看数据手册,如果你想直接用,那么把头文件和c文件直接添加到你的工程中就可以了。 本程序在实质上和51驱动的没有区别,都是模拟I2C。两者区别在于大部分51对于IO口的输入输出配置没有硬性规定,既可以当输入又可以当输出,而stm32的输入输出必须明确模式配置。而ds18b20是一线通信,所以需要输入输出模式来回配置。
本程序我通过硬件明确测试过,可以准确读出数据,如果数据无法读出,可能是以下几点问题:
1、引脚配置未修改。可在h文件中修改宏定义即可
2、请注意该函数void DS18B20_DQ_DDR(uint8_t ddr),他是用于修改IO输入输出模式的,本程序使用的标准库函数进行操作,用到的时间可能会有一点长,影响到了I2C的模拟时序,建议可以直接对寄存器进行操作,库函数的实质也是修改寄存器,只是由于为了程序兼容性,牺牲了时间。
3、由于是模拟的I2C时序,请务必注意中断对于通信时序的影响。
单片机源程序如下:
#include "ds18b20.h"//主要包含了一些引脚宏定义,移植时必须包含
#include "delay.h"//主要是声明了延时函数,由于是模拟I2C,延时必须精准
#include "math.h"//使用了库函数pow()函数,该函数为幂次函数,如pow(10,2),相当于10^2,移植时必须包含
/*******************************************************************************
函数名:DS18B20_DQ_DDR
功能:配置IO输入/输出状态
输入:0/1 输入0配置为输入,输入1配置为输出
输出:
返回值:
*******************************************************************************/
void DS18B20_DQ_DDR(uint8_t ddr)
{
GPIO_InitTypeDef GPIO_InitStructure;
//使能GPIO时钟
RCC_APB2PeriphClockCmd(DS18B20_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
//配置为输出
if(ddr == 1)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}
//配置为输入
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}
}
/*******************************************************************************
函数名:DS18B20_Init
功能:初始化DS18B20
输入:
输出:
返回值:初始化成功为0,不成功为1
备注:
*******************************************************************************/
u8 DS18B20_Init(void)
{
u8 x = 0;
//改变DQ引脚为输出
DS18B20_DQ_DDR(1);
//先置高
DS18B20_DQ_H;
//延时700us,使总线稳定
delay_us(700);
//复位脉冲,低电位
DS18B20_DQ_L;
//保持至少480us,这里500us
delay_us(500);
//改变DQ引脚为输入
DS18B20_DQ_DDR(0);
//拉高数据线,释放总线
DS18B20_DQ_H;
//等待15-60us,这里40us
delay_us(40);
//等待35us
delay_us(35);
//聆听,判断有没有初始化成功(DS18B20有没有发送应答脉冲)
x = DS18B20_DQ_ReadPin;
//至少480us后进入接收状态,这里500us
delay_us(500);
return x;
}
/*******************************************************************************
函数名:DS18B20_Wbyte
功能:写一个字节
输入:uint8_t xbyte
输出:
返回值:
备注:
*******************************************************************************/
void DS18B20_Wbyte(uint8_t xbyte)
{
//i:循环控制变量,x:取位运算变量
int8_t i ,x = 0;
//改变DQ引脚为输出
DS18B20_DQ_DDR(1);
//8次循环实现逐位写入
for(i = 1; i <= 8; i++)
{
//先取低位
x = xbyte & 0x01;
//写1
if(x)
{
DS18B20_DQ_H;
//拉低总线
DS18B20_DQ_L;
//延时15us
delay_us(15);
//总线写1
DS18B20_DQ_H;
//延时15us
delay_us(15);
//保持高电平
DS18B20_DQ_H;
delay_us(4);
}
//写0
else
{
DS18B20_DQ_H;
//总线拉低
DS18B20_DQ_L;
//延时15us
delay_us(15);
//总线写0
DS18B20_DQ_L;
//延时15us
delay_us(15);
//保持高电平
DS18B20_DQ_H;
delay_us(4);
}
//xbyte右移一位
xbyte = xbyte >> 1;
}
}
/*******************************************************************************
函数名:DS18B20_Rbit
功能:从DS18B20读一个位
输入:
输出:
返回值:读取到的位
备注:
*******************************************************************************/
uint8_t DS18B20_Rbit(void)
{
//rbit是最终位数据,x是取状态变量
uint8_t rbit = 0x00,x = 0;
//改变DQ为输出模式
DS18B20_DQ_DDR(1);
DS18B20_DQ_H;
//总线写0
DS18B20_DQ_L;
//延时15us以内
delay_us(5);
//释放总线
DS18B20_DQ_H;
//改变DQ为输入模式
DS18B20_DQ_DDR(0);
//延时大约3us
delay_us(3);
//获取总线电平状态
x = DS18B20_DQ_ReadPin;
//如果是1,则返回0x80,否则返回0x00
if(x)
rbit = 0x80;
//延时大约60us
delay_us(60);
return rbit;
}
/*******************************************************************************
函数名:DS18B20_Rbyte
功能:从DS18B20读一个字节
输入:
输出:
返回值:读取到的字节
备注:
*******************************************************************************/
uint8_t DS18B20_Rbyte(void)
{
//rbyte:最终得到的字节
//tempbit:中间运算变量
uint8_t rbyte = 0,i = 0, tempbit =0;
for (i = 1; i <= 8; i++)
{
//读取位
tempbit = DS18B20_Rbit();
//右移实现高低位排序
rbyte = rbyte >> 1;
//或运算移入数据
rbyte = rbyte|tempbit;
}
return rbyte;
}
int ReadTemperature(void)
{
//fg:符号位
//data:温度的整数部分
int fg;
int data;
//DS18B20初始化
DS18B20_Init();
//跳过读序列号
DS18B20_Wbyte(0xcc);
//启动温度转换
DS18B20_Wbyte(0x44);
//等待温度转换
delay_ms(1);
DS18B20_Init();
DS18B20_Wbyte(0xcc);
//读温度寄存器
DS18B20_Wbyte(0xbe);
uint8_t TempL = DS18B20_Rbyte();//读取低8位
uint8_t TempH = DS18B20_Rbyte();//读取高8位
//符号位为负
if(TempH > 0x70)
{
TempL = ~TempL;
TempH = ~TempH;
fg = 0;
}
else fg = 1;
//将数据高低位合并
data = TempH;//数据高八位
data <<= 8;//左移8位
data += TempL;//加上低八位
//data的"1"相当于0.0625℃
//换句话说,想要多少精度可以这样写:data=(float)data*0.0625*pow(10,n)
//其中n为保留的小数精度位数,可以从目前对ds18b20配置情况下看出最高保留小数的精度位数为4位
//这样只需要对返回值进行处理就可以用于显示了
//特别注意的是,int类型的数据长度为16位,最大值为65535,因此需要注意使用范围
data=(float)data*0.0625*pow(10,1);//这样写等同于下面一句
//data = (float)data*0.625;//这样相当于精度为0.1℃
if(fg)
return data;
else
return -data;
}
复制代码
51hei.png
(2.51 KB, 下载次数: 76)
下载附件
2020-12-19 17:13 上传
所有资料51hei提供下载:
DS18B20.rar
(2.56 KB, 下载次数: 101)
2020-12-19 16:55 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1