读取传感器DHT11的湿度和温度数据
使用NUC240的GPIO (PA.0)和TIMER0读取DHT11的湿度和温度数据。DHT11是个常见的数字湿度、温度传感器。DHT11使用简化的单总线通讯方式交换数据。数据长度为40位,数据格式如所下表所示:
藉由GPIO和TIMER0,使用者可以产生与DHT11通讯的波形。请从以下链接,参考DHT11的规格数据,了解更详细的时序图。
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* $Revision: 1 $
* $Date: 19/06/26 8:14p $
* [url=home.php?mod=space&uid=247401]@brief[/url] Use GPIO and TIMER0 to read DHT11 temperature and humidity
* data
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "NUC230_240.h"
/*---------------------------------------------------------------------------*/
/* Define */
/*---------------------------------------------------------------------------*/
#define PLL_CLOCK 72000000
#define Data_Pin PA0
#define Data_Port PA
#define Data_PinMsk BIT0
#define Max_Data0_Time 40
/*---------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------*/
uint8_t g_u8Humidity_Int, g_u8Humidity_Dec;
uint8_t g_u8Temperature_Int, g_u8Temperature_Dec;
/*---------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------*/
uint32_t DHT11_Reset(void);
uint32_t DHT11_Read(void);
void SYS_Init(void);
void TMR0_Init(void);
void UART0_Init(void);
void Delay_mS(uint32_t m_second);
uint32_t DHT11_Reset(void)
{
uint32_t u32_poll_time;
/* The Quasi-bidirection mode could be used as input with pull-up enable */
GPIO_SetMode(Data_Port, Data_PinMsk, GPIO_PMD_QUASI);
/* Send out start signal to DHT11 */
/* Set data pin level from high to low */
Data_Pin = 1;
Data_Pin = 0;
/* Take at least 18 ms to ensure DHT11's detection of signal */
CLK_SysTickDelay(18000);
/* Pull up data pin */
Data_Pin = 1;
/* Record current timer counter value */
u32_poll_time = TIMER_GetCounter(TIMER0);
/* Wait response from DHT11 by pulling down data pin */
while (1)
{
if (Data_Pin == 0)
{
break;
}
if ((TIMER_GetCounter(TIMER0) - u32_poll_time) > 1000)
/* DHT11 doesn't response over 1 ms */
return FALSE;
}
/* Wait until DHT11 pulls up data pin level */
while (1)
{
if (Data_Pin == 1)
{
break;
}
}
/* Send start signal successfully */
return TRUE;
}
uint32_t DHT11_Read(void)
{
uint32_t i;
uint32_t u32_prev_time;
uint8_t u8Checksum;
/* Init TIMER0 to measure high level time */
TMR0_Init();
/* Start communicate with DHT11 */
if (DHT11_Reset() == TRUE)
{
/* Wait until DHT11 starts data transmission */
while (Data_Pin == 1);
/* A complete data transmission is 40 bits, DHT11 sends MSB first */
/* 1st 8 bits is humidity integral data */
g_u8Humidity_Int = 0;
for (i = 0; i < 8; i++)
{
/* Shift current data for next bit */
g_u8Humidity_Int = g_u8Humidity_Int << 1;
/* Wait until DHT11 pull high data pin */
while (Data_Pin == 0);
/* Measure the high level time to determine the data bit */
u32_prev_time = TIMER_GetCounter(TIMER0);
while (Data_Pin == 1);
if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
{
g_u8Humidity_Int |= 0x01;
}
}
/* 2nd 8 bits is humidity decimal data */
g_u8Humidity_Dec = 0;
for (i = 0; i < 8; i++)
{
/* Shift current data for next bit */
g_u8Humidity_Dec = g_u8Humidity_Dec << 1;
/* Wait until DHT11 pull high data pin */
while (Data_Pin == 0);
/* Measure the high level time to determine the data bit */
u32_prev_time = TIMER_GetCounter(TIMER0);
while (Data_Pin == 1);
if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
{
g_u8Humidity_Dec |= 0x01;
}
}
/* 3rd 8 bits is temperature integral data */
g_u8Temperature_Int = 0;
for (i = 0; i < 8; i++)
{
/* Shift current data for next bit */
g_u8Temperature_Int = g_u8Temperature_Int << 1;
/* Wait until DHT11 pull high data pin */
while (Data_Pin == 0);
/* Measure the high level time to determine the data bit */
u32_prev_time = TIMER_GetCounter(TIMER0);
while (Data_Pin == 1);
if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
{
g_u8Temperature_Int |= 0x01;
}
}
/* 4th 8 bits is temperature decimal data */
g_u8Temperature_Dec = 0;
for (i = 0; i < 8; i++)
{
/* Shift current data for next bit */
g_u8Temperature_Dec = g_u8Temperature_Dec << 1;
/* Wait until DHT11 pull high data pin */
while (Data_Pin == 0);
/* Measure the high level time to determine the data bit */
u32_prev_time = TIMER_GetCounter(TIMER0);
while (Data_Pin == 1);
if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
{
g_u8Temperature_Dec |= 0x01;
}
}
/* 5th 8 bits is checksum */
u8Checksum = 0;
for (i = 0; i < 8; i++)
{
/* Shift current data for next bit */
u8Checksum = u8Checksum << 1;
/* Wait until DHT11 pull high data pin */
while (Data_Pin == 0);
/* Measure the high level time to determine the data bit */
u32_prev_time = TIMER_GetCounter(TIMER0);
while (Data_Pin == 1);
if ((TIMER_GetCounter(TIMER0) - u32_prev_time) > Max_Data0_Time)
{
u8Checksum |= 0x01;
}
}
/* Stop TIMER0 */
TIMER_Stop(TIMER0);
/* Compare received data and checksum */
if ((uint8_t)(g_u8Humidity_Int + g_u8Humidity_Dec + g_u8Temperature_Int + g_u8Temperature_Dec) == \
u8Checksum)
{
return TRUE;
}
else
{
printf("Checksum error!\n");
return FALSE;
}
}
else
{
/* Stop TIMER0 */
TIMER_Stop(TIMER0);
printf("DHT11 is no response.\n");
return FALSE;
}
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable Internal RC 22.1184MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
/* Waiting for Internal RC clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(PLL_CLOCK);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and CycylesPerUs automatically. */
SystemCoreClockUpdate();
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Enable TIMER0 module clock */
CLK_EnableModuleClock(TMR0_MODULE);
/* Select UART module clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));
/* Select TIMER0 module clock source */
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HCLK, NULL);
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFP = (SYS->GPB_MFP & ~(SYS_GPB_MFP_PB0_Msk | SYS_GPB_MFP_PB1_Msk)) | \
(SYS_GPB_MFP_PB0_UART0_RXD | SYS_GPB_MFP_PB1_UART0_TXD);
}
void UART0_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset UART0 */
SYS_ResetModule(UART0_RST);
/* Configure UART0 and set UART0 Baudrate */
UART_Open(UART0, 115200);
}
void TMR0_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init TIMER */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset TIMER0 */
SYS_ResetModule(TMR0_RST);
/* Set periodic mode */
TIMER0->TCSR = TIMER_PERIODIC_MODE;
/* Set prescaler value to make unit count time is 1 us */
/* Timer clock input is HCLK = 72 MHz, prescaler value is HCLK/(10^6) - 1 = 71 */
TIMER_SET_PRESCALE_VALUE(TIMER0, SystemCoreClock / 1000000 - 1);
/* Set 24-bit comapre register value to maximum value 0xFFFFFF */
TIMER_SET_CMP_VALUE(TIMER0, 0xFFFFFF);
/* Enable TDR_EN to make TDR register be updated continuously to monitor 24-bit up counter value */
TIMER0->TCSR |= TIMER_TCSR_TDR_EN_Msk;
/* Start TIMER0 */
TIMER_Start(TIMER0);
}
void Delay_mS(uint32_t m_second)
{
uint32_t i;
for (i = 0; i < m_second; i++)
{
TIMER_Delay(TIMER0, 1000);
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Init System, peripheral clock and multi-function I/O */
SYS_Init();
/* Lock protected registers */
SYS_LockReg();
/* Init UART0 for printf */
UART0_Init();
printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
printf("+--------------------------------------------------+\n");
printf("| Read DHT11 data Sample Code |\n");
printf("| Use GPIO(PA.0) and TIMER0 to read DHT11 data |\n");
printf("| Please connect PA.0 to DHT11 data pin |\n");
printf("+--------------------------------------------------+\n\n");
while (1)
{
/* Delay 1.5 seconds */
Delay_mS(1500);
if (DHT11_Read() == TRUE)
{
printf("Humidity: %d.%d, ", g_u8Humidity_Int, g_u8Humidity_Dec);
printf("Temperature: %d.%d\n", g_u8Temperature_Int, g_u8Temperature_Dec);
}
}
}
/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/
|