查看: 1360|回复: 3

[主题月] 【5月主题月】LPC845读取DHT11温湿度模块

[复制链接]
  • TA的每日心情

    2024-2-5 12:06
  • 签到天数: 627 天

    [LV.9]以坛为家II

    94

    主题

    1628

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    4429

    热心会员

    最后登录
    2024-2-5
    发表于 2021-5-18 10:35:20 | 显示全部楼层 |阅读模式
    本帖最后由 胤幻1988 于 2021-5-21 09:40 编辑

    最近响应日天号召,调试下温湿度传感器DHT11。本来在32平台上弄过,顺利的异常。
    但这次用自制板LPC845_Lite读取DHT11温湿度传感器,却出现了无法发现器件的问题。
    反复查看代码,及DHT11的时序图,没发现问题。最终怀疑SDK自带的延时不够精准,
    用CTIMER0 做了个精度高些的延时,果然好了。
    模拟单总线对时序的要求还真是高。时序要求高,要求高,要求高。出不来数据的,
    一般都是这个问题。
    我们先看下DHT11的时序图及DATA存储位置及计算方法:
    时序图:
    D2.png
    D3.png
    DATA存储位置及计算方法:
    D1.png
    下面我们根据时序图写函数,之前强掉过延时精准的重要性,
    我们用CTIMER0定时器来作为延时的发生器:
    当前系统LPC845定时器时钟30M,这里仅将其时钟分频为30(1MHz,一个节拍对应1us)
    和分频为30000(1KHz,一个节拍对应1ms),然后读取定时器TC的值,来判断延时的到达。
    未使用中断,和其他高端设计。
    代码如下:
    定时器初始化设置:
    1. const ctimer_config_t CTIMER0_config = {
    2.   .mode = kCTIMER_TimerMode,
    3.   .input = kCTIMER_Capture_0,
    4.   .prescale = 29
    5. };

    6. static void CTIMER0_init(void) {
    7.   /* CTIMER0 peripheral initialization */
    8.   CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);
    9. }
    复制代码


    基于对us的实时性,这里定时器默认配置位微妙的设置,毫秒延时后,恢复成微妙的设置:
    1. void delay_us(uint32_t nus)
    2. {
    3.         //SDK_DelayAtLeastUs(nus,SystemCoreClock);

    4.         CTIMER0_PERIPHERAL->TC=0;
    5.         /* Start the timer */
    6.         CTIMER_StartTimer(CTIMER0_PERIPHERAL);
    7.         //等待计时完成
    8.         while((CTIMER0_PERIPHERAL->TC)<nus){};
    9.     //关闭定时器
    10.         CTIMER_StopTimer(CTIMER0_PERIPHERAL);
    11. }


    12. void delay_ms(uint32_t nms)
    13. {
    14. /*        while(nms--)
    15.         {
    16.                 delay_us(1000);
    17.         }*/

    18.         ctimer_config_t CTIMER0_config = {
    19.           .mode = kCTIMER_TimerMode,
    20.           .input = kCTIMER_Capture_0,
    21.           .prescale = 29999                          //30M 分频 30000 1000 1cnt=1ms
    22.         };

    23.         /* CTIMER0 peripheral initialization */
    24.         CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);

    25.         CTIMER0_PERIPHERAL->TC=0;
    26.         /* Start the timer */
    27.         CTIMER_StartTimer(CTIMER0_PERIPHERAL);
    28.         //等待计时完成
    29.         while((CTIMER0_PERIPHERAL->TC)<nms){};
    30.     //关闭定时器
    31.         CTIMER_StopTimer(CTIMER0_PERIPHERAL);
    32.         //ms级别对时间不敏感
    33.         //恢复US 配置
    34.         CTIMER0_config.prescale = 29;                       //30M 分频 29+1 1M 1cnt=1us
    35.         /* CTIMER0 peripheral initialization */
    36.         CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);

    37. }
    复制代码
    DHT的操作函数:
    IO口方向及赋值及读取的宏定义:
    1. //DATA-->P0_16
    2. ////IO操作函数
    3. #define DHT11_PIN_CLR  GPIO_PortClear(BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT,     \
    4.                                                                                 1U << BOARD_INITPINS_dht11_data_PIN)
    5. #define DHT11_PIN_SET  GPIO_PortSet  (BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT,     \
    6.                                                                                 1U << BOARD_INITPINS_dht11_data_PIN)

    7. #define DHT11_DQ_OUT(x)   (x>0)? DHT11_PIN_SET:DHT11_PIN_CLR

    8. #define DHT11_DQ_IN    GPIO_PinRead  (BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT,     \
    9.                                                 BOARD_INITPINS_dht11_data_PIN)
    10. //IO方向设置
    11. //        GPIO->DIRSET[0]|=1<<16;//1 OUTPUT  0 INPUT
    12. //        GPIO->DIRCLR[0]|=1<<16;
    13. #define DHT11_IO_IN()  (BOARD_INITPINS_dht11_data_GPIO->DIRCLR[BOARD_INITPINS_dht11_data_PORT] |= 1UL << BOARD_INITPINS_dht11_data_PIN)
    14. #define DHT11_IO_OUT() (BOARD_INITPINS_dht11_data_GPIO->DIRSET[BOARD_INITPINS_dht11_data_PORT] |= 1UL << BOARD_INITPINS_dht11_data_PIN)
    复制代码
    具体操作函数:
    1. void DHT11_Reset(void)
    2. {
    3.         DHT11_IO_OUT();  //SET OUTPUT
    4.         DHT11_DQ_OUT(0); //拉低DQ
    5.         delay_ms(20);    //拉低至少18ms
    6.         DHT11_DQ_OUT(1); //DQ=1
    7.         delay_us(30);    //主机拉高20~40us
    8. }

    9. uint8_t DHT11_Check(void)
    10. {
    11.         uint8_t retry=0;
    12.         DHT11_IO_IN();//SET INPUT
    13.         while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
    14.         {
    15.                 retry++;
    16.                 delay_us(1);
    17.         };

    18.         if(retry>=100)return 1;
    19.         else retry=0;
    20.         while (!DHT11_DQ_IN&&retry<100)
    21.         {
    22.                 retry++;
    23.                 delay_us(1);
    24.         };
    25.         if(retry>=100)return 2;
    26.         return 0;
    27. }



    28. uint8_t DHT11_Read_Bit(void)
    29. {
    30.         uint8_t retry=0;
    31.         while(DHT11_DQ_IN&&retry<100)
    32.         {
    33.                 retry++;
    34.                 delay_us(1);
    35.         }
    36.         retry=0;
    37.         while(!DHT11_DQ_IN&&retry<100)
    38.         {
    39.                 retry++;
    40.                 delay_us(1);
    41.         }
    42.         delay_us(40);
    43.         if(DHT11_DQ_IN) return 1;
    44.         else return 0;
    45. }

    46. uint8_t DHT11_Read_Byte(void)
    47. {
    48.         uint8_t i,dat;
    49.         dat=0;
    50.         for(i=0;i<8;i++)
    51.         {
    52.                    dat<<=1;
    53.             dat|=DHT11_Read_Bit();
    54.         }

    55.         return dat;
    56. }

    57. //从DHT11读取一次数据
    58. //temp:温度值(范围:0~50°)
    59. //humi:湿度值(范围:20%~90%)
    60. //返回值:0,正常;1,读取失败
    61. uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi)
    62. {
    63.          uint8_t buf[5],i;
    64.         DHT11_Reset();
    65.         if(DHT11_Check()==0)
    66.         {
    67.                 for(i=0;i<5;i++)//读取40位数据
    68.                 {
    69.                         buf[i]=DHT11_Read_Byte();
    70.                 }
    71.                 if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
    72.                 {
    73.                         *humi=buf[0];
    74.                         *temp=buf[2];
    75.                 }
    76.         }
    77.         else return 1;
    78.         return 0;
    79. }

    80. uint8_t DHT11_Init(void)
    81. {

    82.         /* Enables the clock for the GPIO0 module */
    83.         CLOCK_EnableClock(kCLOCK_Gpio0);

    84.         gpio_pin_config_t dht11_data_config = {
    85.             .pinDirection = kGPIO_DigitalOutput,
    86.                 .outputLogic = 1U,
    87.         };
    88.         /* Initialize GPIO functionality on pin PIO0_16 (pin 19)  */
    89.         GPIO_PinInit(BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT, BOARD_INITPINS_dht11_data_PIN, &dht11_data_config);

    90.         DHT11_PIN_SET;
    91.         //DHT11_PIN_OUT();

    92.         DHT11_Reset();
    93.         return DHT11_Check();
    94. }
    复制代码
    具体在main函数里面的调用:
    初始化:
    1. while(DHT11_Init())        //DHT11初始化
    2.         {
    3.                 PRINTF("DHT11 Error\r\n");
    4.                 RGBLED_Show(255,0,0);delay_ms(500);
    5.                 PRINTF("time cnt value is %d \r\n",CTIMER0_PERIPHERAL->TC);
    6.                 RGBLED_Show(254,254,0);delay_ms(500);
    7.         }

    8.         PRINTF("DHT11   OK\r\n");
    9.         delay_ms(10);
    10.         //去掉前期不稳定的读取
    11.         for(j=0;j<10;j++)
    12.         {
    13.                 DHT11_Read_Data(&temperature,&humidity);
    14.                 delay_ms(100);
    15.         }
    复制代码
    OLED显示:
    1. OLED_Clear();
    2.         OLED_ShowChinese(0,0,0,16,1);
    3.         OLED_ShowChinese(18,0,1,16,1);
    4.         OLED_ShowChinese(36,0,2,16,1);
    5.         OLED_ShowChinese(54,0,3,16,1);
    6.         OLED_ShowChinese(72,0,4,16,1);
    7.         OLED_ShowChinese(90,0,5,16,1);
    8.         OLED_ShowChinese(108,0,6,16,1);
    9.         OLED_ShowString(8,16,(uint8_t *)"JacksonQiu_NXP",16,1);
    10.         OLED_ShowString(20,32,(uint8_t *)"2021/05/18",16,1);
    11.         OLED_ShowString(0,48,(uint8_t *)"TEMP:",16,1);
    12.         OLED_ShowString(63,48,(uint8_t *)"HUMD:",16,1);

    13.         //OLED_ShowNum(48,48,temperature,3,16,1);//显示TEMP
    14.         //OLED_ShowNum(103,48,humidity,3,16,1);//显示HUMD
    15.         OLED_Refresh();
    16.         delay_ms(1000);
    复制代码


    循环里面打印出,并刷新OLED:
    1. DHT11_Read_Data(&temperature,&humidity);        //读取温湿度值
    2.                         PRINTF("the tem is : %d ,the hum is : %d \r\n",temperature,humidity);

    3.                         //显示温度 湿度
    4. OLED_ShowNum(48-8,48,temperature,2,16,1);//显示TEMP
    5.                         OLED_ShowNum(103,48,humidity,2,16,1);//显示HUMD
    6.                         OLED_Refresh();
    7.                         delay_ms(1000);
    复制代码
    编译下载,显示如下:
    DHT11.png

    D40.gif

    好了,DHT11温湿度的实验就到这了。
    谢谢观看!代码: LPC845_MICOKIT_EXT_Project.rar (2.37 MB, 下载次数: 3)
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-10 22:38
  • 签到天数: 1335 天

    [LV.10]以坛为家III

    88

    主题

    4292

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9049
    最后登录
    2024-4-13
    发表于 2021-5-18 14:31:16 | 显示全部楼层
    鼓掌 鼓掌
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 11:26
  • 签到天数: 1274 天

    [LV.10]以坛为家III

    21

    主题

    1万

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    13214
    最后登录
    2024-4-19
    发表于 2021-5-21 21:36:49 | 显示全部楼层
    膜拜大神!
    跟着日天混 ,三天饱九顿!
    回复

    使用道具 举报

  • TA的每日心情

    昨天 10:49
  • 签到天数: 557 天

    [LV.9]以坛为家II

    34

    主题

    5913

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    5680
    最后登录
    2024-4-19
    发表于 2021-6-2 11:05:49 | 显示全部楼层
    好详细,另外最后那个图的灯一亮,差点闪瞎我
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-20 02:49 , Processed in 0.122804 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表