STM32使用DHT11读取温湿度以及usart串口显示乱码解决

使用开发板为stm32f103. USART串口显示乱码问题往下翻
上原理图:
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第1张图片
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第2张图片
DHT11数据传送过程解释:
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第3张图片
步骤一:
DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境
温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的
DATA 引脚处于输入状态,时刻检测外部信号。
步骤二:
微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms),
然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变
高,等待 DHT11 作出回答信号,发送信号如图所示:
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第4张图片
图 4 主机发送起始信号
步骤三:
DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒
的高电平后的数据接收,发送信号如图所示:
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第5张图片
图 5 从机响应信号
步骤四: 由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”
的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74
微秒的高电平。位数据“0”、“1”格式信号如图所示:
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第6张图片

DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 54 微秒后转为输入状态,由于上拉电阻随
之变为高电平。但 DHT11 内部重测环境温湿度数据,并记录数据,等待外部信号的到来。
以上就是具体数据读取传送不揍
下面我们看一下伪代码实现:

(1)配置引脚为输出:推挽输出;
(2)输出高电平;延时100ms;
(3)输出低电平;延时20ms;
(4)输出高电平;
(5)配置引脚为输入:浮空输入;
(6)等待从机拉低:(while(引脚电平为高电平);)
(7)等待从机拉高:(while(引脚为低电平);)
(8)取数据:
a)       Dat[5]={0};
b        )For(i=0;i<5;i++)
c)      {
d)      For(j=0;j<8;j++)
e)      {
f)     While();//等待拉低;
g)     While();//等待拉高
h)      //延时30us;
i )      Dat[i]<<=1;
j)       If(输入数据位为1/0)
          Dat[i] |=0x01;
k)}
l)}
(9)校验:前4字节的数据取和的末8位和校验值比较;
(10)取对应的温湿度数据;

注意延时操作,最好使用滴答(毫秒延时)定时器结合系统延时(微妙延时)
下面具体看一下代码的实现

#define DHT11_OUT 1
#define DHT11_IN 2
//PB6
void DHT11_Config(uint8_t p)
{
     
	RCC->APB2ENR |=(0x01<<3);//开B端口时钟
	
	GPIOB->CRL &=~(0x0F<<24);//端口配置清0
	
	if(p==DHT11_OUT)
		GPIOB->CRL |=(0x01<<24);//通用推挽输出
	else if(p==DHT11_IN)
		GPIOB->CRL |=(0x01<<27);//浮空输入
}

#define DHT11(x) (x?(GPIOB->ODR |=(0x01<<6)):(GPIOB->ODR &=~(0x01<<6)))//高低电平
#define DHT11_Val (GPIOB->IDR & (0x01<<6))  //0100 0000=0x40输入数据寄存器


void DHT11_read(float *Hum,float *Temp)//Hum:湿度   Temp:温度
{
     
	uint8_t rdata[5]={
     0};
	uint8_t i,j;
	
//STM32的GPIO引脚配置为输出,输出高电平;
	DHT11_Config(DHT11_OUT);
	DHT11(1);//输出高电平
	DelayMs(100);
	
//GPIO拉低,保持18ms~30ms,再拉高;----起始信号
	DHT11(0);//输出低电平 保持20ms
	DelayMs(20);
	DHT11(1);//拉高电平

//GPIO引脚配置为输入模式;
	DHT11_Config(DHT11_IN);
//等待DHT11拉低;while(总线为高电平);
	while(DHT11_Val);
	
//等待DHT11拉高;while(总线为低电平);-----响应信号
	while(DHT11_Val==0);

	for(i=0;i<5;i++)
	{
     
		for(j=0;j<8;j++)
		{
     
			//等待DHT11拉低;while(总线为高电平);
			while(DHT11_Val);//等待数据发送
			
			//等待DHT11拉高;while(总线为低电平);
			while(DHT11_Val==0);//等待数据发送
			
			rdata[i] <<=1;
			
			//判断0/1:延时30us~50us之间,判断当前输入的电平高低。
			DelayUsCnt(40);
			if(DHT11_Val)//此刻输入的是高电平为“1”
			{
     
				rdata[i] +=1;
			}
			else//输入为0
			{
     
				rdata[i] +=0;
			}
		}
	}
	
	if(rdata[0]+rdata[1]+rdata[2]+rdata[3] == rdata[4])
	{
     
		*Hum  = (float)(rdata[0]+rdata[1]/10.0);//湿度值读取
		
		//温度值读取
		if(rdata[3] & (0x01<<8))   //正温度/负温度
		{
     
			rdata[3] &=~ (0x80);
			*Temp = -(float)(rdata[2]+rdata[3]/10.0);
		}
		else
			*Temp = (float)(rdata[2]+rdata[3]/10.0);
	}
}

DHT11读取数据最好间隔2s读取一次

**

USART串口显示乱码问题

**

大部分都是系统时钟的问题
举个例子,我的开发板是stm32f103,但是我的晶振是12000000的,系统默认的是8000000

STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第7张图片
我这个已经改成12000000了

你以为已近改好了嘛!!!还没有哈
system_stm32f10x.c 中
注意到/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz /这一句没
HSE上面已近改成了12000000,但是这里倍频仍然是9.
12x6=72
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第8张图片
RCC_CFGR_PLLMULL6注意这个地方
这个地方是我已近改过的原本是这个RCC_CFGR_PLLMULL9(9倍频)
我们跳过去看看
STM32使用DHT11读取温湿度以及usart串口显示乱码解决_第9张图片
注意后面的注释 PLL INPUT CLOCK
N
你晶振是12000000,系统时钟是72000000,所以倍频这里也要改为配套的哟!
这里我改后就是如第一张图所示RCC_CFGR_PLLMULL6

你可能感兴趣的:(stm32,stm32,单片机,嵌入式,串口通信)