STM32驱动DS18B20
DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传
统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的
数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,
从而为测量系统的构建引入全新概念,测量温度范围为-55~+125℃ ,精度为±0.5℃。现场温
度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,
并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。它工作在 3—5. 5 V 的电
压范围,采用多种封装形式,从而使系统设计灵活、方便,设定分辨率及用户设定的报警温度
存储在 EEPROM 中,掉电后依然保存
其内部结构如下所示
DS18B20的通讯方式是单总线的,一般而言,我们遇到的封装都是如下
其中DQ就是主要的通讯线路,对DS的读取和写入都需要主机来控制DQ线路的DQ高低电平的时间来确定,具体如下
一般而言,DQ线需要接一个上拉电阻,所以,才写操作的最后一步都需要将总线拉高
向DS写0需要总线拉低至少60US最多120US就算完成,也就是说,1-->0(持续60-120us)-->1 写入了0
像DS写入1需要总线拉低最少1us最多15US,然后总线拉高,拉高时间至少15us,一般40us以上即可 1->0(1-15us,推荐5us)-->1(持续15us以上,推荐40us)
由此可见,DS的总线采样实在总线拉低之后的15us开始的
读取DS分别为读取1和读取0,但是这两者时序是统一的
首先总线拉低至少1us,最多15us,还是选择2us,然后释放总线(也就是说进入输入模式),等待15us以上的事件,然后采样,高电平为1低电平为0
1-->0(持续2us,最多15us)-->等待15us以上60us以下-->采样总线电平,得到1或者0,记得采样完成之后切换到输出模式将总线拉高便于下一次使用
DS18B20的命令
DS1820有三个主要数字部件:1)64位激光ROM,2)温度传感器,3)非易失性温度报警触发器TH和TL
启动温度转换的命令是0X44,读取命令是0XBE
所以一般而言,对于DS的驱动包含以下几步
复位-->发 SKIP ROM 命令(0XCC)-->发开始转换命令(0X44)-->延时-->复
位-->发送 SKIP ROM 命令(0XCC)-->发读存储器命令(0XBE)-->连续读出两个字节数据(即
温度)-->结束
我们在读取的时候只读取两个字节的原因在于DS的存储器布局
前两个就是我们需要的温度,当然也可以读取全部的,扩展驱动达到其他目的
以下是驱动代码,STM32驱动代码中使用了位段操作
#ifndef __Ds18b20H
#define __Ds18b20H
#include "ioremap.h"
#include "delay.h"
#include "uart.h" //IO方向设置
#define Ds18b20IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define Ds18b20IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;} ////IO操作函数
#define Ds18b20DQ_OUT PGout(11) //数据端口 PG11
#define Ds18b20DQ_IN PGin(11) //数据端口 PG11 u8 Ds18b20Init(void); //初始化DS18B20 short Ds18b20GetTemp(void); //获取温度 void Ds18b20Start(void); //开始温度转换 void Ds18b20WriteByte(u8 dat);//写入一个字节 u8 Ds18b20ReadByte(void); //读出一个字节 u8 Ds18b20ReadBit(void); //读出一个位 u8 Ds18b20Check(void); //检测是否存在DS18B20 void Ds18b20Rst(void); //复位DS18B20 void Ds18b20Show(void); #endif
#include "ds18b20.h" //复位DS18B20
void Ds18b20Rst(void)
{
Ds18b20IO_OUT(); //SET PA0 OUTPUT
Ds18b20DQ_OUT=0; //拉低DQ
DelayUs(750); //拉低750us
Ds18b20DQ_OUT=1; //DQ=1
DelayUs(15); //15US
} //等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 Ds18b20Check(void)
{
u8 retry=0;
Ds18b20IO_IN();//SET PA0 INPUT
while (Ds18b20DQ_IN&&retry<200)
{
retry++;
DelayUs(1);
};
if(retry>=200)return 1;
else retry=0;
while (!Ds18b20DQ_IN&&retry<240)
{
retry++;
DelayUs(1);
};
if(retry>=240)return 1;
return 0;
} //从DS18B20读取一个位
//返回值:1/0
u8 Ds18b20ReadBit(void) // read one bit
{
u8 data;
Ds18b20IO_OUT();//SET PA0 OUTPUT
Ds18b20DQ_OUT=0;
DelayUs(2);
Ds18b20DQ_OUT=1;
Ds18b20IO_IN();//SET PA0 INPUT
DelayUs(12);
if(Ds18b20DQ_IN)data=1;
else data=0;
DelayUs(50);
return data;
} //从DS18B20读取一个字节
//返回值:读到的数据
u8 Ds18b20ReadByte(void) // read one byte
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=Ds18b20ReadBit();
dat=(j<<7)|(dat>>1);
}
return dat;
} //写一个字节到DS18B20
//dat:要写入的字节
void Ds18b20WriteByte(u8 dat)
{
u8 j;
u8 testb;
Ds18b20IO_OUT();//SET PA0 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
Ds18b20DQ_OUT=0;// Write 1
DelayUs(2);
Ds18b20DQ_OUT=1;
DelayUs(60);
}
else
{
Ds18b20DQ_OUT=0;// Write 0
DelayUs(60);
Ds18b20DQ_OUT=1;
DelayUs(2);
}
}
} //开始温度转换
void Ds18b20Start(void)// ds1820 start convert
{
Ds18b20Rst();
Ds18b20Check();
Ds18b20WriteByte(0xcc);// skip rom
Ds18b20WriteByte(0x44);// convert
} //初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
u8 Ds18b20Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PORTG口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTG.11 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_SetBits(GPIOG,GPIO_Pin_11); //输出1 Ds18b20Rst(); return Ds18b20Check();
} //从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short Ds18b20GetTemp(void)
{
u8 temp;
u8 TL,TH;
short tem;
Ds18b20Start (); // ds1820 start convert
Ds18b20Rst();
Ds18b20Check();
Ds18b20WriteByte(0xcc);// skip rom
Ds18b20WriteByte(0xbe);// convert
TL=Ds18b20ReadByte(); // LSB
TH=Ds18b20ReadByte(); // MSB if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0;//温度为负
}else temp=1;//温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL;//获得底八位
tem=(short)((float)tem*0.625);//转换
if(temp)return tem; //返回温度值
else return -tem;
} void Ds18b20Show(void)
{
short t = 0;
t = Ds18b20GetTemp();
printf("ds18b20 temp is %d\r\n",t);
}
STM32驱动DS18B20的更多相关文章
- esp8266的STM32驱动
esp8266的STM32驱动,数据发送接收由DMA完成,释放CPU. 目前只能发送返回消息为成功或失败的AT命令,并判断是否成功,详见esp8266_cmd():其它返回消息不可预知的命令(如查看A ...
- STM32驱动OV7725摄像头颜色识别
实验目的: 使用stm32驱动OV7725摄像头进行图像实时采集,在tft屏幕上实时显示并识别图像中的特定颜色,在颜色的周围画上框. 实验现象: 我的工程代码链接: http://download.c ...
- STM32驱动ILI9341控制器控制TFTLCD显示
STM32驱动ILI9341控制器控制TFTLCD显示 一.用STM32控制TFTLCD显示的编程方法,在编程驱动TFTLCD液晶显示器之前,我们先熟悉以下概念: 1.色彩深度,这是一个与TFTLCD ...
- AMS5601的ardunio和STM32驱动开发
AMS5601的ardunio和STM32驱动开发 本文有麦粒电子撰写,并提供相应产品服务. 前言 目前ams关于磁编码芯片用的比较多的可能是ams5600,能够输出pwm信号,电压信号以及I2C通信 ...
- STM32驱动LCD实战
前段时间写了<STM32驱动LCD原理>和<STM32的FSMC外设简介>两篇文章,本文将对STM32驱动LCD进行实战应用.LCD是深圳市拓普微科技开发有限公司的LMT028 ...
- STM32—驱动GY85-IMU模块
GY85是一个惯性测量模块,内部集成了三轴加速度计.三轴陀螺仪.电子罗盘.气压传感器等芯片,用于测量和报告设备速度.方向.重力,模块可以将加速度计.陀螺仪.电子罗盘等传感器的数据进行综合,在上位机可以 ...
- STM32—驱动六轴MPU6050输出欧拉角
文章目录 一.MPU6050介绍 1.MPU6050与陀螺仪.加速度计的关系: 2.整体概括 3.引脚说明 4.基本配置及相关寄存器 电源管理寄存器1 陀螺仪配置寄存器 加速度计配置寄存器 FIFO使 ...
- STM32—驱动HC-SR04超声波测距模块
文章目录 超声波测距原理 HC-SR04工作原理 STM32实现驱动 1.引脚的配置 2.时序控制 3.时间差测量 4.如何将距离测出来 超声波测距原理 利用HC-SR04超声波测距模块可以实现比较精 ...
- stm32驱动超声波模块
下面是关于stm32驱动超声波模块的一段代码,有需要的朋友可以复制参考,希望对大家能够有所帮助和启发. #define HCSR04_PORT GPIOB #define HCSR04_CLK RCC ...
随机推荐
- 内联函数 inline 漫谈
内联函数存在的结论是: 引入内联函数是为了解决函数调用效率的问题 由于函数之间的调用,会从一个内存地址调到另外一个内存地址,当函数调用完毕之后还会返回原来函数执行的地址.函数调用会有一定的时间开销,引 ...
- 初探JavaScript魅力(二)
行为,样式,结构三者分离(javascript, css, html),不要在行间加行为,样式 样式优先级:*<标签<class<ID<行间 style与className,如 ...
- javascript语句语义大全(2)
1. 四则运算相关 +,-,*,/,% 分别是加减乘除和取余 2.Math.pow(a,b) a的b次方 3.toFixed(a) 四舍五入为指定小数位数的数字 4. k++; ++K 看似相同但是在 ...
- [原创] web_custom_request 与 Viewstate
在用loadrunner对.net编写的website进行性能测试时,经常会遇上一些hidden fields,例如,CSRFTOKEN.VIEWSTATE.EVENTVALIDATION等,而对于这 ...
- [转]solr DataImportHandler 解决mysql 表导入内存溢出问题
最近一个项目要用到solr做全文检索,开始盲人摸象. 用tomcat 7 开始配置,开始正常,但是遇到cookie里有中文就报错. 无奈,换tomcat 6, 结果DataImportHandler ...
- Junit单元测试的简单使用(主要是在spring框架下的项目)
首先是解释什么是单元测试,单元测试是指对于一个大型项目里,对于单一模块或者单一接口的测试. 然后解释为什么要写单元测试,首先对于一个大型的项目,如果你每次都要重启一遍服务器调页面或者接口的bug,那就 ...
- Linux格式化硬盘 常用命令小记
今天新蛋上订购了一块1TB的硬盘打算装Ubuntu,当然先要做好功课,查一下注意事项啦! 基本功,格式化命令,以格式化 /dev/sda1 分区为例:$ sudo umount /dev/sda1 ...
- HDU 1203 I NEED A OFFER! 01背包 概率运算预处理。
题目大意:中问题就不说了 ^—^~ 题目思路:从题目来看是很明显的01背包问题,被录取的概率记为v[],申请费用记为w[].但是我们可以预先做个处理,使问题解决起来更方便:v[]数组保留不被录取的概率 ...
- push控制器 卡顿
代码: RecommendController *rec = [[RecommendController alloc]init]; [self.navigationController pushVie ...
- ios复制到剪贴板
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...