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