精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux+Qt驅動dht11溫濕度傳感器實驗過程遇到的問題及解決辦法

CHANBAEK ? 來源:嵌入式大本營 ? 作者:小小飛飛哥 ? 2023-05-23 15:54 ? 次閱讀

最近想要做一個基于嵌入式Linux+Qt驅動dht11溫濕度傳感器的實驗。 想要實現的功能是通過野火的imx6ull開發板控制dht11傳感器,然后使用Qt做一個上位機,在上位機上面把數據顯示出來。

這里把我在做的過程中遇到的一些問題先記錄一下,免得日后忘記。

在網上關于這方面的資料不多,大多數都是基于stm32來控制的,所以在做的過程中遇到一些問題解決起來也比較麻煩。

下面簡述一下我做的過程及遇到的問題

首先查看原理圖看使用到了哪個管腳,然后在設備樹里添加相應的節點。 這里用到了gpio子系統和pinctrl子系統。

接著參考網上的相關代碼,進行了改寫,因為這個傳感器的時序也比較簡單,所以有關時序的部分基本上可以不用改。

遇到的第一個問題 :寫好驅動后,在應用程序中使用read函數來讀取設備文件,如果只讀取一次,可以得到結果,但是如果使用while(1)來嘗試反復讀取,就會失敗。

按照手冊來說,只要兩次讀取間隔超過1秒就行了,但是我使用while(1)即使休眠sleep(3)之類的依然會在第二次讀取的失敗,而且整個函數會卡死在讀取這里,這個進程怎么也殺不死,kill -9殺不死,kill -15 也殺不死。 這里很快把問題定位在了read函數。

后面,我在代碼中做了如下修改:本來在驅動程序里面有使用while函數來等待管腳電平的跳變,我認為這樣是不合理的,因為沒有超時處理,容易卡死,所以我加了一個計數,當超過一定計數值時就跳出while循環。 后來這個問題就解決了。 雖然我是不確定一開始是不是因為這個原因,因為中間過了挺久的時間,我不確定有沒有別的因素存在 ,總之后來就不會卡死了,可以使用while循環來反復讀取。

遇到的第二個問題 :在解決了上面的問題之后,insmod安裝驅動,可以工作,然后rmmod卸載驅動,再次insmod安裝驅動就會發現安裝不上去。

圖片

使用dmesg命令查看內核打印的信息,比較容易猜到應該是卸載驅動的時候沒有卸載干凈,然后仔細看了一下驅動,在結合網上查找資料,發現我的驅動里沒有寫remove函數。 所以我添加了remove函數,在remove函數里注銷掉那些東西。 而且要注意注銷的順序,和注冊是相反的,比如在驅動中最先是申請設備號,在注銷的時候就是最后注銷它,否則會出現很多錯誤,包括段錯誤 。

遇到的第三個問題 :在解決了第二個問題之后,已經可以反復卸載和安裝驅動了,但是發現一個問題,就是在第二次安裝的時候,總是會出現gpio_request失敗,按道理講我已經在remove函數里使用gpio_free釋放掉了,不應該會失敗才對,后來發現是在gpio_request的時候還沒拿到引腳號, 全局變量沒有初始化默認是0,所以request的是0,后來通過一個函數(忘記叫什么了,總之是gpio子系統的那些函數)從設備樹中拿到引腳號,這個引腳號是2,所以后面free的是2,也就是說request和free的不是同一個引腳,當然會出錯了。

這屬于粗心的錯,把這個問題解決了之后,這個驅動總算可以正常工作了,也完全可以反復卸載和安裝。

遇到的第四個問題 :在第一個問題里提到我在while里加了超時處理,防止一直死等卡死。 最開始我是這樣寫的

while(gpio_get_value(gpio)==0 &&cnt<6)< span="">
{
       cnt++;
       udelay(10);
}

這里通過cnt來防止while死掉,也就是說最多等待60微秒就退出循環。 但是直覺告訴我這樣不好 ,因為中間延時10個微秒太長了,導致響應性不好。 所以我改成了這樣:

while(gpio_get_value(gpio)==0 &&cnt<60)< span="">
{
       cnt++;
       udelay(1);
}

這樣的實時響應性好多了,測出的數據也更準確了。

到這里為止,驅動就基本沒有問題了,使用應用程序來讀取設備文件,也基本沒問題,就是有時數據校驗會失敗,但是測出的數據基本可以,而且是有變化的,說明還是比較可靠的。

接下來是把在Qt里把數據讀出來并且顯示, 下面說一下調試Qt遇到的問題 。

在寫完驅動之后,很自然會寫一個.c的測試程序,用來驗證驅動是否能正常工作,很幸運,一下子就成功了,于是我認為在Qt中也是類似,直接用Qt里的read相關的函數去讀取設備文件就好了,但是沒想到在這個環節卡了我最久

起初,我使用Qfile 里的readAll方法去讀,發現控制臺會刷屏(刷屏就是驅動中的read一直被調用而打印出的信息刷屏),一讀就停不下來,而且后面的程序也執行不了,也就是說函數沒有返回。

我不太清楚是什么原因,只能換一個函數,接著我嘗試了readLine方法,一樣刷屏,接著嘗試read方法,這個方法和C語言的read類似,參數里要填讀幾個字節,這和前面兩個不太一樣,所以我想,這回應該不會刷屏了吧。

結果確實沒有刷屏,但是讀取的數據是錯的,體現出來的就是從機無響應(這時我還沒有注意這個問題)。

雖然說數據是錯的,但是好歹沒有刷屏了,只要再想一想為什么會讀出錯的數據就行了。

我想到Qt里還有一種讀文件的方式,就是使用數據流Datastream,但是效果和上面的read一樣。

接著我開始思考刷屏的原因,百度了一下,有人說要在末尾加一個"\\0",嘗試,未果。

接著,我在一些技術交流群尋求幫助,因為此刻我的問題確實很奇怪,在自己寫的.c測試程序里,調用read讀設備文件是完全沒有問題的,現在唯一的區別就是在Qt中讀,驅動又不變,為什么讀出來的是錯的呢? 我懷疑是Qt的read對數據的解析可能和C語言里不太一樣,因為此刻是有數據的, 會不會是因為字節對齊之類的原因導致解析數據不對呢 ? 群里大佬建議先排查一下源數據對不對。

于是我拿出了我許久沒用過的邏輯分析儀來分析波形,我先觀察了我的.c測試程序的波形,和手冊描述的基本一致。 接著觀察Qt里read時的波形,一觀察發現根本沒有波形,正常情況應該是主機先拉低18ms,再拉高,等待從機應答。 而我觀察到的波形是主機拉低了30多ms才拉高,再看一下終端打印的數據, 發現驅動里的read被調用了兩次 。

這時,我已經猜到原因了,**之所以數據不對,是因為驅動里的read被連續調用了兩次,導致時序根本就不對,從機沒有應答。 **

再觀察之前使用readAll函數來讀取,雖然會刷屏,但是偶爾能捕捉到有效的波形。 這已經很能說明問題了,就是要解決驅動里的read為什么會被調用多次這個問題,正常應該是應用層調用一次read,驅動里的read就被調用一次。

關于這個問題,這篇文章講的不錯,使用cat讀取和echo寫內核文件節點的一些問題

這篇文章對我還是有很大的啟發。 總之就是驅動中read 的返回值會影響它是否被多次調用。

先來看一下驅動中read函數的參數和返回值

ssize_t dht11_chr_dev_read(struct file *filp, char __user *buf, size_t count, loff_t *fops)

我經過很多實驗,發現以下規律:

對于Qt中的readAll、readLine函數,不管驅動返回什么,readAll都會刷屏,readLine會調用驅動多次。

對于Qt中的read函數,如果驅動返回的是count,將不會刷屏,否則,也會刷屏。 (這一點確實很奇怪)

更奇怪的是同樣的實驗條件,在多次實驗中甚至可能得到不同的結果,但是上面這幾點結論是反復實驗得到的結論。

最后,我發現可以在Qt中使用C和C++混合編程,方法就是使用

extern "C"{
#include    //這里寫用到的C頭文件
}

然后在用到的C語言的函數前加兩個冒號,比如

::read(fd,buf,sizeof(buf));

這樣就可以直接調用C語言代碼了,而且發現效果還不錯,比Qt中的read系列函數穩定。 (實驗次數有限,從我觀察到的結果來看是這樣)。

所以,最終的解決方法就是:

方法一 :使用Qfile 的read函數,使用方法和C語言類似,可以正確讀出數據,但是要注意,如果使用這個函數,驅動中的read要返回參數列表中的count,否則會刷屏。

方法二 :直接使用混合編程的方式,調用C語言中的read ,這樣測出的效果是最好的,而且不必要求驅動中的read 返回count,直接返回實際讀取的字節即可,也就是copy_to_user的字節數。

驅動代碼參考了Linux下DHT11驅動編程,以及測試程序

在此基礎上修改得到

#include 
#include 
#include 
#include 
#include 


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include 








/*------------------字符設備內容----------------------*/
#define DEV_NAME            "dht11"
#define DEV_CNT                 (1)


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;




//定義字符設備的設備號
static dev_t dht11_devno;
//定義字符設備結構體chr_dev
static struct cdev dht11_chr_dev;




struct class *class_dht11;  //保存創建的類
struct device *device;      // 保存創建的設備
struct device_node  *dht11_device_node; //dht11的設備樹節點


int dht11_data_pin;         // 保存獲取得到的dht11引腳編號


DHT11_Data_TypeDef DHT11_Data;


//從DHT11讀取1byte數據,MSB先行
uint8_t DHT11_ReadByte(void)
{
  uint8_t i, temp=0;

    int cnt=0;
  for(i=0;i<8;i++)    
  {   
    /*每bit以50us低電平標置開始,輪詢直到從機發出 的50us 低電平 結束*/
    while(gpio_get_value(dht11_data_pin) == 0  && cnt<60)
        {
            cnt++;
            udelay(1);
        }
        cnt =0;
    /*DHT11 以26~28us的高電平表示“0”,以70us高電平表示“1”,
     *通過檢測 x us后的電平即可區別這兩個狀 ,x 即下面的延時 
     */
    udelay(40); //延時x us 這個延時需要大于數據0持續的時間即可         

    if(gpio_get_value(dht11_data_pin))/* x us后仍為高電平表示數據“1” */
    {
      /* 等待數據1的高電平結束 */
      while(gpio_get_value(dht11_data_pin) && cnt<50)
            {
                cnt++;
                udelay(1);
            }

      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;

}


/**
 * 一次完整的數據傳輸為40bit,高位先出
 * 8bit 濕度整數 + 8bit 濕度小數 + 8bit 溫度整數 + 8bit 溫度小數 + 8bit 校驗和的末8位
 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
  //  int ret;
    int cnt=0;

    printk(KERN_ERR"DHT11_Read_TempAndHumidity 被調用\\n");

  /*主機拉低*/
  gpio_direction_output(dht11_data_pin, 0);

  /*延時18ms,(>=18ms)*/
  mdelay(18);

  /*總線拉高 主機延時30us*/
  gpio_direction_output(dht11_data_pin, 1);

  udelay(30);   //延時30us,(20~40us)

  /*主機設為輸入 判斷從機響應信號*/ 
  gpio_direction_input(dht11_data_pin);

  /*判斷從機是否有低電平響應信號 如不響應則跳出,響應則向下運行*/   
  if(gpio_get_value(dht11_data_pin) == 0)     
  {
    /*輪詢直到從機發出 的80us 低電平 響應信號結束*/  
    while(gpio_get_value(dht11_data_pin) == 0 && cnt<100)
        {
            cnt++;
            udelay(1);
        }
        cnt = 0;
    /*輪詢直到從機發出的 80us 高電平 標置信號結束*/
    while(gpio_get_value(dht11_data_pin) && cnt<100)
        {
            cnt++;
            udelay(1);
        }

    /*開始接收數據*/   
    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_direction_output(dht11_data_pin, 1);


        printk("humi: %d.%d, temp: %d.%d,check:%d\\n",DHT11_Data->humi_int,\\
                    DHT11_Data->humi_deci,DHT11_Data->temp_int,DHT11_Data->temp_deci,DHT11_Data->check_sum);
    /*檢查讀取的數據是否正確*/
    //DHT11_Data->check_sum的正確的結果是溫濕度總和的末8位,結構體也有定義check_sum為uint8_t類型
    if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
      return 0;
    else {
       printk(KERN_ERR " ERROR 數據校驗失敗");
       return -1;
    }

  }
  else
    {
        printk(KERN_ERR "ERROR 從機無響應");
        return -1;
    }


}




/*字符設備操作函數集,open函數*/
static int dht11_chr_dev_open(struct inode *inode, struct file *filp)
{
  printk("\\n open form driver \\n");
    return 0;
}


/*字符設備操作函數集,write函數*/
static ssize_t dht11_chr_dev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{



  unsigned char write_data; //用于保存接收到的數據


  int error = copy_from_user(&write_data, buf, cnt);
  if(error < 0) {
    return -1;
  }


  return 0;
}




ssize_t dht11_chr_dev_read(struct file *filp, char __user *buf, size_t count, loff_t *fops)
{




  int size=sizeof(DHT11_Data_TypeDef);
  printk(KERN_ERR " count: %d, fops: %lld\\n", count, *fops);

  printk(KERN_ERR "--------%s---------\\n",__func__);

    /*調用DHT11_Read_TempAndHumidity讀取溫濕度,若成功則輸出該信息*/
  if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) != 0)
  {
    printk(KERN_ERR "Read DHT11 ERROR!\\r\\n");
  }
  else
  {
    if(copy_to_user(buf, &DHT11_Data, size)!=0)
    {
      printk(KERN_ERR " 拷貝失敗\\n");
//        return 0;
    }
    else
      printk(KERN_ERR " 拷貝成功\\n");
  }

    // ret= simple_read_from_buffer(buf, count, fops, &DHT11_Data, sizeof(DHT11_Data_TypeDef));
  //   *fops=0;

  return count;
//    return size;
}






/*字符設備操作函數集*/
static struct file_operations  dht11_chr_dev_fops = 
{
  .owner = THIS_MODULE,
    .open = dht11_chr_dev_open,
  .write = dht11_chr_dev_write,
  .read = dht11_chr_dev_read,
};






/*----------------平臺驅動函數集-----------------*/
static int dht11_probe(struct platform_device *pdv)
{

  int ret = 0;  //用于保存申請設備號的結果

  printk(KERN_EMERG "\\t  match successed  \\n");

    /*獲取dht11的設備樹節點*/
    dht11_device_node = of_find_node_by_path("/dht11");
    if(dht11_device_node == NULL)
    {
        printk(KERN_EMERG "\\t  get dht11 failed!  \\n");
    }


    dht11_data_pin = of_get_named_gpio(dht11_device_node, "dht11_data_pin", 0);



    printk("dht11_data_pin = %d\\n ", dht11_data_pin);


  ret=gpio_request(dht11_data_pin, "DQ_OUT");
    if(ret==0)
    {
        printk(KERN_ERR "gpio request success\\n");
    }
    else
    {
        printk(KERN_ERR "gpio request failed \\n");

    }




    gpio_direction_output(dht11_data_pin, 1);





  /*---------------------注冊 字符設備部分-----------------*/


  //第一步
    //采用動態分配的方式,獲取設備編號,次設備號為0,
    //設備名稱為rgb-leds,可通過命令cat  /proc/devices查看
    //DEV_CNT為1,當前只申請一個設備編號
    ret = alloc_chrdev_region(&dht11_devno, 0, DEV_CNT, DEV_NAME);
    if(ret < 0){
        printk("fail to alloc dht11_devno\\n");
        goto alloc_err;
    }
    //第二步
    //關聯字符設備結構體cdev與文件操作結構體file_operations
  dht11_chr_dev.owner = THIS_MODULE;
    cdev_init(&dht11_chr_dev, &dht11_chr_dev_fops);
    //第三步
    //添加設備至cdev_map散列表中
    ret = cdev_add(&dht11_chr_dev, dht11_devno, DEV_CNT);
    if(ret < 0)
    {
        printk(KERN_ERR"fail to add cdev\\n");
        goto add_err;
    }


  //第四步
  /*創建類 */
  class_dht11 = class_create(THIS_MODULE, DEV_NAME);
    if(class_dht11==NULL)
    {
        printk(KERN_ERR"class creat failed\\n");
        goto add_class;
    }
  /*創建設備*/
  device = device_create(class_dht11, NULL, dht11_devno, NULL, DEV_NAME);
    if(device==NULL)
    {
        printk(KERN_ERR"device creat failed\\n");
        goto add_device;
    }
  return 0;


 //   device_destroy(class_dht11,dht11_devno);
add_device:
    class_destroy(class_dht11);
    printk(KERN_EMERG "\\t  刪除類成功  \\n");
add_class:
    cdev_del(&dht11_chr_dev);
    printk(KERN_EMERG "\\t  刪除設備成功  \\n");


add_err:
    //添加設備失敗時,需要注銷設備號
    unregister_chrdev_region(dht11_devno, DEV_CNT);
  printk(KERN_EMERG"\\n 注銷設備號成功! \\n");
alloc_err:


  return -1;


}


int  dht11_remove(struct platform_device *dht11_dev)
{
    printk(KERN_EMERG"開始釋放資源");
    gpio_free(dht11_data_pin);
    device_destroy(class_dht11,dht11_devno);
    class_destroy(class_dht11);
    cdev_del(&dht11_chr_dev);
    unregister_chrdev_region(dht11_devno, DEV_CNT);
    printk(KERN_EMERG"釋放資源完畢");
    return 0;
}




static const struct of_device_id dht11[] = {
{ .compatible = "dht11"},
  { /* sentinel */ }
};


/*定義平臺設備結構體*/
struct platform_driver dht11_platform_driver = {
  .probe = dht11_probe,
    .remove = dht11_remove,
  .driver = {
    .name = "dht11-platform",
    .owner = THIS_MODULE,
    .of_match_table = dht11,
  }
};






/*
*驅動初始化函數
*/
static int __init dht11_platform_driver_init(void)
{
  int DriverState;

  DriverState = platform_driver_register(&dht11_platform_driver);

  printk(KERN_EMERG "\\tDriverState is %d\\n",DriverState);
  return 0;
}




/*
*驅動注銷函數
*/
static void __exit led_platform_driver_exit(void)
{


  printk(KERN_EMERG "dht11 module exit!\\n");


  platform_driver_unregister(&dht11_platform_driver);  
}




module_init(dht11_platform_driver_init);
module_exit(led_platform_driver_exit);


MODULE_LICENSE("GPL");
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5069

    文章

    19023

    瀏覽量

    303454
  • Linux
    +關注

    關注

    87

    文章

    11232

    瀏覽量

    208941
  • STM32
    +關注

    關注

    2266

    文章

    10875

    瀏覽量

    354898
  • 溫濕度傳感器

    關注

    5

    文章

    574

    瀏覽量

    35667
  • Qt
    Qt
    +關注

    關注

    1

    文章

    301

    瀏覽量

    37836
收藏 人收藏

    評論

    相關推薦

    基于arduino的dht11溫濕度傳感器的使用

    本文介紹了DHT11溫濕度傳感器電氣特性、DHT11封裝形式及接口說明與典型應用電路,其次介紹了DHT11
    發表于 01-22 15:50 ?4.5w次閱讀
    基于arduino的<b class='flag-5'>dht11</b><b class='flag-5'>溫濕度</b><b class='flag-5'>傳感器</b>的使用

    DHT11數字式溫濕度傳感器的應用性研究

    基于DHT11溫濕度傳感器具有測量精度高、響應速度快、抗干擾能力強等優點。通過介紹DHT11數字式溫濕度
    發表于 11-06 16:28

    【眾拳】基于STM8的DHT11溫濕度傳感器實驗 附代碼

    ~50us)時間,作為響應信號,然后DHT11拉高數據線,保持t4(40~50us)時間后,開始輸出數據。DHT11 溫濕度傳感器時序圖【眾拳】劍齒虎STM8開發板的
    發表于 12-07 09:14

    DHT11溫濕度傳感器介紹

    DHT11溫濕度傳感器介紹,1.實物原理圖2.模塊說明2.1 DHT11產品概述DHT11數字溫濕度
    發表于 07-21 09:04

    DHT11溫濕度傳感器

    DHT11溫濕度傳感器1. DHT11簡介2. 硬件設計3. 軟件設計3.1 STM32CubeMX設置3.2 MDK-ARM編程4. 下載驗證
    發表于 08-11 06:04

    DHT11數字溫濕度傳感器的數據通訊過程是怎樣的

    DHT11數字溫濕度傳感器是什么?有何優點呢?DHT11數字溫濕度傳感器的數據通訊
    發表于 01-18 06:07

    DHT11溫濕度傳感器簡介

    DHT11溫濕度傳感器1、DHT11簡介DHT11數字溫濕度
    發表于 02-16 06:55

    DHT11數字溫濕度傳感器的相關資料推薦

    STM32采集DHT11溫濕度關于DHT11相關參數代碼篇接線和實驗結果總結關于DHT11DHT11是一款數字
    發表于 02-21 07:34

    DHT11數字溫濕度傳感器產品介紹

    DHT11數字溫濕度傳感器產品介紹 DHT11數字溫濕度傳感器是一款含有已校準數字信號輸出的
    發表于 02-26 17:19 ?256次下載

    DHT11數字式溫濕度傳感器的應用性研究

    基于DHT11溫濕度傳感器具有測量精度高、響應速度快、抗干擾能力強等優點。通過介紹DHT11數字式溫濕度
    發表于 07-25 17:03 ?216次下載
    <b class='flag-5'>DHT11</b>數字式<b class='flag-5'>溫濕度</b><b class='flag-5'>傳感器</b>的應用性研究

    數字溫濕度傳感器 DHT11

    數字溫濕度傳感器 DHT11 ?相對濕度和溫度測量 ?全部校準,數字輸出 ?卓越的長期穩定性 ?無需額外部件 ?超長的信號傳輸距離 ?超低能耗 ?4 引腳安裝 ?完全互換
    發表于 12-02 11:06 ?4次下載

    溫濕度傳感器DHT11驅動程序

    本文開始介紹了驅動程序的定義與驅動程序的作用,其次介紹了DHT11溫濕度傳感器特性、引腳說明與封裝詳情,最后介紹了
    發表于 01-22 16:52 ?5.3w次閱讀
    <b class='flag-5'>溫濕度</b><b class='flag-5'>傳感器</b><b class='flag-5'>DHT11</b><b class='flag-5'>驅動</b>程序

    Arduino的實驗例程之溫濕度傳感器DHT11實驗

    本文檔的主要內容詳細介紹的是Arduino的實驗例程之溫濕度傳感器DHT11實驗免費下載。
    發表于 03-01 11:42 ?30次下載

    溫濕度傳感器DHT11的STM32驅動實現

    溫濕度傳感器DHT11的STM32驅動實現
    發表于 11-25 20:36 ?76次下載
    <b class='flag-5'>溫濕度</b><b class='flag-5'>傳感器</b><b class='flag-5'>DHT11</b>的STM32<b class='flag-5'>驅動</b>實現

    使用ESP8266驅動DHT11溫濕度傳感器

    DHT11數字溫濕度傳感器是一款含有已校準數字信號輸出的溫濕度綜合傳感器,在Arduino提高篇中已對其進行了介紹,本篇使用ESP8266來
    的頭像 發表于 05-19 14:20 ?6252次閱讀
    使用ESP8266<b class='flag-5'>驅動</b><b class='flag-5'>DHT11</b><b class='flag-5'>溫濕度</b><b class='flag-5'>傳感器</b>