使用开发板为stm32f103. USART串口显示乱码问题往下翻
上原理图:
DHT11数据传送过程解释:
步骤一:
DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境
温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的
DATA 引脚处于输入状态,时刻检测外部信号。
步骤二:
微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms),
然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变
高,等待 DHT11 作出回答信号,发送信号如图所示:
图 4 主机发送起始信号
步骤三:
DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒
的高电平后的数据接收,发送信号如图所示:
图 5 从机响应信号
步骤四: 由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”
的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74
微秒的高电平。位数据“0”、“1”格式信号如图所示:
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
我这个已经改成12000000了
你以为已近改好了嘛!!!还没有哈
在system_stm32f10x.c 中
注意到/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz /这一句没
HSE上面已近改成了12000000,但是这里倍频仍然是9.
12x6=72
RCC_CFGR_PLLMULL6
注意这个地方
这个地方是我已近改过的原本是这个RCC_CFGR_PLLMULL9
(9倍频)
我们跳过去看看
注意后面的注释 PLL INPUT CLOCKN
你晶振是12000000,系统时钟是72000000,所以倍频这里也要改为配套的哟!
这里我改后就是如第一张图所示RCC_CFGR_PLLMULL6