stm32串口控制dht11温湿度传感器

stm32串口控制dht11温湿度传感器


实验结果

    通过串口向stm32发送字符串”open",接收到“open"后温湿度开始工作,采集数据并将采集到的数据通过串口助手打印出来。

温湿度传感器相关代码

dht11.c

#include "dht11.h"

/*
DHT11初始化

函数名称:DHT11_init
函数参数:无
函数返回值:无
PC8
*/
void DHT11_init(void)
{
    
    
	//开时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
	//配置IO口
	GPIO_InitTypeDef GPIO_InitStructrue;
	GPIO_InitStructrue.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructrue.GPIO_Pin=GPIO_Pin_8;
	GPIO_InitStructrue.GPIO_OType=GPIO_OType_OD;
	GPIO_InitStructrue.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_InitStructrue.GPIO_Speed=GPIO_Low_Speed;
	GPIO_Init(GPIOC,&GPIO_InitStructrue);

	//越过1s的不稳定时间
	delay_ms(500);
	delay_ms(500);

	DATA_H;

}

/*
	DHT11开始

	函数名称:DHT11_start
	函数参数:无
	函数返回值:无
*/
void DHT11_start(void)
{
    
    
	DATA_L;
	delay_ms(20);
	DATA_H;
}

/*
DHT11应答

函数名称:DHT11_recask
函数参数:无
函数返回值:返回1表示响应失败,0表示成功
*/
uint8_t DHT11_recask(void)
{
    
    
	uint8_t cnt =0;
	while(DATA_READ == 1) //等待高电平变成低电平,产生响应信号
	{
    
    
		cnt++;
		delay_us(20);
		if(cnt>5)
		{
    
    
			return 1;
		}
	}
	while(DATA_READ == 0); //等待低电平变成高电平,83us
	while(DATA_READ == 1); //等待高电平变成低电平,87us

	return 0;
}

/*
DHT11应答

函数名称:DHT11_recdata
函数参数:无
函数返回值:返回数据
*/
uint8_t DHT11_recdata(void)
{
    
    
	uint8_t i=0;
	uint8_t data=0;

	for(i=0;i<8;i++)
	{
    
    
		while(DATA_READ == 0); //等待低电平变成高电平,越过54us低电平时间
		delay_us(45);
		data=data<<1;//空出最低位
		if(DATA_READ)
		{
    
    
			data |= 0x01;
		}

		while(DATA_READ == 1 );//等待高电平时间结束
	}

	return data;
}

/*
函数名称:DHT11_data
函数参数:uint8_t *temper uint8_t *hum
函数返回值:返回数据
*/
uint8_t DHT11_data(float *hum,float *temper)
{
    
    
	uint8_t byte[5] = {
    
    0};

	DHT11_start();//启动信号开始传输

	if(DHT11_recask()==1)
	{
    
    
		return 1;
	}

	byte[0]=DHT11_recdata();//温度整数部分
	byte[1]=DHT11_recdata();//温度小数部分
	byte[2]=DHT11_recdata();//湿度整数部分
	byte[3]=DHT11_recdata();//湿度小数部分
	byte[4]=DHT11_recdata();//校验位
	
	if(byte[4]==((byte[0]+byte[1]+byte[2]+byte[3])&0xff))
	{
    
    
		*hum=byte[0]/1.0+byte[1]/10.0;

		*temper=byte[2]/1.0+byte[3]/10.0;
	}
	return 0;
}

dht11.h

#ifndef _DHT11_H
#define _DHT11_H

#include "stm32f4xx.h"                  // Device header
#include "delay.h"


void DHT11_init(void);
void DHT11_start(void);
uint8_t DHT11_recask(void);
uint8_t DHT11_recdata(void);
uint8_t DHT11_data(float *hum,float *temperhu);

#define DATA_H GPIO_SetBits(GPIOC,GPIO_Pin_8)
#define DATA_L GPIO_ResetBits(GPIOC,GPIO_Pin_8)

#define DATA_READ GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8)

#endif

延时函数

delay.c

#include "delay.h"                  // Device header


/*

毫秒级延时

函数名称:delay_ms()
函数参数:uint16_t ms
函数返回值:无

*/

void delay_ms(uint16_t ms)
{
    
    
//关闭计数器
SysTick ->CTRL = 0;

//写入重载值 21 000 * ms -1    最大792ms
SysTick ->LOAD = 21000 * ms -1;
//清零计数器
SysTick ->VAL = 0;
//使能计数器并且选择时钟源
SysTick ->CTRL = 0x00000001;
//等待标志位出现(计数完成)
while(!(SysTick ->CTRL & 0x00010000));

//关闭计数器
SysTick ->CTRL = 0;

}


/*

微秒级延时

函数名称:delay_us()
函数参数:uint16_t us
函数返回值:无

*/
void delay_us(uint16_t us)
{
    
    
//关闭计数器
SysTick ->CTRL = 0;

//写入重载值 168000 * ms -1    最大99ms
SysTick ->LOAD = 168 * us -1;
//清零计数器
SysTick ->VAL = 0;
//使能计数器
SysTick ->CTRL = 0x00000005;
//等待标志位出现(计数完成)
while(!(SysTick ->CTRL & 0x00010000));

//关闭计数器
SysTick ->CTRL = 0;

}


/*

延时1s

函数名称:delay_1s()
函数参数:无
函数返回值:无

*/
void delay_1s(void)
{
    
    
delay_ms(500);
delay_ms(500);

}

delay.h

#ifndef _DELAY_H
#define _DELAY_H

#include "stm32f4xx.h"                  // Device header

void delay_ms(uint16_t ms);
void delay_us(uint16_t us);
void delay_1s(void);

#endif

串口相关代码

usart.c

#include "usart.h"
#include "stdio.h"
/*
usart_init
PA9/PA10
*/

void usart1_init(uint32_t baud){
    
    
	//开启串口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	//GPIO时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);


	GPIO_InitTypeDef GPIO_InitStructrue;

	GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructrue.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructrue.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructrue.GPIO_Speed = GPIO_Medium_Speed;


	//串口初始化
	USART_InitTypeDef USART_InitStructrue;

	USART_InitStructrue.USART_BaudRate = baud;//波特率
	USART_InitStructrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流控制
	USART_InitStructrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_InitStructrue.USART_Parity = USART_Parity_No;//奇偶校验位
	USART_InitStructrue.USART_StopBits = USART_StopBits_1;//停止位
	USART_InitStructrue.USART_WordLength = USART_WordLength_8b;//数据长度

	//清除标志位
	USART_ClearFlag(USART1,USART_FLAG_TC);

	GPIO_Init(GPIOA, &GPIO_InitStructrue);
	USART_Init(USART1, &USART_InitStructrue);

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1 ;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);

	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//接收中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//空闲中断
	USART_Cmd(USART1, ENABLE);
}
/*
usart1_sendbyte
PA9/PA10
*/
void usart1_sendByte(uint8_t data){
    
    

	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );
	USART_SendData(USART1, data);

}


/*
usart1_sendArray
PA9/PA10
*/

uint8_t ch[10] = {
    
    0}; 

void usart1_sendArray(uint8_t *array){
    
    

	for(uint8_t i = 0; i < sizeof(ch); i++){
    
    

	usart1_sendByte(ch[i]);

}

}

/*
usart1_sendString
PA9/PA10
*/

void usart1_sendString(uint8_t *str){
    
    
	while(*str != '\0'){
    
    
	usart1_sendByte(*str);
	str++;
	}
}


#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{
    
     
	int handle; 
	/* Whatever you require here. If the only file you are using is */ 
	/* standard output using printf() for debugging, no file handling */ 
	/* is required. */ 
	}; 
	/* FILE is typedef’ d in stdio.h. */ 
	FILE __stdout;       
	//定义_sys_exit()以避免使用半主机模式    
	int _sys_exit(int x) 
	{
    
     
		x = x; 

		return 0;
	} 
	//重定义fputc函数 
	int fputc(int ch, FILE *f)
	{
    
          
		while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
		USART1->DR = (u8) ch;      
		return ch;
	}
#endif


//中断服务函数

uint8_t recbuff[SIZE]={
    
    0};
uint8_trecbuff_i = 0;

void USART1_IRQHandler(void){
    
    

	//判断发生什么样的中断
	if(USART_GetITStatus( USART1, USART_IT_RXNE) == SET)
	{
    
    

		//清除对应的中断标志位
		USART_ClearITPendingBit( USART1,USART_IT_RXNE);

		recbuff[recbuff_i] = USART_ReceiveData(USART1);
		recbuff_i++;

	}


	//判断发生什么样的中断
	if(USART_GetITStatus( USART1, USART_IT_IDLE) == SET)
	{
    
    
		//清除对应的中断标志位
		USART1->SR;
		USART1->DR;

		//处理紧急事件 
		recbuff[recbuff_i] = '\0';
		recbuff_i=0;
	}
	
}

usart.h

#ifndef _USART_H
#define _USART_H


#include "stm32f4xx.h"

#define SIZE 10

extern uint8_t recbuff[SIZE];

void usart1_init(uint32_t baud);
void usart1_sendByte(uint8_t data);
void usart1_sendArray(uint8_t *array);
void usart1_sendString(uint8_t *str);

#endif

main函数

main.c,通过strcmp来判断recbuff(串口发送过来的字符串)与”open“是否一样,如果一样,返回值为0。

#include "main.h"                  // Device header

int main(void)
{
    
    
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	usart1_init(115200);
	DHT11_init();
	float temper,hum;

	while(1)
	{
    
    
		if(strcmp(recbuff,"open")==0)
		{
    
    
			DHT11_data(&hum,&temper);

			printf("湿度为:%.2f\n",hum);
			printf("温度为:%.2f\n",temper);

			for(uint8_t i = 0; i < SIZE ;i++){
    
    
				recbuff[i]=0;
			}
		}
	}

}

main.h

#ifndef _MAIN_H
#define _MAIN_H



#include "stm32f4xx.h"                  // Device header


#include "delay.h"

#include "usart.h"
#include "dht11.h"
#include <stdio.h>
#include <string.h>


#endif

猜你喜欢

转载自blog.csdn.net/crabxd/article/details/129591527