1、 485 CAN 单总线 SPI I2C :1、是什么 2、特点3、协议 4、使用方法 5、区别 6通信方式
概念
单总线是美国DALLAS公司推出的外围串行扩展总线技术。与SPI、I²C串行数据通信方式不同,它采用单根信号线传输。 这种协议由一个总线主节点、或多个从节点组成系统,通过单根信号线对从芯片进行数据的读取。
单总线的数据传输速率一般为16.3Kbit/s,最大可达142 Kbit/s,通常情况下采用100Kbit/s以下的速率传输数据。主设备I/O口可直接驱动200m范围内的从设备,经过扩展后可达1km范围
DHT11单总线通信
HT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。 单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗, 信号传输距离可达20米以上, 使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚封装。 连接方便, 特殊封装形式可根据用户需求而提供
通信过程
主机等待DHT11响应和DHT11回应
数据0表示方式
数字1的表现
代码实现
DHT11响应为微秒级别普通HAL库延时最小单位为毫秒所以需要收写延时函数
static uint32_t fac_us = 0; //us延时倍乘数 //系统时钟频率 void delay_init(uint8_t SYSCLK) { fac_us = SYSCLK; } void delay_us(uint32_t nus) { uint32_t ticks; uint32_t told, tnow, tcnt = 0; uint32_t reload = SysTick->LOAD; //LOAD的值 ticks = nus * fac_us; //需要的节拍数 told = SysTick->VAL; //刚进入时的计数器值 while (1) { tnow = SysTick->VAL; if (tnow != told) { if (tnow < told) tcnt += told - tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了. else tcnt += reload - tnow + told; told = tnow; if (tcnt >= ticks) break; //时间超过/等于要延迟的时间,则退出. } }; }
#include "dht11.h"
#include <stdio.h>
//GPIO组
#define DHT11_GPIO_PORT GPIOB
//接入引脚
#define DHT11_GPIO_PIN GPIO_PIN_8
//读取电平状态
#define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
/********配置引脚具有收发功能************/
//IO口的初始化为输入模式 上拉(初始为高电平)
static void DHT11_IO_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
//初始化为输出模式
static void DHT11_IO_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
/**************起始*********************/
void DHT11_Rst(void)
{
//单片机向DHT11发送信号
//配置输出模式
DHT11_IO_OUT();
//将电平拉低
HAL_GPIO_WritePin(DHT11_GPIO_PORT,DHT11_GPIO_PIN,GPIO_PIN_RESET);
//延时20ms
HAL_Delay(20);
//将电平拉高
HAL_GPIO_WritePin(DHT11_GPIO_PORT,DHT11_GPIO_PIN,GPIO_PIN_SET);
//延时30us(20us-40us)
delay_us(30);
//单片机链接DHT11结束
}
//等待DHT11答复
//1 未检测到DHT11的存在
//0 存在
uint8_t DHT11_Check(void)
{
uint8_t retry = 0;
DHT11_IO_IN();//SET INPUT
//判断电平是否拉低或者延时不超过100us
while(DHT11_DQ_IN && retry<100)
{
retry++;
delay_us(1);
}
//>100us:未检测到DHT11存在
//<100us: 检测到DHT11
if(retry >=100)
{
return 1;
}else
{
retry = 0;
}
//下一步检测DHT11将电平拉高
while(!DHT11_DQ_IN && retry<100)
{
retry ++;
delay_us(1);
}
if(retry >=100)
{
return 1;
}else
{
return 0;
}
}
//传送数据
//从DHT11读取一位
//返回值:1/0
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0;
while(DHT11_DQ_IN && retry <100)
{
retry++;
delay_us(1);
}
retry = 0;
//等待电平拉高第一个数据位
while(!DHT11_DQ_IN && retry < 100)
{
retry++;
delay_us(1);
}
//此时在第一个数据位开始时间
delay_us(40);
//0 26us - 28us
//1 70us
//延时40us 如果现在还是高电平代表1 反之为0;
if(DHT11_DQ_IN)return 1;
else
return 0;
}
//读取一个字节
uint8_t DHT11_Read_Byte(void)
{
uint8_t i,dat;
dat = 0;
for(i=0;i<8;i++)
{
//依次将读到的一位数据左移
dat <<= 1;
//将数据读出一位
dat |= DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
uint8_t DHT11_Rrad_Date(uint8_t *humiH,uint8_t *humiL,uint8_t *tempH,uint8_t *tempL)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)
{
buf[i]=DHT11_Read_Byte();
}
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humiH=buf[0];
*humiL=buf[1];
*tempH=buf[2];
*tempL=buf[3];
}else
return HAL_ERROR;
return HAL_OK;
}