STM32驱动DHT11,配置端口为开楼输出模式

//---定义结构体
typedef struct _DHT11_HandlerType		DHT11_HandlerType;
//---定义指针结构体
typedef struct _DHT11_HandlerType		*pDHT11_HandlerType;
//---定义
struct _DHT11_HandlerType
{
	UINT16_T		msgWenDu;																								//---温度
	UINT16_T		msgShiDu;																								//---湿度
	UINT32_T		msgBit;																									//---端口序号
	GPIO_TypeDef	*msgPort;																								//---端口号	
	void			(*msgDelayus)(UINT32_T delay);																			//---us延时函数
	void			(*msgDelayms)(UINT32_T delay);																			//---ms延时函数
	UINT8_T			(*msgTask)(DHT11_HandlerType *DHT11HandlerType, UINT16_T length, UINT8_T *pVal, UINT8_T msg);			//---消息处理函数
};
 
//---外部调用接口
extern DHT11_HandlerType	g_DHT11_0;
extern pDHT11_HandlerType	pDHT11_0;
 
//---变量定义
DHT11_HandlerType	g_DHT11_0;
pDHT11_HandlerType	pDHT11_0=&g_DHT11_0;
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:
//
UINT8_T DHT11_Init(DHT11_HandlerType *DHT11HandlerType, void(*msgDelayus)(UINT32_T delay), void(*msgDelayms)(UINT32_T delay))
{
#ifdef USE_MCU_STM32
	if ((DHT11HandlerType == NULL|| (DHT11HandlerType->msgPort == NULL))
	{
		return ERROR_1;
	}
	//---使能端口时钟
	GPIOTask_Clock(DHT11HandlerType->msgPort, 1);
	LL_GPIO_InitTypeDef GPIO_InitStruct;
	//---GPIO的初始化
	GPIO_InitStruct.Pin = DHT11HandlerType->msgBit;			//---对应的GPIO的引脚
	GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;					//---配置状态为输出模式
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;			//---GPIO的速度
	GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;				//---输出模式---开漏输出
	GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;						//---上拉使能
	//---初始化端口
	LL_GPIO_Init(DHT11HandlerType->msgPort, &GPIO_InitStruct);
#endif
	GPIO_OUT_1(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit);
	//---延时函数
	if (msgDelayus != NULL)
	{
		DHT11HandlerType->msgDelayus = msgDelayus;
	}
	if (msgDelayms != NULL)
	{
		DHT11HandlerType->msgDelayms = msgDelayms;
	}
	//---消息函数
	DHT11HandlerType->msgTask = NULL;
	return OK_0;
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:
//
UINT8_T DHT11_DeInit(DHT11_HandlerType *DHT11HandlerType)
{
#ifdef USE_MCU_STM32
	LL_GPIO_DeInit(DHT11HandlerType->msgPort);
#endif
	GPIO_OUT_1(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit);
	//---消息函数
	DHT11HandlerType->msgTask = NULL;
	return OK_0;
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:
//
UINT8_T DHT11_RESET(DHT11_HandlerType *DHT11HandlerType)
{
	GPIO_OUT_1(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit);
	//---主机拉高2us 
	if (DHT11HandlerType->msgDelayus != NULL)
	{
		DHT11HandlerType->msgDelayus(2);
	}
	GPIO_OUT_0(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit);
	//---触发开始,总线拉低要大于18ms
	if (DHT11HandlerType->msgDelayms!=NULL)
	{
		DHT11HandlerType->msgDelayms(20);
	}
	//---释放总线
	GPIO_OUT_1(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit);
	//主机拉高20~40us;等待DHT11的低电平响应信号
	if (DHT11HandlerType->msgDelayus != NULL)
	{
		DHT11HandlerType->msgDelayus(30);
	}
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:1:不存在;0:存在 
//
UINT8_T DHT11_Check(DHT11_HandlerType *DHT11HandlerType)
{
	UINT8_T count = 0;
	//---DHT11如果响应的话会拉低总线40~80us
	while (GPIO_GET_STATE(DHT11HandlerType->msgPort,DHT11HandlerType->msgBit)!=0)
	{
		if (DHT11HandlerType->msgDelayus !=NULL)
		{
			DHT11HandlerType->msgDelayus(1);
		}
		count++;
		if (count>100)
		{
			break;
		}
	}
	if (count>100)
	{
		return ERROR_1;
	}
	count = 0;
	//---DHT11高电平数据准备信号再次拉高40~80us
	while (GPIO_GET_STATE(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit) == 0)
	{
		if (DHT11HandlerType->msgDelayus != NULL)
		{
			DHT11HandlerType->msgDelayus(1);
		}
		count++;
		if (count > 100)
		{
			break;
		}
	}
	if (count > 100)
	{
		return ERROR_1;
	}
	return OK_0;
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:1:不存在;0:存在 
//
UINT8_T DHT11_START(DHT11_HandlerType *DHT11HandlerType)
{
	//---触发传输
	DHT11_RESET(DHT11HandlerType);
	//---检测设备
	return DHT11_Check(DHT11HandlerType);
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:位数据“0”的格式为: 50 微秒的低电平和 26-28 微秒的高电平;
/  位数据“1”的格式为: 50 微秒的低电平加 70微秒的高电平
//
UINT8_T DHT11_ReadBit(DHT11_HandlerType *DHT11HandlerType)
{
	UINT8_T count = 0;
	//---等待变为低电平
	while (GPIO_GET_STATE(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit) != 0)
	{
		if (DHT11HandlerType->msgDelayus != NULL)
		{
			DHT11HandlerType->msgDelayus(1);
		}
		count++;
		if (count > 100)
		{
			break;
		}
	}
	count = 0;
	//---等待变高电平
	while (GPIO_GET_STATE(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit) == 0)
	{
		if (DHT11HandlerType->msgDelayus != NULL)
		{
			DHT11HandlerType->msgDelayus(1);
		}
		count++;
		if (count > 100)
		{
			break;
		}
	}
	//---等待40us;数据为0的信号时间为26-28us,1则为70us
	if (DHT11HandlerType->msgDelayus != NULL)
	{
		DHT11HandlerType->msgDelayus(40);
	}
	//---读取状态
	if (GPIO_GET_STATE(DHT11HandlerType->msgPort, DHT11HandlerType->msgBit) != 0)
	{
		return 1;
	}
	return 0;
}
 
///
//函	   数:
//功	   能:
//输入参数: 
//输出参数: 
//说	   明:
//
UINT8_T DHT11_ReadByte(DHT11_HandlerType *DHT11HandlerType)
{
	UINT8_T i = 0, _return = 0;
	for (i=0;i<8;i++)
	{
		_return <<= 1;
		_return |= DHT11_ReadBit(DHT11HandlerType);
	}
	return _return;
}
 
///
//函		数: 
//功		能: 
//输入参数: 
//输出参数: 
//说		明: 
//
UINT8_T DHT11_ReadData(DHT11_HandlerType *DHT11HandlerType)
{
	UINT8_T temp[5= { 0 };
	UINT8_T i= 0;
	for (i=0;i<5;i++)
	{
		temp[i] = DHT11_ReadByte(DHT11HandlerType);
	}
	//---数据校验
	if ((temp[0]+temp[1]+temp[2]+temp[3])!=temp[4])
	{
		return ERROR_1;
	}
	//---温度整数部分
	DHT11HandlerType->msgWenDu = temp[0];
	//---温度小数部分
	DHT11HandlerType->msgWenDu = (DHT11HandlerType->msgWenDu<<8)+temp[1];
	//---湿度整数部分
	DHT11HandlerType->msgShiDu = temp[2];
	//---湿度小数部分
	DHT11HandlerType->msgShiDu = (DHT11HandlerType->msgShiDu << 8+ temp[3];
	return OK_0;
}

驱动DHT11传感器,首先需要连接DHT11传感器到STM32的GPIO引脚上。然后,需要编写STM32代码来读取DHT11传感器的数据。 以下是一个简单的代码示例,可以读取DHT11传感器的数据: ```c #include "stm32f10x.h" #define DHT11_DATA_PIN GPIO_Pin_0 #define DHT11_DATA_PORT GPIOA void delay_us(uint32_t us) { // 延时函数,us为微秒数 uint32_t i; for (i = 0; i < us * 8; i++); } void DHT11_start() { // 发送起始信号 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_DATA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(18000); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(20); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); } uint8_t DHT11_read_bit() { // 读取一个位的数据 while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); delay_us(40); if(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET) { while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); return 1; } else { return 0; } } uint8_t DHT11_read_byte() { // 读取一个字节的数据 uint8_t i, byte = 0; for (i = 0; i < 8; i++) { byte <<= 1; byte |= DHT11_read_bit(); } return byte; } uint8_t DHT11_read(uint8_t *humidity, uint8_t *temperature) { // 读取温湿度数据 uint8_t data[5]; uint8_t i; DHT11_start(); if(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET) { while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); while(GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); for (i = 0; i < 5; i++) { data[i] = DHT11_read_byte(); } if(data[0] + data[1] + data[2] + data[3] == data[4]) { *humidity = data[0]; *temperature = data[2]; return 1; } else { return 0; } } else { return 0; } } int main(void) { uint8_t humidity, temperature; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); while(1) { if(DHT11_read(&humidity, &temperature)) { // 读取成功 } else { // 读取失败 } } } ``` 在这个代码示例中,首先定义了DHT11传感器的引脚和端口。然后,定义了一些辅助函数,如延时函数、发送起始信号和读取一个位数据等。最后,在主函数中循环读取DHT11传感器的温湿度数据。 需要注意的是,DHT11传感器的数据读取需要严格按照一定的时间序列进行,否则可能会出现读取错误。因此,在编写代码时需要仔细调试和测试。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值