Producción de reloj electrónico keil basado en RASC (Renesas RA) (10) - lectura de datos de temperatura y humedad DHT11

descripción general

Este artículo presenta cómo controlar el sensor de humedad DH11 y realizar la impresión de datos del puerto serie actual.
El sensor digital de temperatura y humedad DHT11 es un sensor compuesto de temperatura y humedad con salida de señal digital calibrada.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

preparación de hardware

Primero, debe preparar una placa de desarrollo. Aquí estoy preparando una placa de desarrollo con el modelo de chip R7FA2E1A72DFL:

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

videotutorial

https://www.bilibili.com/video/BV1e94y1C7YV/

Producción de reloj electrónico keil basado en RASC (Renesas RA)----(10) Leer datos de temperatura y humedad DHT11

parametros del producto

El rango de medición de temperatura es de -20 a 60 °C y el rango de humedad es de 5 a 95 % de HR.
inserte la descripción de la imagen aquí

configuración del circuito

1. En el circuito de aplicación típico, se recomienda usar una resistencia pull-up de 4,7 K cuando la longitud del cable de conexión es inferior a 5 m, y reducir el valor de resistencia
de la resistencia pull-up de acuerdo con la situación real cuando el la longitud es mayor a 5m.
2. Cuando se utiliza un voltaje de 3,3 V para la fuente de alimentación, el cable de conexión debe ser lo más corto posible. Si el cable es demasiado largo, la fuente de alimentación del sensor será insuficiente, lo que provocará una desviación de la medición.
3. El valor de temperatura y humedad leído cada vez es el resultado de la última medición. Para obtener datos en tiempo real, debe leerse dos veces seguidas. Sin embargo, no se recomienda leer el sensor varias veces seguidas. fila. El intervalo entre
cada lectura del sensor es superior a 2 segundos. Obtenga datos precisos.
4. Si la parte de potencia fluctúa, afectará la temperatura. Si la ondulación de la fuente de alimentación conmutada es demasiado grande, la temperatura fluctuará.
inserte la descripción de la imagen aquí

Formato de datos

El dispositivo DHT11 emplea comunicación simplificada de un solo cable. El bus único significa que solo hay una línea de datos, y el intercambio de datos y el control en el sistema se completan con el bus único. El dispositivo (maestro o esclavo) está conectado a la línea de datos a través de un puerto de drenaje abierto o de tres estados para permitir que el dispositivo libere el bus cuando no está enviando datos y permita que otros dispositivos usen el bus; un solo bus generalmente requiere un conexión externa de aproximadamente 4,7 kΩ de resistencias pull-up, de modo que cuando el bus está inactivo, su estado es alto. Debido a que son estructuras maestro-esclavo, solo cuando el maestro llama al esclavo, el esclavo puede responder, por lo que el maestro debe seguir estrictamente la secuencia de un solo bus al acceder al dispositivo.Si la secuencia está desordenada, el dispositivo no responderá a la maestro.
Los DATOS se utilizan para la comunicación y la sincronización entre el microprocesador y el DHT11, adoptan un formato de datos de un solo bus y transmiten datos de 40 bits a la vez, primero en orden alto.
Formato de datos:
datos enteros de humedad de 8 bits + datos decimales de humedad de 8 bits + datos enteros de temperatura de 8 bits + datos decimales de temperatura de 8 bits + dígito de control de 8 bits.
Nota: La parte decimal de la humedad es 0.

inserte la descripción de la imagen aquí

Pasos de lectura de datos

Paso 1:
Después de encender el DHT11 (después de encender el DHT11, espere a que 1S supere el estado inestable y no pueda enviar ningún comando durante este período), pruebe los datos de temperatura y humedad ambiental
, y registre los datos, y en Al mismo tiempo, la línea de datos DHT11 DATA es tirada por la resistencia pull-up High mantiene un nivel alto todo el tiempo; en este momento, el pin DATA de DHT11 está en el estado de entrada y detecta señales externas todo el tiempo.
Paso 2:
configure la E/S del microprocesador en salida y nivel bajo de salida al mismo tiempo, y el nivel bajo no debe mantenerse por menos de 18 ms (el máximo no debe exceder los 30 ms), y luego la E/S
de El microprocesador está configurado en el estado de entrada. Tire de la resistencia, la E/S del microprocesador, es decir, la línea de datos de DATOS de DHT11 también se volverá alta, esperando que DHT11 haga una señal de respuesta, y la señal de envío es como se muestra en la figura:
inserte la descripción de la imagen aquí

Paso 3:
cuando el pin de DATOS de DHT11 detecta que la señal externa tiene un nivel bajo, espere el final del nivel bajo de la señal externa.Después del retraso, el pin de DATOS de DHT11 está en el estado de salida y emite un nivel bajo durante 83 microsegundos como señal de respuesta, y luego emite un nivel alto de 87 microsegundos para notificar a los periféricos que reciban datos. La E/S del microprocesador está en el estado de entrada en este momento. Después de detectar que la E/S tiene un nivel bajo (señal de respuesta DHT11), espere un nivel alto de 87 microsegundos Las señales de recepción y envío de datos después del nivel se muestran en la figura:
inserte la descripción de la imagen aquí

Los datos de 40 bits son emitidos por el pin DATA de DHT11, y el microprocesador recibe datos de 40 bits de acuerdo con el cambio del nivel de E / S. El formato de datos de bits "0" es: 54 microsegundos de nivel bajo y 23-27 microsegundos nivel alto, el formato de los datos de bits "1" es: 54 microsegundos de nivel bajo más 68-74 microsegundos de nivel alto. Datos de bit "0", señal de formato "1" como se muestra en la figura:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Los datos recopilados se muestran a continuación.

inserte la descripción de la imagen aquí

Configuración de GPIO

El módulo de temperatura y humedad DHT11 es el siguiente.
inserte la descripción de la imagen aquí

El puerto de datos correspondiente se muestra a continuación, que es P301.
inserte la descripción de la imagen aquí

Debido a la necesidad de configurar
inserte la descripción de la imagen aquí

En lo anterior, puede agregar un retraso de 1 s para dejar que el programa se ejecute, para que el sensor de temperatura y humedad sea estable.

/**********************DHT11初始化***************************************/    
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_HIGH);
    R_BSP_SoftwareDelay(1000U, BSP_DELAY_UNITS_MILLISECONDS);

inserte la descripción de la imagen aquí
La modificación de E/S se puede realizar a través de R_IOPORT_PinCfg().

inserte la descripción de la imagen aquí

Por ejemplo, establezca el estado de entrada.

   //DATA设为输入状态
    R_IOPORT_PinCfg(&g_ioport_ctrl,BSP_IO_PORT_03_PIN_01,((uint32_t) IOPORT_CFG_PORT_DIRECTION_INPUT));

Leer datos de temperatura y humedad

Dado que se utiliza el oscilador de cristal interno, la precisión definitivamente no es tan buena como la del oscilador de cristal externo, y el tiempo correspondiente debe modificarse ligeramente.
La señal de inicio se muestra en la siguiente figura.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Las señales correspondientes se muestran en la siguiente figura.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Si los datos no se pueden leer con normalidad, el siguiente retardo se puede modificar adecuadamente.
inserte la descripción de la imagen aquí

Tenga en cuenta que el archivo de encabezado correspondiente se introduce en el programa principal.

#include "dht11.h"

inserte la descripción de la imagen aquí

Las variables de temperatura y humedad deben definirse en el programa principal.

//温湿度变量定义
uint8_t humdity_integer;//湿度整数
uint8_t humdity_decimal;//湿度小数
uint8_t temp_integer ;//温度整数
uint8_t temp_decimal ;//温度小数
uint8_t dht11_check ;//校验值

inserte la descripción de la imagen aquí

Leer datos cada 5S en el programa principal.

               if(rtc_second%5==0)//5S读一次
               {
    
    
                   DHT11_Read();
                   printf("hum=%d temp=%d\n",humdity_integer,temp_integer);

               }

inserte la descripción de la imagen aquí

dht11.c

/*
 * dht11.c
 *
 *  Created on: 2023年6月29日
 *      Author: a8456
 */
#include "dht11.h"




extern fsp_err_t err ;



uint8_t DHT11_ReadByte(void)
{
    
    
    bsp_io_level_t state;
    uint8_t ans=0,ind;
    for (ind=0;ind<8;ind++)
    {
    
    
        ans<<=1;
        do
        {
    
    
            R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
        }while(state==BSP_IO_LEVEL_LOW);//直至识别低电平,开始接受数据
        R_BSP_SoftwareDelay(30, BSP_DELAY_UNITS_MICROSECONDS); //延时54us
        R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
        if (state==BSP_IO_LEVEL_HIGH)
            ans |= 1;
        do{
    
    
            R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
        }while(state==BSP_IO_LEVEL_HIGH);
    }
    return ans;
}


extern uint8_t humdity_integer;//湿度整数
extern uint8_t humdity_decimal;//湿度小数
extern uint8_t temp_integer ;//温度整数
extern uint8_t temp_decimal ;//温度小数
extern uint8_t dht11_check ;//校验值
uint8_t DHT11_Read(void)
{
    
    
    uint8_t dht11_check=0;
    bsp_io_level_t state;
    uint16_t delay_dht=0xffff;

    //DHT启动时序DATA设为输出状态
    R_IOPORT_PinCfg(&g_ioport_ctrl,BSP_IO_PORT_03_PIN_01,((uint32_t) IOPORT_CFG_PORT_DIRECTION_OUTPUT | (uint32_t) IOPORT_CFG_PORT_OUTPUT_HIGH));
    //发送18ms低电平
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_LOW);
    R_BSP_SoftwareDelay(18, BSP_DELAY_UNITS_MILLISECONDS); //延时20ms
    //在输出20-40us高电平
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_HIGH);
//    R_BSP_SoftwareDelay(30, BSP_DELAY_UNITS_MICROSECONDS); //延时30us
    //DATA设为输入状态
    R_IOPORT_PinCfg(&g_ioport_ctrl,BSP_IO_PORT_03_PIN_01,((uint32_t) IOPORT_CFG_PORT_DIRECTION_INPUT));
    //等待DATA响应低电平,后变为高电平
    do{
    
    
        delay_dht--;
        if (!delay_dht)
            return 0;
        R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
    }while(state==BSP_IO_LEVEL_HIGH);
    do{
    
    
        delay_dht--;
        if (!delay_dht)
            return 0;
        R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
    }while(state==BSP_IO_LEVEL_LOW);
    do{
    
    
        delay_dht--;
        if (!delay_dht)
            return 0;
        R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, &state);
    }while(state==BSP_IO_LEVEL_HIGH);

    humdity_integer = DHT11_ReadByte();
    humdity_decimal = DHT11_ReadByte();
    temp_integer = DHT11_ReadByte();
    temp_decimal = DHT11_ReadByte();
    dht11_check = DHT11_ReadByte();
    if (((humdity_integer+humdity_decimal+temp_integer+temp_decimal)&0xff)==dht11_check)
        return 1;
    else
        return 0;
}


dht11.h

/*
 * DHT11.h
 *
 *  Created on: 2023年6月29日
 *      Author: a8456
 */

#ifndef DHT11_H_
#define DHT11_H_

#include "hal_data.h"


uint8_t DHT11_ReadByte(void);
uint8_t DHT11_Read(void);



#endif /* DHT11_H_ */

programa principal

#include "hal_data.h"
#include <stdio.h>
#include "smg.h"
#include "timer_smg.h"
#include "flash_smg.h"
#include "dht11.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

//温湿度变量定义
uint8_t humdity_integer;//湿度整数
uint8_t humdity_decimal;//湿度小数
uint8_t temp_integer ;//温度整数
uint8_t temp_decimal ;//温度小数
uint8_t dht11_check ;//校验值

//数码管变量
uint8_t num1=1,num2=4,num3=6,num4=8;//4个数码管显示的数值
uint8_t num_flag=0;//4个数码管和冒号轮流显示,一轮刷新五次


//RTC变量
/* rtc_time_t is an alias for the C Standard time.h struct 'tm' */
rtc_time_t set_time =
{
    
    
    .tm_sec  = 50,      /* 秒,范围从 0 到 59 */
    .tm_min  = 59,      /* 分,范围从 0 到 59 */
    .tm_hour = 23,      /* 小时,范围从 0 到 23*/
    .tm_mday = 29,       /* 一月中的第几天,范围从 0 到 30*/
    .tm_mon  = 11,      /* 月份,范围从 0 到 11*/
    .tm_year = 123,     /* 自 1900 起的年数,2023为123*/
    .tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/
//    .tm_yday=0,         /* 一年中的第几天,范围从 0 到 365*/
//    .tm_isdst=0;        /* 夏令时*/
};


//RTC闹钟变量
rtc_alarm_time_t set_alarm_time=
{
    
    
     .time.tm_sec  = 58,      /* 秒,范围从 0 到 59 */
     .time.tm_min  = 59,      /* 分,范围从 0 到 59 */
     .time.tm_hour = 23,      /* 小时,范围从 0 到 23*/
     .time.tm_mday = 29,       /* 一月中的第几天,范围从 1 到 31*/
     .time.tm_mon  = 11,      /* 月份,范围从 0 到 11*/
     .time.tm_year = 123,     /* 自 1900 起的年数,2023为123*/
     .time.tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/

     .sec_match        =  1,//每次秒到达设置的进行报警
     .min_match        =  0,
     .hour_match       =  0,
     .mday_match       =  0,
     .mon_match        =  0,
     .year_match       =  0,
     .dayofweek_match  =  0,
    };

bsp_io_level_t sw1;//按键SW1状态
bsp_io_level_t sw2;//按键SW2状态
bsp_io_level_t sw3;//按键SW3状态
bsp_io_level_t sw4;//按键SW4状态
bsp_io_level_t qe_sw;//触摸电容状态

int sw1_num1=0;//按键SW1计数值,去抖和长按短按判断
int sw2_num1=0;//按键SW2计数值,去抖和长按短按判断
int sw3_num1=0;//按键SW3计数值,去抖和长按短按判断
int sw4_num1=0;//按键SW4计数值,去抖和长按短按判断
int qe_sw_num1=0;//触摸按键计数值,去抖和长按短按判断
void qe_touch_sw(void);

//数码管显示状态,0正常显示,1修改小时,2修改分钟,3保存修改数据,4温度,5湿度
int smg_mode=0;
int sec=0,min=0,hour=0;//保存时间数据
uint16_t time_mode_num=0;//定时器刷新时间,实现闪烁效果

volatile uint8_t g_src_uint8[4]={
    
    0x00,0x00,0x00,0x00};//时间保存在该数组里面
volatile uint8_t  g_src_uint8_length=4;
uint8_t flash_flag=0;//保存时间数据,一半在每过一分钟或者按键修改时间


//RTC回调函数
volatile bool rtc_flag = 0;//RTC延时1s标志位
volatile bool rtc_alarm_flag = 0;//RTC闹钟
/* Callback function */
void rtc_callback(rtc_callback_args_t *p_args)
{
    
    
    /* TODO: add your own code here */
    if(p_args->event == RTC_EVENT_PERIODIC_IRQ)
        rtc_flag=1;
    else if(p_args->event == RTC_EVENT_ALARM_IRQ)
        rtc_alarm_flag=1;
}


fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    
    
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
    
    
        uart_send_complete_flag = true;
    }
}

#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
    
    
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){
    
    }
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    
    
    for(int i=0;i<size;i++)
    {
    
    
        __io_putchar(*pBuffer++);
    }
    return size;
}





/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    
    
    /* TODO: add your own code here */
    /**********************DHT11初始化***************************************/
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_03_PIN_01, BSP_IO_LEVEL_HIGH);
        R_BSP_SoftwareDelay(1000U, BSP_DELAY_UNITS_MILLISECONDS);

    /* Open the transfer instance with initial configuration. */
       err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
       assert(FSP_SUCCESS == err);
/**********************数码管测试***************************************/
//              ceshi_smg();
/**********************定时器开启***************************************/
    /* Initializes the module. */
    err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* Start the timer. */
    (void) R_GPT_Start(&g_timer0_ctrl);

/**********************data flash***************************************/
    flash_result_t blank_check_result;
    /* Open the flash lp instance. */
    err = R_FLASH_LP_Open(&g_flash0_ctrl, &g_flash0_cfg);
    assert(FSP_SUCCESS == err);

    //       WriteFlashTest(4,g_src_uint8 ,FLASH_DF_BLOCK_0);

    PrintFlashTest(FLASH_DF_BLOCK_0);


    set_time.tm_sec=0;//时间数据 秒
    set_time.tm_min=min;//时间数据 分钟
    hour=set_time.tm_hour=hour;//时间数据 小时



/**********************RTC开启***************************************/
    /* Initialize the RTC module*/
    err = R_RTC_Open(&g_rtc0_ctrl, &g_rtc0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);

    /* Set the RTC clock source. Can be skipped if "Set Source Clock in Open" property is enabled. */
    R_RTC_ClockSourceSet(&g_rtc0_ctrl);

/* R_RTC_CalendarTimeSet must be called at least once to start the RTC */
    R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);
    /* Set the periodic interrupt rate to 1 second */
    R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);

           R_RTC_CalendarAlarmSet(&g_rtc0_ctrl, &set_alarm_time);
           uint8_t rtc_second= 0;      //秒
           uint8_t rtc_minute =0;      //分
           uint8_t rtc_hour =0;         //时
           uint8_t rtc_day =0;          //日
           uint8_t rtc_month =0;      //月
           uint16_t rtc_year =0;        //年
           uint8_t rtc_week =0;        //周
           rtc_time_t get_time;


           sec=set_time.tm_sec;//时间数据 秒
            min=set_time.tm_min;//时间数据 分钟
            hour=set_time.tm_hour;//时间数据 小时

       while(1)
       {
    
    
           if(flash_flag)//按键修改完毕数据后进行保存
           {
    
    
               g_src_uint8[0]=hour;
               g_src_uint8[1]=min;
               WriteFlashTest(4,g_src_uint8 ,FLASH_DF_BLOCK_0);
               flash_flag=0;
           }


           if(rtc_flag)
           {
    
    
               R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
               rtc_flag=0;
               rtc_second=get_time.tm_sec;//秒
               rtc_minute=get_time.tm_min;//分
               rtc_hour=get_time.tm_hour;//时
               rtc_day=get_time.tm_mday;//日
               rtc_month=get_time.tm_mon;//月
               rtc_year=get_time.tm_year; //年
               rtc_week=get_time.tm_wday;//周
               printf(" %d y %d m %d d %d h %d m %d s %d w\n",rtc_year+1900,rtc_month,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);

                //时间显示
               num1=rtc_hour/10;
               num2=rtc_hour%10;

               num3=rtc_minute/10;
               num4=rtc_minute%10;
               if(rtc_second==0&&smg_mode==0)//这个时候刷新变量
               {
    
    
                   sec=rtc_second;//时间数据 秒
                   min=rtc_minute;//时间数据 分钟
                   hour=rtc_hour;//时间数据 小时

                   g_src_uint8[0]=hour;
                   g_src_uint8[1]=min;
                   WriteFlashTest(4,g_src_uint8 ,FLASH_DF_BLOCK_0);


               }
               if(rtc_second%5==0)//5S读一次
               {
    
    
                   DHT11_Read();
                   printf("hum=%d temp=%d\n",humdity_integer,temp_integer);

               }

           }
           if(rtc_alarm_flag)
           {
    
    
               rtc_alarm_flag=0;
               printf("/************************Alarm Clock********************************/\n");
           }
           set_smg_button();
           R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
       }

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

Supongo que te gusta

Origin blog.csdn.net/qq_24312945/article/details/132131731
Recomendado
Clasificación