4、串行接口 (单线双向)
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
1.通讯过程如图1所示
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
数字0信号表示方法如图4所示
数字1信号表示方法.如图5所示
介绍完DHT11后,上传我写的程序,由于没有时间,这个弄的比较简单,希望大家见谅,以后有必要再进行更改,另外我把程序写在一个文件夹里,是为了方便大家浏览,我平时写程序不是这样的,呵呵。
#include "msp430x22x4.h"
#include"stdio.h"
#define DHT11_OUTPUT P2DIR|=BIT0
#define DHT11_INPUT P2DIR&=~BIT0
#define DHT11_H P2OUT|=BIT0
#define DHT11_L P2OUT&=~BIT0
#define DHT11_IN (P2IN&BIT0)
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define CPU (16000000)
#define delay_us(x) (__delay_cycles((double)x*CPU/1000000.0))
#define delay_ms(x) (__delay_cycles((double)x*CPU/1000.0))
uchar start_DHT11(void);
uchar DHT11_ReadChar(void);
void dht11(void);
uchar DHT11T_Data_H, DHT11T_Data_L, DHT11RH_Data_H, DHT11RH_Data_L,CheckData_temp;
void put(uchar *x)
{
while(*x)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF=*x;
x++;
}
}
void putc(char *x)
{
while(*x)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF=*x;
x++;
}
}
void wellcome()
{
put("*************************************\n");
put("******** hello,eeworld! ********\n");
put("******** this is mengzhilv! ********\n");
put("******** Copyright @ 2011 ********\n");
put("*************************************\n\n");
delay_ms(10);
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_16MHZ; // Set DCO
DCOCTL = CALDCO_16MHZ;
P1DIR |=BIT0;
P1OUT &=~BIT0;
P1DIR |=BIT1;
P1OUT &=~BIT1;
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
P3DIR |=BIT4; //P3.4为输出方向
//Baud rate divider with 1MHz = 1MHz/9600 = ~104.2
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0x82; // 16MHz 9600
UCA0BR1 = 0x06; // 16MHz 9600
UCA0MCTL = UCBRS1; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
delay_us(100);
wellcome();
put("**********DHT11 TEST**********\n");
delay_ms(1000);
while(1)
{
dht11();
}
}
uchar start_DHT11(void)
{
uchar TData_H_temp,TData_L_temp,RHData_H_temp,RHData_L_temp,checktemp;
uchar presence,flag;
uint count;
DHT11_OUTPUT;
DHT11_L; //拉低18ms以上
delay_ms(20);
DHT11_H;
DHT11_INPUT;
delay_us(40);
presence=DHT11_IN;
if(!presence)
{
count=2;
while((!DHT11_IN)&&count++);//等待低电平
count=2;
while((DHT11_IN)&&count++);//等待高电平
RHData_H_temp = DHT11_ReadChar();
RHData_L_temp = DHT11_ReadChar();
TData_H_temp = DHT11_ReadChar();
TData_L_temp = DHT11_ReadChar();
CheckData_temp = DHT11_ReadChar();
DHT11_OUTPUT;
DHT11_H;
checktemp = (RHData_H_temp + RHData_L_temp + TData_H_temp + TData_L_temp);
if (checktemp == CheckData_temp) {
DHT11RH_Data_H = RHData_H_temp;
DHT11RH_Data_L = RHData_L_temp;
DHT11T_Data_H = TData_H_temp;
DHT11T_Data_L = TData_L_temp;
flag=1;
}
}
P1OUT |=BIT0;
return flag;
}
uchar DHT11_ReadChar(void)
{
unsigned char dat;
unsigned int count; //计数防止死等
unsigned char i;
for(i=0;i<8;i++)
{
count=2;
while((!DHT11_IN)&&count++); //等待50us低电平结束
delay_us(40); //40us
dat <<= 1; //50us低电平+28us高电平表示'0'
if(DHT11_IN) //50us低电平+70us高电平表示'1'
dat |= 1;
count=2;
while((DHT11_IN)&&count++);
if(count==1) //超时则跳出for循环
break;
}
return dat;
}
void dht11()
{
char c[40];
uchar o;
o=start_DHT11();
P1OUT |=BIT1;
delay_ms(300);
P1OUT &=~BIT1;
delay_ms(300);
if (o)
{
put("DHT11 EXIST AND ACQUIRE SUCCESSFUL!\n");
delay_ms(10);
sprintf(c, "%d.%d %d.%d %d\r\n",DHT11RH_Data_H,DHT11RH_Data_L,DHT11T_Data_H,DHT11T_Data_L,CheckData_temp);
putc(c);
}
}