#include “stm8s.h”
#include “tim1.h”
#include
void Init_UART1(void);
void UART1_printf( uint8_t *Data,…);
typedef struct
{
uint8_t humi_int;
uint8_t humi_deci;
uint8_t temp_int;
uint8_t temp_deci;
uint8_t check_sum;
} DHT11_Data_TypeDef;
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef * DHT11_Data);
void main(void)
{
DHT11_Data_TypeDef DHT11_Data;
CLK_HSICmd(ENABLE);//开始内部高频RC
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);//不分频
// GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_IT);
GPIO_Init(GPIOA,GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
// IWDG_Conf();
Tim1_Init();
//Tim2_Timer_Init();
Init_UART1();
enableInterrupts();
UART1_printf("\r\n***dht11 温湿度传感器实验***\r\n");
while (1)
{
if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)
{
UART1_printf("\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",
DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
}
delay_ms(7200);
}
}
static uint8_t DHT11_ReadByte ( void )
{
uint8_t i, temp=0;
for(i=0;i<8;i++)
{
/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/
while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==RESET);
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
delay_ms(2);//延时x us 这个延时需要大于数据0持续的时间即可
if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)!=RESET)/* x us后仍为高电平表示数据“1” */
{
/* 等待数据1的高电平结束 */
while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)!=RESET);
temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行
}
else // x us后为低电平表示数据“0”
{
temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
}
}
return temp;
}
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
/输出模式/
GPIO_Init(GPIOA,GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
/主机拉低/
GPIO_WriteLow(GPIOA,GPIO_PIN_3);
/延时18ms/
delay_ms(720);
/*总线拉高 主机延时30us*/
GPIO_WriteHigh(GPIOA,GPIO_PIN_3);
delay_ms(1); //延时30us
/*主机设为输入 判断从机响应信号*/
GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT);
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)!=RESET);
/*开始接收数据*/
DHT11_Data->humi_int= DHT11_ReadByte();
DHT11_Data->humi_deci= DHT11_ReadByte();
DHT11_Data->temp_int= DHT11_ReadByte();
DHT11_Data->temp_deci= DHT11_ReadByte();
DHT11_Data->check_sum= DHT11_ReadByte();
/*读取结束,引脚改为输出模式*/
GPIO_Init(GPIOA,GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);
/*主机拉高*/
GPIO_WriteHigh(GPIOA,GPIO_PIN_3);
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return SUCCESS;
else
return ERROR;
}
else
return ERROR;
}
void Init_UART1(void)
{
UART1_DeInit();
UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
UART1_Cmd(ENABLE);
}
/********************************************************
函数名:itoa
描述 :将整形数据转换成字符串
输入 :-radix =10 表示10进制,其他结果为0
-value 要转换的整形数
-buf 转换后的字符串
-radix = 10
输出 :无
返回 :无
调用 :被USART1_printf()调用
*******************************************************/
static char *itoa(int value, char *string, int radix)
{
int i, d;
int flag = 0;
char *ptr = string;
/* This implementation only works for decimal numbers. */
if (radix != 10)
{
*ptr = 0;
return string;
}
if (!value)
{
*ptr++ = 0x30;
*ptr = 0;
return string;
}
/* if this is a negative value insert the minus sign. */
if (value < 0)
{
*ptr++ = ‘-’;
/* Make the value positive. */
value *= -1;
}
for (i = 10000; i > 0; i /= 10)
{
d = value / i;
if (d || flag)
{
*ptr++ = (char)(d + 0x30);
value -= (d * i);
flag = 1;
}
}
/* Null terminate the string. */
*ptr = 0;
return string;
} /* NCL_Itoa /
/***********************************************************************
-Data 要发送到串口的内容的指针
-... 其他参数
典型应用 UART1_printf( "\r\n this is a demo \r\n" );
UART1_printf( "\r\n %d \r\n", i );
UART1_printf( "\r\n %s \r\n", j );
***************************************************************************/
void UART1_printf( uint8_t *Data,…)
{
const char *s;
int d;
char buf[16];
va_list ap;
va_start(ap, Data);
while ( *Data != 0) // 判断是否到达字符串结束符
{
if ( *Data == 0x5c ) //'\'
{
switch ( *++Data )
{
case 'r': //回车符
UART1_SendData8(0x0d);
Data ++;
break;
case 'n': //换行符
UART1_SendData8(0x0a);
Data ++;
break;
default:
Data ++;
break;
}
}
else if ( *Data == '%')
{ //
switch ( *++Data )
{
case 's': //字符串
s = va_arg(ap, const char *);
for ( ; *s; s++)
{
UART1_SendData8(*s);
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
Data++;
break;
case 'd': //十进制
d = va_arg(ap, int);
itoa(d, buf, 10);
for (s = buf; *s; s++)
{
UART1_SendData8(*s);
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
Data++;
break;
default:
Data++;
break;
}
} /* end of else if */
else UART1_SendData8(*Data++);
while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}
}
#ifdef USE_FULL_ASSERT
/**
/* Infinite loop */
while (1)
{
}
}
#endif
说明:DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。所以常用于扬尘监测和自动气象站中。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。