文章目录
硬件连接
使用PG4来连接DHT11温湿度模块。
设备树
1、修改设备树位置1
sun8i-v3s.dtsi
dht11_pin: dht11_pin{
pins = "PG4";
};
位置:
2、修改设备树位置2
文件:sun8i-v3s-licheepi-zero-dock.dts
dht11{
pinctrl-1 =<&dht11_pin>;/*dht11的pin管脚属性来自dtsi文件*/
compatible = "dht-11";
pinctrl-names = "default";
status = "okay";
dht11_pin@1{
/*配置dht11所属管脚的io口*/
gpios = <&pio 6 4 GPIO_ACTIVE_HIGH>;/*管脚是接在PG4上面*/
label = "dht_11";
linux,default-trigger = "heartbeat";
linux,default-trigger-delay-ms = <0>;
};
};
位置:
驱动
参考:https://blog.csdn.net/qq_46079439/article/details/126131667
/***************************************************************************
* DHT11 linux5.2内核驱动
*
* 2022-10-29
*
***************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/of_gpio.h>
#define DEVICE_NAME "dht11_ctl"//设备名称
#define DRIVER_NAME "dht11_ctl"
uint32_t dth11_pin = 1;//定义dht11的管脚属性
struct dht11_data
{
u_int16_t temp;//温度
u_int16_t hmi;//湿度
};
#define delay_us(x) udelay(x)
#define delay_ms(x) msleep(x)
static u8 dht11_read_io(void)
{
gpio_direction_input(dth11_pin);
return gpio_get_value(dth11_pin);
}
//复位DHT11
static void dht11_rst(void)
{
gpio_direction_output(dth11_pin, 0);
msleep (20); //拉低至少18ms
gpio_direction_output(dth11_pin, 1); //DQ=1
delay_us (30); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
static u8 dht11_check(void)
{
u8 retry=0;//定义临时变量
gpio_direction_input(dth11_pin);//设置io口为输入模式
while ((dht11_read_io()==1)&&retry<100)//DHT11会拉低40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while ((dht11_read_io()==0)&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//从DHT11读取一个位
//返回值:1/0
static u8 dht11_read_bit(void)
{
u8 retry=0;
while((dht11_read_io()==1)&&retry<100)//等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while((dht11_read_io()==0)&&retry<100)//等待变高电平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(dht11_read_io()==1)
return 1;
else
return 0;
}
/*读取一个byte*/
static u8 dht11_read_byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=dht11_read_bit();//读取一个位
}
return dat;
}
/*从DHT11中取出温度和湿度数据*/
static u8 dht11_read_data(u_int16_t *temp,u_int16_t *humi)
{
u8 buf[5];
u8 i;
dht11_rst();
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]<<8|buf[1];
*temp=buf[2]<<8|buf[3];
printk("readout data:buf=%d,%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3],buf[4]);
}
}else return 1;
return 0;
}
/*检测dht11所连接的io口的状态*/
static void dht11_init(void)
{
dht11_rst(); //复位DHT11
dht11_check();//等待DHT11的回应
}
/*dht11读函数*/
ssize_t dht11_read(struct file *file, char __user *user, size_t bytesize, loff_t *this_loff_t)
{
struct dht11_data this_data;//得到当前的温度和湿度信息
if(dht11_read_data(&this_data.temp,&this_data.hmi) == 0);//读取温湿度值
{
//将温度和湿度信息拷贝到user指针中
if ( copy_to_user(user,&this_data,sizeof(this_data)) )
{
return EFAULT ;
}
}
}
/*dht11设备节点打开函数*/
int dht11_open(struct inode *inode, struct file *file)
{
printk("--------------%s--------------\n",__FUNCTION__);
return 0;
}
/*设备节点关闭*/
int dht11_close(struct inode *inode, struct file *file)
{
return 0;//返回0
}
/*ioctl读取函数*/
long dht11_ioctl(struct file *file, unsigned int item, unsigned long long_item)
{
return 0;
}
/*dht11文件结构体*/
static struct file_operations dht11_ops = {
.owner = THIS_MODULE,
.open = dht11_open,
.release = dht11_close,
.unlocked_ioctl = dht11_ioctl,
.read = dht11_read
};
/*将DHT11注册为杂项*/
static struct miscdevice dht11_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dht11_ops,
};
/*probe 函数*/
static int dht11_probe(struct platform_device *pdev)
{
int ret;
enum of_gpio_flags flag;//(flag == OF_GPIO_ACTIVE_LOW) ?
struct device_node *dht11_gpio_node = pdev->dev.of_node;
dth11_pin = of_get_named_gpio_flags(dht11_gpio_node->child, "gpios", 0, &flag);
if (!gpio_is_valid(dth11_pin))
{
printk("dht11-gpio: %d is invalid\n", dth11_pin);
return -ENODEV;
}
else
printk("dht11-gpio: %d is valid!\n", dth11_pin);
if (gpio_request(dth11_pin, "dht11-gpio"))
{
printk("gpio %d request failed!\n", dth11_pin);
gpio_free(dth11_pin);
return -ENODEV;
}
else
printk("gpio %d request success!\n", dth11_pin);
/**/
ret = misc_register(&dht11_misc_dev);//注册设备为杂项设备
msleep(100);//延时100毫秒
printk(DEVICE_NAME "\tinitialized\n");
dht11_init();//初始化一次系统
return 0;
}
static int dht11_remove (struct platform_device *pdev)
{
misc_deregister(&dht11_misc_dev);
gpio_free(dth11_pin);
return 0;
}
static int dht11_suspend (struct platform_device *pdev, pm_message_t state)
{
printk("dht11 suspend off\n");
return 0;
}
static int dht11_resume (struct platform_device *pdev)
{
printk("dht11 resume on!\r\n");
return 0;
}
/*匹配设备树驱动*/
static const struct of_device_id dht11_of_match[] = {
{
.compatible = "dht-11" },
{
/* sentinel */ }
};
/**/
MODULE_DEVICE_TABLE(of, dht11_of_match);
/*注册平台驱动*/
static struct platform_driver dht11_driver = {
.probe = dht11_probe,
.remove = dht11_remove,
.suspend = dht11_suspend,
.resume = dht11_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(dht11_of_match),
},
};
/*设备驱动挂载函数*/
static int __init dht11_dev_init(void) {
printk("dht 11 driver config successfully\r\n");
return platform_driver_register(&dht11_driver);
}
/*设备驱动退出函数*/
static void __exit dht11_dev_exit(void) {
platform_driver_unregister(&dht11_driver);
}
module_init(dht11_dev_init);
module_exit(dht11_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liefyuan");
Makefile文件:
KERN_DIR = /home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
rm -rf *.order *o *.symvers *.mod.c *.mod *.ko
obj-m += dht11_dev.o
编译及传输到开发板:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make -C /home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y M=/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11 modules
make[1]: Entering directory '/home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y'
CC [M] /home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.o
/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.c: In function ‘dht11_read’:
/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.c:153:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Building modules, stage 2.
MODPOST 1 modules
LD [M] /home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.ko
make[1]: Leaving directory '/home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y'
liefyuan@ubuntu:~/Liefyuan/bingpi-v3s/drivers/dht11$ scp dht11_dev.ko [email protected]:/home
[email protected]'s password:
dht11_dev.ko 100% 8378 8.2KB/s 00:00
liefyuan@ubuntu:~/Liefyuan/bingpi-v3s/drivers/dht11$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make -C /home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y M=/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11 modules
make[1]: Entering directory '/home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y'
CC [M] /home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.o
/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.c: In function ‘dht11_read’:
/home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.c:153:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Building modules, stage 2.
MODPOST 1 modules
LD [M] /home/liefyuan/Liefyuan/bingpi-v3s/drivers/dht11/dht11_dev.ko
make[1]: Leaving directory '/home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y'
liefyuan@ubuntu:~/Liefyuan/bingpi-v3s/drivers/dht11$ scp dht11_dev.ko [email protected]:/home
[email protected]'s password:
dht11_dev.ko 100% 8378 8.2KB/s 00:00
测试驱动的程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef struct DHT11_SENSOR_DATA
{
u16 temp;//温度
u16 hum;//湿度
}dht11_data;
int main ( void )
{
int fd;
int retval;
dht11_data Curdht11_data;
fd = open ( "/dev/dht11_ctl" , O_RDONLY);
if ( fd == -1 )
{
perror ( "open dht11 error\n" );
exit ( -1 );
}
printf ( "open /dev/dht11 successfully\n" );
sleep ( 2 );
while ( 1 )
{
sleep ( 1 ) ;
retval = read ( fd , &Curdht11_data , sizeof(Curdht11_data) );
if ( retval == -1 )
{
perror ( "read dht11 error" );
printf ( "read dht11 error" );
exit ( -1 );
}
if(Curdht11_data.temp != 0xffff)
printf ( "Temperature:%d.%d C,Humidity:%d.%d %%RH\n",Curdht11_data.temp>>8,Curdht11_data.temp&0xff,\
Curdht11_data.hum>>8,Curdht11_data.hum&0xff );
}
close ( fd );
}
编译,传输到开发板:
$ arm-linux-gnueabihf-gcc dhtApp.c -o dhtApp.elf
$ scp dhtApp.elf [email protected]:/home
dhtApp.elf 100% 11KB 10.6KB/s 00:00
最后:安装驱动、测试打印
安装驱动
# insmod dht11_dev.ko
[ 1298.414771] dht 11 driver config successfully
[ 1298.419639] dht11-gpio: 196 is valid!
[ 1298.423558] gpio 196 request success!
[ 1298.539965] dht11_ctl initialized
查看一下设备节点有没有出来:
可以!
测试打印
# ./dhtApp.elf
[ 1319.825865] --------------dht11_open--------------
open /dev/dht11 successfully
[ 1322.873868] readout data:buf=47,0,27,0,74
Temperature:27.0 C,Humidity:47.0 %RH
[ 1323.913867] readout data:buf=47,0,27,0,74
Temperature:27.0 C,Humidity:47.0 %RH
[ 1324.953923] readout data:buf=47,0,27,0,74
Temperature:27.0 C,Humidity:47.0 %RH
[ 1325.993784] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1327.033784] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1328.073783] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1329.113807] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1330.153862] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1331.193784] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1332.233781] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1333.273776] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1334.313782] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1335.353789] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1336.393785] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
Temperature:0.0 C,Humidity:160.0 %RH
[ 1338.473791] readout data:buf=46,0,27,0,73
Temperature:27.0 C,Humidity:46.0 %RH
[ 1339.513702] readout data:buf=48,0,28,0,76
Temperature:28.0 C,Humidity:48.0 %RH
[ 1340.553691] readout data:buf=52,0,28,0,80
Temperature:28.0 C,Humidity:52.0 %RH
[ 1341.593731] readout data:buf=52,0,29,0,81
Temperature:29.0 C,Humidity:52.0 %RH
[ 1342.633730] readout data:buf=52,0,29,0,81
Temperature:29.0 C,Humidity:52.0 %RH
[ 1343.673824] readout data:buf=54,0,30,0,84
Temperature:30.0 C,Humidity:54.0 %RH
[ 1344.713837] readout data:buf=56,0,30,0,86
完美。