打印
[STM32F1]

STM32基础篇——ds18b20实验

[复制链接]
3208|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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。

使用特权

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

使用特权

评论回复
6
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 的介绍就到这里,详细的可以参考中文或者英文手册

使用特权

评论回复
7
aizaixiyuanqian|  楼主 | 2017-12-19 12:12 | 只看该作者
DS18B20原理图

使用特权

评论回复
8
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)

使用特权

评论回复
9
aizaixiyuanqian|  楼主 | 2017-12-19 12:15 | 只看该作者
DS18B20 初始化时序图

使用特权

评论回复
10
aizaixiyuanqian|  楼主 | 2017-12-19 12:15 | 只看该作者
DS18B20 初始化时序
void ds18b20init()
{
DQOUTINT();//输出
ds18b20_dq_L;
delay_us(480);//延时 480 微妙
ds18b20_dq_H;
delay_us(480);//延时 480 微妙
}

使用特权

评论回复
11
aizaixiyuanqian|  楼主 | 2017-12-19 12:17 | 只看该作者
ds18b20读操作时序图

使用特权

评论回复
12
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;
}

使用特权

评论回复
13
aizaixiyuanqian|  楼主 | 2017-12-19 12:21 | 只看该作者
ds18b20写时序图





使用特权

评论回复
14
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;//准备下一位数据的发送
}
}

使用特权

评论回复
15
aizaixiyuanqian|  楼主 | 2017-12-19 12:22 | 只看该作者
读取温度操作
a) 初始化 DS18B20
b) 跳过 ROM 操作
c) 发送温度转换命令。
d) 跳过 ROM 操作
e) 发送读取温度命令
f) 读取温度值。

使用特权

评论回复
16
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;
}

使用特权

评论回复
17
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);
}
}

使用特权

评论回复
18
aizaixiyuanqian|  楼主 | 2017-12-19 12:25 | 只看该作者
后面还有关于DS18B20TFT的显示部分,这里的串口打印温度就先到这里了。感谢大家。

使用特权

评论回复
19
一路向北lm| | 2017-12-19 12:32 | 只看该作者
楼主辛苦,分享不错,继续加油。

使用特权

评论回复
20
mmuuss586| | 2017-12-19 13:47 | 只看该作者

感谢分享;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝