開發(fā)環(huán)境:
主機(jī):Ubuntu12.04
開發(fā)板:RT5350
Openwrt:Openwrt15.05
1 硬件原理
下圖是我們溫度傳感器的接入引腳,3.3V 供電,io 口接 P13 的 GP0( GPIO0 的簡(jiǎn)稱 )。DHT11數(shù)字溫濕度傳感器 是一款含有已校準(zhǔn)數(shù)字信號(hào)輸出的溫濕度復(fù)合傳感器,它應(yīng)用專用的數(shù)字模塊采集技術(shù)和溫濕度傳感技術(shù),確保產(chǎn)品具有極高的可靠性和卓越的長(zhǎng)期穩(wěn)定性。傳感器包括一個(gè)電阻式感濕元件和一個(gè)NTC測(cè)溫元件,并與一個(gè)高性能 8 位單片機(jī)相連接。因此該產(chǎn)品具有品質(zhì)卓越、超快響應(yīng)、抗干擾能力強(qiáng)、性價(jià)比極高等優(yōu)點(diǎn)。每個(gè)DHT11 傳感器都在極為精確的濕度校驗(yàn)室中進(jìn)行校準(zhǔn)。校準(zhǔn)系數(shù)以程序的形式存在OTP內(nèi)存中,傳感器內(nèi)部在檢測(cè)型號(hào)的處理過(guò)程中要調(diào)用這些校準(zhǔn)系數(shù)。單線制串行接口,使系統(tǒng)集成變得簡(jiǎn)易快捷。超小的體積、極低的功耗,使其成為該類應(yīng)用中,在苛刻應(yīng)用場(chǎng)合的最佳選擇。
2 DHT11 相關(guān)時(shí)序
- 初始化(復(fù)位)時(shí)序圖
- 控制器首先至少拉低 18ms,然后拉高 20-40us 后等待 DHT11 的應(yīng)答
- 當(dāng) DHT11 檢測(cè)到信號(hào)后,首先將總線拉低約 80us 然后在拉高 80us 作為應(yīng)答信號(hào)。
- 讀取數(shù)據(jù)時(shí)序圖
- 表示 0 的時(shí)序如下
- 表示 1 的時(shí)序如下
- DHT11 以低電平應(yīng)答主機(jī),然后拉高總線準(zhǔn)備輸出。輸出 0 信號(hào)和 1 信號(hào)都是以低電平開始高電平結(jié)束。
- DHT11 輸出 0、 1 信號(hào)的低電平時(shí)間相同,而高電平的時(shí)間不同,輸出 0 信號(hào)時(shí)高電平約 26-28us,而當(dāng)輸出 1 信號(hào)時(shí)高電平約為 70us。
3 驅(qū)動(dòng)程序
關(guān)于字符設(shè)備驅(qū)動(dòng)程序的使用,我們可以參照點(diǎn)亮 led 燈的那個(gè)實(shí)驗(yàn),這里只給出跟DHT11 密切相關(guān)的驅(qū)動(dòng)程序,詳細(xì)的程序請(qǐng)查看我們的驅(qū)動(dòng)文件!
//配置連接溫度傳感器的引腳
#define DHT11_L *GPIO21_0_DATA &= ~(1< 0) //低電平
#define DHT11_H *GPIO21_0_DATA |= (1< 0) //高電平
#define DHT11_OUT *GPIO21_0_DIR |= (1< 0) //輸出
#define DHT11_IN *GPIO21_0_DIR &= ~(1< 0) //輸入
#define DHT11_STA *GPIO21_0_DATA & 0x01
//寄存器定義
volatile unsigned long *GPIO21_0_DIR;
volatile unsigned long *GPIO21_0_DATA;
/**************** 基本定義 **********************/
//初始化函數(shù)必要資源定義
//用于初始化函數(shù)當(dāng)中
//device number;
dev_t dev_num;
//struct dev
struct cdev dht11_cdev;
//auto "mknode /dev/dht11 c dev_num minor_num"
struct class *dht11_class = NULL;
struct device *dht11_device = NULL;
/******************** dht11有關(guān)的函數(shù) ****************************/
//從dht11中讀取一個(gè)字節(jié)
static unsigned char read_byte(void)
{
unsigned char r_val = 0;
unsigned char t_count = 0; //計(jì)時(shí)器,防止超時(shí);
unsigned char i;
for(i = 0 ; i < 8 ; i++)
{
t_count = 0;
while(!DHT11_STA)
{
udelay(1);
t_count++;
if(t_count >250)
{
printk("read_byte error1n");
return 100;
}
}
t_count = 0;
udelay(32);
if(DHT11_STA == 1)
{
r_val < <= 1;
r_val |= 1;
}
else
{
r_val < <= 1;
continue;
}
while( DHT11_STA == 1 )
{
udelay(2);
t_count++;
if(t_count >250)
{
printk("read_byte error2n");
return 100;
}
}
}
return r_val;
}
//從dht11中讀出數(shù)據(jù)
static unsigned int read_dht11(void)
{
unsigned char t_count = 0; //計(jì)時(shí)器;
unsigned int dht11 = 0;
unsigned char h_i = 0 , h_f = 0;
unsigned char t_i = 0 , t_f = 0;
unsigned char check_sum = 0;
DHT11_OUT;
DHT11_L;
mdelay(30); // >18ms;
DHT11_H;
udelay(30);
DHT11_IN;
while(DHT11_STA == 1)
{
udelay(1);
t_count++;
if(t_count > 50)
{
printk("device error: dht11!n");
return 0;
}
}
t_count = 0;
while(!DHT11_STA)
{
udelay(1);
t_count++;
if(t_count > 250)
{
printk("read_dht11 error1n");
return 0;
}
}
t_count = 0;
udelay(50);
while(DHT11_STA)
{
udelay(1);
t_count++;
if(t_count > 250)
{
printk("read_dht11 error2n");
return 0;
}
}
h_i = read_byte();
h_f = read_byte();
t_i = read_byte();
t_f = read_byte();
check_sum = read_byte();
if(check_sum == (h_i+h_f+t_i+t_f) || (h_i!=100 && t_i != 100))
{
dht11 = t_i;
dht11 < <= 8;
dht11 += h_i;
}
else
{
dht11 = 0;
printk("read_dht11 error3n");
}
return dht11;
}
/**********************************************************************/
/**************** 結(jié)構(gòu)體 file_operations 成員函數(shù) *****************/
//open
static int dht11_open(struct inode *inode, struct file *file)
{
printk("dht11 drive open...n");
DHT11_OUT;
DHT11_H;
return 0;
}
//close
static int dht11_close(struct inode *inode , struct file *file)
{
return 0;
}
//read
static ssize_t dht11_read(struct file *file, char __user *buffer,
size_t len, loff_t *pos)
{
unsigned int dht11;
printk("dht11 drive read...n");
dht11 = read_dht11();
copy_to_user(buffer, &dht11, 4);
return 4;
}
/***************** 結(jié)構(gòu)體: file_operations ************************/
//struct
static const struct file_operations dht11_fops = {
.owner = THIS_MODULE,
.open = dht11_open,
.release = dht11_close,
.read = dht11_read,
};
/************* functions: init , exit*******************/
//條件值變量,用于指示資源是否正常使用
unsigned char init_flag = 0;
unsigned char add_code_flag = 0;
//init
static __init int dht11_init(void)
{
int ret_v = 0;
printk("dht11 drive init...n");
//函數(shù)alloc_chrdev_region主要參數(shù)說(shuō)明:
//參數(shù)2: 次設(shè)備號(hào)
//參數(shù)3: 創(chuàng)建多少個(gè)設(shè)備
if( ( ret_v = alloc_chrdev_region(&dev_num,0,1,"dht11") ) < 0 )
{
goto dev_reg_error;
}
init_flag = 1; //標(biāo)示設(shè)備創(chuàng)建成功;
printk("The drive info of dht11:nmajor: %dnminor: %dn",
MAJOR(dev_num),MINOR(dev_num));
cdev_init(&dht11_cdev,&dht11_fops);
if( (ret_v = cdev_add(&dht11_cdev,dev_num,1)) != 0 )
{
goto cdev_add_error;
}
dht11_class = class_create(THIS_MODULE,"dht11");
if( IS_ERR(dht11_class) )
{
goto class_c_error;
}
dht11_device = device_create(dht11_class,NULL,dev_num,NULL,"dht11");
if( IS_ERR(dht11_device) )
{
goto device_c_error;
}
printk("auto mknod success!n");
//------------ 請(qǐng)?jiān)诖颂砑幽某跏蓟绦? --------------//
GPIO21_0_DATA = (volatile unsigned long *)ioremap(0x10000620, 4);
GPIO21_0_DIR = (volatile unsigned long *)ioremap(0x10000624, 4);
//如果需要做錯(cuò)誤處理,請(qǐng):goto dht11_error;
add_code_flag = 1;
//---------------------- END ---------------------------//
goto init_success;
dev_reg_error:
printk("alloc_chrdev_region failedn");
return ret_v;
cdev_add_error:
printk("cdev_add failedn");
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return ret_v;
class_c_error:
printk("class_create failedn");
cdev_del(&dht11_cdev);
unregister_chrdev_region(dev_num, 1);
init_flag = 0;
return PTR_ERR(dht11_class);
device_c_error:
printk("device_create failedn");
cdev_del(&dht11_cdev);
unregister_chrdev_region(dev_num, 1);
class_destroy(dht11_class);
init_flag = 0;
return PTR_ERR(dht11_device);
//------------------ 請(qǐng)?jiān)诖颂砑幽腻e(cuò)誤處理內(nèi)容 ----------------//
dht11_error:
add_code_flag = 0;
return -1;
//-------------------- END -------------------//
init_success:
printk("dht11 init success!n");
return 0;
}
//exit
static __exit void dht11_exit(void)
{
printk("dht11 drive exit...n");
if(add_code_flag == 1)
{
//---------- 請(qǐng)?jiān)谶@里釋放您的程序占有的資源 ---------//
printk("free your resources...n");
iounmap(GPIO21_0_DATA);
iounmap(GPIO21_0_DIR);
printk("free finishn");
//---------------------- END -------------------//
}
if(init_flag == 1)
{
//釋放初始化使用到的資源;
cdev_del(&dht11_cdev);
unregister_chrdev_region(dev_num, 1);
device_unregister(dht11_device);
class_destroy(dht11_class);
}
}
/**************** module operations**********************/
//module loading
module_init(dht11_init);
module_exit(dht11_exit);
//some infomation
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("from Jafy");
MODULE_DESCRIPTION("dht11 drive");
/********************* The End ***************************/
4 應(yīng)用程序
int main(int argc, char **argv)
{
int fd;
unsigned int dht11 = 0;
unsigned int humi,temp;
//打開溫度傳感器驅(qū)動(dòng)模塊
fd = open("/dev/dht11", O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("can't open /dev/dht11n");
return -1;
}
read(fd, &dht11, sizeof(dht11));
temp = dht11 >>8;
humi = dht11 &0x000000ff;
printf("the current temperature is: %dn",temp);
printf("the current humidity is: %dn",humi);
close(fd);
return 0;
}
5 實(shí)驗(yàn)結(jié)果
審核編輯:湯梓紅
-
傳感器
+關(guān)注
關(guān)注
2550文章
51035瀏覽量
753063 -
溫濕度傳感器
+關(guān)注
關(guān)注
5文章
579瀏覽量
35706 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5032瀏覽量
97371 -
OpenWrt
+關(guān)注
關(guān)注
10文章
130瀏覽量
39296 -
DHT11
+關(guān)注
關(guān)注
19文章
277瀏覽量
57580
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論