DHT11温湿度传感器C语言例程
#include “stm8s.h” #include “tim1.h” #include <stdarg.h>
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 / /***********************************************************************
- 函数名:UART1_printf
- 描述 :格式化输出,类似于C库中的printf,但这里没有用到C库
- 输入 :-UARTx 串口通道,这里只用到了串口1,即UART1
-
-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
/**
- @brief Reports the name of the source file and the source line number
- where the assert_param error has occurred.
- @param file: pointer to the source file name
- @param line: assert_param error line source number
- @retval : None / void assert_failed(u8 file, u32 line) { /* User can add his own implementation to report the file name and line number, ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) */
/* Infinite loop */ while (1) { } } #endif
说明:DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。所以常用于扬尘监测和自动气象站中。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。