历史上的今天
今天是:2024年12月03日(星期二)
2020年12月03日 | 完美实现STM32单总线挂多个DS18B20
2020-12-03 来源:eefocus
一般常见的STM32的关于DS18B20的例程都是检测一个传感器,代码一般都是跳过ROM检测,直接获取温度值。这种写法并不适用于单总线上挂载多个DS18B20的情况,Sandeepin的这个代码就是针对这种情况完善的单总线挂多个DS18B20检测,实现获取每个DS18B20的ID和温度。
主要的DS18B20时序代码没变,增加了搜索ROM函数,获取温度时先匹配ID。
核心代码如下:
DS18B20.c文件代码:
#include "DS18B20.h"
#include "Delay.h"
#include "stdio.h" // printf用
#define DS18B20_GPIO_NUM GPIO_Pin_5
#define DS18B20_GPIO_X GPIOC
#define RCC_APB2Periph_DS18B20_GPIO_X RCC_APB2Periph_GPIOC
#define DS18B20_DQ_OUT_Low GPIO_ResetBits(DS18B20_GPIO_X,DS18B20_GPIO_NUM)
#define DS18B20_DQ_OUT_High GPIO_SetBits(DS18B20_GPIO_X,DS18B20_GPIO_NUM)
#define DS18B20_DQ_IN GPIO_ReadInputDataBit(DS18B20_GPIO_X,DS18B20_GPIO_NUM)
#define MaxSensorNum 8
unsigned char DS18B20_ID[MaxSensorNum][8]; // 存检测到的传感器DS18B20_ID的数组,前面的维数代表单根线传感器数量上限
unsigned char DS18B20_SensorNum; // 检测到的传感器数量(从1开始,例如显示1代表1个,8代表8个)
// 配置DS18B20用到的I/O口
void DS18B20_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_DS18B20_GPIO_X, ENABLE);
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_GPIO_X, DS18B20_GPIO_NUM);
}
// 引脚输入
void DS18B20_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);
}
// 引脚输出
void DS18B20_Mode_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_NUM;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_GPIO_X, &GPIO_InitStructure);
}
// 复位,主机给从机发送复位脉冲
void DS18B20_Rst(void)
{
DS18B20_Mode_Out();
DS18B20_DQ_OUT_Low; // 产生至少480us的低电平复位信号
Delay_us(480);
DS18B20_DQ_OUT_High; // 在产生复位信号后,需将总线拉高
Delay_us(15);
}
// 检测从机给主机返回的应答脉冲。从机接收到主机的复位信号后,会在15~60us后给主机发一个应答脉冲
u8 DS18B20_Answer_Check(void)
{
u8 delay = 0;
DS18B20_Mode_IPU(); // 主机设置为上拉输入
// 等待应答脉冲(一个60~240us的低电平信号 )的到来
// 如果100us内,没有应答脉冲,退出函数,注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
while (DS18B20_DQ_IN&&delay < 100)
{
delay++;
Delay_us(1);
}
// 经过100us后,如果没有应答脉冲,退出函数
if (delay >= 100)//Hu200
return 1;
else
delay = 0;
// 有应答脉冲,且存在时间不超过240us
while (!DS18B20_DQ_IN&&delay < 240)
{
delay++;
Delay_us(1);
}
if (delay >= 240)
return 1;
return 0;
}
// 从DS18B20读取1个位
u8 DS18B20_Read_Bit(void)
{
u8 data;
DS18B20_Mode_Out();
DS18B20_DQ_OUT_Low; // 读时间的起始:必须由主机产生 >1us <15us 的低电平信号
Delay_us(2);
DS18B20_DQ_OUT_High;
Delay_us(12);
DS18B20_Mode_IPU();// 设置成输入,释放总线,由外部上拉电阻将总线拉高
if (DS18B20_DQ_IN)
data = 1;
else
data = 0;
Delay_us(50);
return data;
}
// 从DS18B20读取2个位
u8 DS18B20_Read_2Bit(void)//读二位 子程序
{
u8 i;
u8 dat = 0;
for (i = 2; i > 0; i--)
{
dat = dat << 1;
DS18B20_Mode_Out();
DS18B20_DQ_OUT_Low;
Delay_us(2);
DS18B20_DQ_OUT_High;
DS18B20_Mode_IPU();
Delay_us(12);
if (DS18B20_DQ_IN) dat |= 0x01;
Delay_us(50);
}
return dat;
}
// 从DS18B20读取1个字节
u8 DS18B20_Read_Byte(void) // read one byte
{
u8 i, j, dat;
dat = 0;
for (i = 0; i < 8; i++)
{
j = DS18B20_Read_Bit();
dat = (dat) | (j << i);
}
return dat;
}
// 写1位到DS18B20
void DS18B20_Write_Bit(u8 dat)
{
DS18B20_Mode_Out();
if (dat)
{
DS18B20_DQ_OUT_Low;// Write 1
Delay_us(2);
DS18B20_DQ_OUT_High;
Delay_us(60);
}
else
{
DS18B20_DQ_OUT_Low;// Write 0
Delay_us(60);
DS18B20_DQ_OUT_High;
Delay_us(2);
}
}
// 写1字节到DS18B20
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_Mode_Out();
for (j = 1; j <= 8; j++)
{
testb = dat & 0x01;
dat = dat >> 1;
if (testb)
{
DS18B20_DQ_OUT_Low;// 写1
Delay_us(10);
DS18B20_DQ_OUT_High;
Delay_us(50);
}
else
{
DS18B20_DQ_OUT_Low;// 写0
Delay_us(60);
DS18B20_DQ_OUT_High;// 释放总线
Delay_us(2);
}
}
}
//初始化DS18B20的IO口,同时检测DS的存在
u8 DS18B20_Init(void)
{
DS18B20_GPIO_Config();
DS18B20_Rst();
return DS18B20_Answer_Check();
}
// 从ds18b20得到温度值,精度:0.1C,返回温度值(-550~1250),Temperature1返回浮点实际温度
float DS18B20_Get_Temp(u8 i)
{
//u8 flag;
u8 j;//匹配的字节
u8 TL, TH;
short Temperature;
float Temperature1;
DS18B20_Rst();
DS18B20_Answer_Check();
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0x44);// convert
DS18B20_Rst();
DS18B20_Answer_Check();
// DS18B20_Write_Byte(0xcc);// skip rom
//匹配ID,i为形参
DS18B20_Write_Byte(0x55);
for (j = 0; j < 8; j++)
{
DS18B20_Write_Byte(DS18B20_ID[i][j]);
}
DS18B20_Write_Byte(0xbe);// convert
TL = DS18B20_Read_Byte(); // LSB
TH = DS18B20_Read_Byte(); // MSB
if (TH & 0xfc)
史海拾趣
|
单片机(STC89C52)VCC是5V, GPS(MTK M89)VCC是4.3V RXD连TXD,TXD连RXD 用万用表量的时候GPS的串口是4.8V,GPS的是3.6V 不知道怎么的就烧了?为什么没接串口之前MCU的RXD、TXD都有4.8的电压? 小弟刚入门还请指点迷经,要怎么联才可以让MCU读到GPS ...… 查看全部问答> |
|
一个有关看门狗(AT89s51)的问题问一下高手们。 1.看门狗是一个寄存器吧,它里面有些啥标识符。里面会有像TMOD寄存器里的GATE、C/T#、M1、M1.....吗? 2.还有在用它的时候,为什么要写入:   ...… 查看全部问答> |
|
如题: EVC下代码如下: addr = (unsigned char *)( 0xBFA00000 + 24+ i*2 ); code = *addr; RETAILMSG(1, (TEXT(\"The DTMF code is %x .\\r\\n\"),code)); 复制代码 我是没读出来!… 查看全部问答> |
|
Freescale的ARM® Cortex™-M4 微控制器系列Kinetis 好久才能上市? Freescale的ARM® Cortex™-M4 微控制器系列Kinetis 好久才能上市? 很想玩玩ARM® Cortex™-M4 内核的MCU,不知道有没有机会。 年初的时候使用过NXP的 LPC1000系列的ARM® Cortex™-M0, 感觉不错  ...… 查看全部问答> |
|
wince6.0 mass storage,RNDIS 和activesync USB 连接的实现方法探讨 S5pv210 下有现成的注册表 IF BSP_USBFN_RNDIS [HKEY_LOCAL_MACHINE\\Drivers\\USB\\FunctionDrivers] \"DefaultClientDriver\"=- ; erase previous default \"DefaultClientDriver\"=\"RNDIS\" ENDIF IF BSP_US ...… 查看全部问答> |




