[STM32F1] STM32基础篇——ds18b20实验

[复制链接]
 楼主| aizaixiyuanqian 发表于 2017-12-19 12:02 | 显示全部楼层 |阅读模式
本帖最后由 aizaixiyuanqian 于 2017-12-19 12:05 编辑

STM32 内部自带了温度传感器,但是因为芯片温升较大等问题,与实际温度差别较大,本次实验通过 STM32 来读取外部数字温度传感器温度,来得到较为准确的环境温度。我们将学习使用单总线技术,实现 STM32 和外部温度传感器( DS18B20)的通信,并把从温度传感器到的温度数据通过 printf 打印输出在串口助手上 。
 楼主| aizaixiyuanqian 发表于 2017-12-19 12:06 | 显示全部楼层
DS18B20 简介DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从为测量系统的构建引入全新概念,测量温度范围为-55~+125℃ ,精度为±0. 5℃。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。它工作在3—5. 5 V 电压范围,采用多种封装形式,从而使系统设计灵活、方便,设定分辨率及用户设定的报警温度存储在 EEPROM 中,掉电后依然保存。



 楼主| aizaixiyuanqian 发表于 2017-12-19 12:07 | 显示全部楼层
复位脉冲和应答脉冲
单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,,以产生复位脉冲。接着主机释放总线, 4.7K 的上拉电阻将单总线拉高,延时 15~60 us,并进入接收模式(Rx)。接着 DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲,若为低电平,再延时 480 us。

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:07 | 显示全部楼层
  写时序
写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次独立的写时序之间至少需要 1us 的恢复时间,两种写时序均起始于主机拉低总线。写 1 时序:主机输出低电平,延时 2us,然后释放总线,延时 60us。写 0 时序:主机输出低电平,延时 60us,然后释放总线,延时 2us。

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:09 | 显示全部楼层
读时序
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要 60us,且在 2 次独立的读时序之间至少需要 1us 的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的 15us 之内采样总线状态。典型的读时序过程为:主机输出低电平延时 2us,然后主机转入输入模式延时 12us,然后读取单总线当前的电平,然后延时 50us。

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:11 | 显示全部楼层
DS18B20 的典型温度读取过程, DS18B20 的典型温度读取过程为:
1.复位  
2.发 SKIP ROM 命令( 0XCC)  
3.发开始转换命令( 0X44)
4.延
5.复位
6.发送 SKIP ROM 命令( 0XCC)
7.发读存储器命令( 0XBE)
8.连续读出两个字
节数据(即温度)
9.结束。
DS18B20 的介绍就到这里,详细的可以参考中文或者英文手册

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:12 | 显示全部楼层
DS18B20原理图 5.png

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:13 | 显示全部楼层
ds18b20_init  IO 端口时钟初始化函数
void ds18b20_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
GPIO_InitStructure.GPIO_Pin=dq;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIO_ds18b20,&GPIO_InitStructure);
}
管脚定义是在其头文件内:
#define dq (GPIO_Pin_11) //PG11
#define GPIO_ds18b20 GPIOG
#define ds18b20_dq_H GPIO_SetBits(GPIO_ds18b20,dq)

#define ds18b20_dq_L GPIO_ResetBits(GPIO_ds18b20,dq)

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:15 | 显示全部楼层
DS18B20 初始化时序图
6.png
 楼主| aizaixiyuanqian 发表于 2017-12-19 12:15 | 显示全部楼层
DS18B20 初始化时序
void ds18b20init()
{
DQOUTINT();//输出
ds18b20_dq_L;
delay_us(480);//延时 480 微妙
ds18b20_dq_H;
delay_us(480);//延时 480 微妙
}

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:17 | 显示全部楼层
ds18b20读操作时序图
7.png
 楼主| aizaixiyuanqian 发表于 2017-12-19 12:18 | 显示全部楼层
ds18b20读操作程序
u8 DS18b20rd()
{
u8 i=0,value=0;
for(i=0;i<8;i++)
{
value>>=1;
DQOUTINT();//输出
ds18b20_dq_L;  //拉低
delay_us(4);//延时 4 微妙
ds18b20_dq_H;
delay_us(10);//延时 10 微妙
DQININT();  //输入配置
if(GPIO_ReadInputDataBit(GPIO_ds18b20,dq)==1)
{
value|=0x80;//读数据 从低位开始
}
delay_us(45);//延时 45 微妙
}
return value;
}

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:21 | 显示全部楼层
ds18b20写时序图



8.png

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:21 | 显示全部楼层
ds18b20写操作程序
void ds18b20wr(u8 dat)
{
u8 i=0;
DQOUTINT();//输出
for(i=0;i<8;i++)
{
ds18b20_dq_L;  //拉低
delay_us(15);//延时 15 微妙
if((dat&0x01)==1)
{
ds18b20_dq_H;
}
else
{
ds18b20_dq_L;
}
delay_us(60);//延时 60 微妙
ds18b20_dq_H;
dat>>=1;//准备下一位数据的发送
}
}

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:22 | 显示全部楼层
读取温度操作
a) 初始化 DS18B20
b) 跳过 ROM 操作
c) 发送温度转换命令。
d) 跳过 ROM 操作
e) 发送读取温度命令
f) 读取温度值。

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:23 | 显示全部楼层
读取温度程序函数
double readtemp() //读取温度内需要复位的
{
u16 temp;
u8 a,b;
double value;
ds18b20init(); //初始化
ds18b20wr(0xcc); //发送忽略 ROM 指令
ds18b20wr(0x44); //发送温度转换指令
delay_ms(800);
ds18b20init(); //初始化
ds18b20wr(0xcc); //发送忽略 ROM 指令
ds18b20wr(0xbe); //发读暂存器指令
a=DS18b20rd();  //温度的低八位
b=DS18b20rd();  //温度的高八位
temp=b;
temp=(temp<<8)+a;
if((temp&0xf800)==0xf800)
{
temp=(~temp)+1;
value=temp*(-0.0625);
}
else
{
value=temp*0.0625;
}
return value;
}

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:23 | 显示全部楼层
主程序
int main()
{
double temp;
printf_init();  //printf 初始化
ds18b20_init();  //DS18B20 初始化
while(1)
{
temp=readtemp(); //读取温度
printf("当前温度为:%0.4lf ℃\r\n",temp);
}
}

 楼主| aizaixiyuanqian 发表于 2017-12-19 12:25 | 显示全部楼层
后面还有关于DS18B20TFT的显示部分,这里的串口打印温度就先到这里了。感谢大家。
一路向北lm 发表于 2017-12-19 12:32 | 显示全部楼层
楼主辛苦,分享不错,继续加油。
mmuuss586 发表于 2017-12-19 13:47 | 显示全部楼层

感谢分享;
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝
快速回复 在线客服 返回列表 返回顶部