在线时间372 小时
UID3135871
注册时间2016-10-9
NXP金币20
TA的每日心情 | 怒 2024-2-5 12:06 |
---|
签到天数: 627 天 [LV.9]以坛为家II
版主
- 积分
- 4429
- 最后登录
- 2024-2-5
|
本帖最后由 胤幻1988 于 2021-5-21 09:40 编辑
最近响应日天号召,调试下温湿度传感器DHT11。本来在32平台上弄过,顺利的异常。
但这次用自制板LPC845_Lite读取DHT11温湿度传感器,却出现了无法发现器件的问题。
反复查看代码,及DHT11的时序图,没发现问题。最终怀疑SDK自带的延时不够精准,
用CTIMER0 做了个精度高些的延时,果然好了。
模拟单总线对时序的要求还真是高。时序要求高,要求高,要求高。出不来数据的,
一般都是这个问题。
我们先看下DHT11的时序图及DATA存储位置及计算方法:
时序图:
DATA存储位置及计算方法:
下面我们根据时序图写函数,之前强掉过延时精准的重要性,
我们用CTIMER0定时器来作为延时的发生器:
当前系统LPC845定时器时钟30M,这里仅将其时钟分频为30(1MHz,一个节拍对应1us)
和分频为30000(1KHz,一个节拍对应1ms),然后读取定时器TC的值,来判断延时的到达。
未使用中断,和其他高端设计。
代码如下:
定时器初始化设置:
- const ctimer_config_t CTIMER0_config = {
- .mode = kCTIMER_TimerMode,
- .input = kCTIMER_Capture_0,
- .prescale = 29
- };
- static void CTIMER0_init(void) {
- /* CTIMER0 peripheral initialization */
- CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);
- }
复制代码
基于对us的实时性,这里定时器默认配置位微妙的设置,毫秒延时后,恢复成微妙的设置:
- void delay_us(uint32_t nus)
- {
- //SDK_DelayAtLeastUs(nus,SystemCoreClock);
- CTIMER0_PERIPHERAL->TC=0;
- /* Start the timer */
- CTIMER_StartTimer(CTIMER0_PERIPHERAL);
- //等待计时完成
- while((CTIMER0_PERIPHERAL->TC)<nus){};
- //关闭定时器
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);
- }
- void delay_ms(uint32_t nms)
- {
- /* while(nms--)
- {
- delay_us(1000);
- }*/
- ctimer_config_t CTIMER0_config = {
- .mode = kCTIMER_TimerMode,
- .input = kCTIMER_Capture_0,
- .prescale = 29999 //30M 分频 30000 1000 1cnt=1ms
- };
- /* CTIMER0 peripheral initialization */
- CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);
- CTIMER0_PERIPHERAL->TC=0;
- /* Start the timer */
- CTIMER_StartTimer(CTIMER0_PERIPHERAL);
- //等待计时完成
- while((CTIMER0_PERIPHERAL->TC)<nms){};
- //关闭定时器
- CTIMER_StopTimer(CTIMER0_PERIPHERAL);
- //ms级别对时间不敏感
- //恢复US 配置
- CTIMER0_config.prescale = 29; //30M 分频 29+1 1M 1cnt=1us
- /* CTIMER0 peripheral initialization */
- CTIMER_Init(CTIMER0_PERIPHERAL, &CTIMER0_config);
- }
复制代码 DHT的操作函数:
IO口方向及赋值及读取的宏定义:
- //DATA-->P0_16
- ////IO操作函数
- #define DHT11_PIN_CLR GPIO_PortClear(BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT, \
- 1U << BOARD_INITPINS_dht11_data_PIN)
- #define DHT11_PIN_SET GPIO_PortSet (BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT, \
- 1U << BOARD_INITPINS_dht11_data_PIN)
- #define DHT11_DQ_OUT(x) (x>0)? DHT11_PIN_SET:DHT11_PIN_CLR
- #define DHT11_DQ_IN GPIO_PinRead (BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT, \
- BOARD_INITPINS_dht11_data_PIN)
- //IO方向设置
- // GPIO->DIRSET[0]|=1<<16;//1 OUTPUT 0 INPUT
- // GPIO->DIRCLR[0]|=1<<16;
- #define DHT11_IO_IN() (BOARD_INITPINS_dht11_data_GPIO->DIRCLR[BOARD_INITPINS_dht11_data_PORT] |= 1UL << BOARD_INITPINS_dht11_data_PIN)
- #define DHT11_IO_OUT() (BOARD_INITPINS_dht11_data_GPIO->DIRSET[BOARD_INITPINS_dht11_data_PORT] |= 1UL << BOARD_INITPINS_dht11_data_PIN)
复制代码 具体操作函数:
- void DHT11_Reset(void)
- {
- DHT11_IO_OUT(); //SET OUTPUT
- DHT11_DQ_OUT(0); //拉低DQ
- delay_ms(20); //拉低至少18ms
- DHT11_DQ_OUT(1); //DQ=1
- delay_us(30); //主机拉高20~40us
- }
- uint8_t DHT11_Check(void)
- {
- uint8_t retry=0;
- DHT11_IO_IN();//SET INPUT
- while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
- {
- retry++;
- delay_us(1);
- };
- if(retry>=100)return 1;
- else retry=0;
- while (!DHT11_DQ_IN&&retry<100)
- {
- retry++;
- delay_us(1);
- };
- if(retry>=100)return 2;
- return 0;
- }
- uint8_t DHT11_Read_Bit(void)
- {
- uint8_t retry=0;
- while(DHT11_DQ_IN&&retry<100)
- {
- retry++;
- delay_us(1);
- }
- retry=0;
- while(!DHT11_DQ_IN&&retry<100)
- {
- retry++;
- delay_us(1);
- }
- delay_us(40);
- if(DHT11_DQ_IN) return 1;
- else return 0;
- }
- uint8_t DHT11_Read_Byte(void)
- {
- uint8_t i,dat;
- dat=0;
- for(i=0;i<8;i++)
- {
- dat<<=1;
- dat|=DHT11_Read_Bit();
- }
- return dat;
- }
- //从DHT11读取一次数据
- //temp:温度值(范围:0~50°)
- //humi:湿度值(范围:20%~90%)
- //返回值:0,正常;1,读取失败
- uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi)
- {
- uint8_t buf[5],i;
- DHT11_Reset();
- if(DHT11_Check()==0)
- {
- for(i=0;i<5;i++)//读取40位数据
- {
- buf[i]=DHT11_Read_Byte();
- }
- if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
- {
- *humi=buf[0];
- *temp=buf[2];
- }
- }
- else return 1;
- return 0;
- }
- uint8_t DHT11_Init(void)
- {
- /* Enables the clock for the GPIO0 module */
- CLOCK_EnableClock(kCLOCK_Gpio0);
- gpio_pin_config_t dht11_data_config = {
- .pinDirection = kGPIO_DigitalOutput,
- .outputLogic = 1U,
- };
- /* Initialize GPIO functionality on pin PIO0_16 (pin 19) */
- GPIO_PinInit(BOARD_INITPINS_dht11_data_GPIO, BOARD_INITPINS_dht11_data_PORT, BOARD_INITPINS_dht11_data_PIN, &dht11_data_config);
- DHT11_PIN_SET;
- //DHT11_PIN_OUT();
- DHT11_Reset();
- return DHT11_Check();
- }
复制代码 具体在main函数里面的调用:
初始化:
- while(DHT11_Init()) //DHT11初始化
- {
- PRINTF("DHT11 Error\r\n");
- RGBLED_Show(255,0,0);delay_ms(500);
- PRINTF("time cnt value is %d \r\n",CTIMER0_PERIPHERAL->TC);
- RGBLED_Show(254,254,0);delay_ms(500);
- }
- PRINTF("DHT11 OK\r\n");
- delay_ms(10);
- //去掉前期不稳定的读取
- for(j=0;j<10;j++)
- {
- DHT11_Read_Data(&temperature,&humidity);
- delay_ms(100);
- }
复制代码 OLED显示:
- OLED_Clear();
- OLED_ShowChinese(0,0,0,16,1);
- OLED_ShowChinese(18,0,1,16,1);
- OLED_ShowChinese(36,0,2,16,1);
- OLED_ShowChinese(54,0,3,16,1);
- OLED_ShowChinese(72,0,4,16,1);
- OLED_ShowChinese(90,0,5,16,1);
- OLED_ShowChinese(108,0,6,16,1);
- OLED_ShowString(8,16,(uint8_t *)"JacksonQiu_NXP",16,1);
- OLED_ShowString(20,32,(uint8_t *)"2021/05/18",16,1);
- OLED_ShowString(0,48,(uint8_t *)"TEMP:",16,1);
- OLED_ShowString(63,48,(uint8_t *)"HUMD:",16,1);
- //OLED_ShowNum(48,48,temperature,3,16,1);//显示TEMP
- //OLED_ShowNum(103,48,humidity,3,16,1);//显示HUMD
- OLED_Refresh();
- delay_ms(1000);
复制代码
循环里面打印出,并刷新OLED:
- DHT11_Read_Data(&temperature,&humidity); //读取温湿度值
- PRINTF("the tem is : %d ,the hum is : %d \r\n",temperature,humidity);
- //显示温度 湿度
- OLED_ShowNum(48-8,48,temperature,2,16,1);//显示TEMP
- OLED_ShowNum(103,48,humidity,2,16,1);//显示HUMD
- OLED_Refresh();
- delay_ms(1000);
复制代码 编译下载,显示如下:
好了,DHT11温湿度的实验就到这了。
谢谢观看!代码:
LPC845_MICOKIT_EXT_Project.rar
(2.37 MB, 下载次数: 3)
|
|