一 操作流程及思路
一 传感器指标:
二 接口图
二 代码实现(结合DHT11的时序图)
封装配置IO接口函数
#define SET_DQ_OUT (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)) | (0x1))) //设置输出
#define SET_DQ_IN (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)))) //设置输入
#define SET_DQ_HIGH (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1))) //高电平
#define SET_DQ_LOW (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1))) //低电平
#define GET_DQ_STAT (*(pGPFBase+1) & (0x1)) //获得电平状态
封装起始信号函数 和接受响应函数
static void send_dht11_start(void)
{
SET_DQ_LOW;
mdelay(20);
SET_DQ_HIGH;
SET_DQ_IN;
return;
}
static int check_dht11_reply(void)
{
int cnt = 0;
while (GET_DQ_STAT && cnt < 24)
{
cnt++;
udelay(10);
}
if (cnt >= 24)
{
return -1;
}
while (!GET_DQ_STAT);
while (GET_DQ_STAT);
return 0;
}
封装接受信号的函数
static unsigned char dht11_readbyte(void)
{
int cnt = 0;
int i = 0;
unsigned char ret = 0;
for (i = 7; i >= 0; i--)
{
cnt = 0;
while (!GET_DQ_STAT);
while (GET_DQ_STAT)
{
cnt++;
udelay(1);
}
if (cnt > 40)
{
ret |= (0x1 << i);
}
}
return ret;
}
platform代码框架总体实现
其分为三部分,内核设备层,内核驱动层,用户应用层
decice.c
static struct resource res[] = { //资源,分配其需要的资源
[0] = {
.start = 0x56000050, // 物理地址起始
.end = 0x56000050 + 8 - 1, // 物理地址结束
.name = "GPF", //资源名称
.flags = IORESOURCE_MEM, //标识为内存资源
},
};
static struct platform_device dht11_device = { //platform框架,混杂设备注册的结构体初始化
.name = "dht11", //是否能配对成功,主要看这个
.id = -1,
.dev.release = dht11_release,
.resource = res,
.num_resources = sizeof(res) / sizeof(res[0]),
};
static void dht11_release(struct device *dev) //释放设备
{
return;
}
static int __init init_dht11_device(void) //初始化设备
{
int ret = 0;
ret = platform_device_register(&dht11_device);
if (ret != 0)
{
return -1;
}
printk("platform dht11 device register success!\n");
return 0;
}
static void __exit exit_dht11_device(void) //注销设备
{
platform_device_unregister(&dht11_device); //注册混杂设备
printk("platform dht11 device unregister success!\n");
return;
}
module_init(init_dht11_device);
module_exit(exit_dht11_device);
MODULE_LICENSE("GPL");
driver.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
static volatile unsigned int *pGPFBase = NULL;
static int dht11_probe(struct platform_device *device);
static int dht11_open(struct inode *node, struct file *fp);
static ssize_t dht11_read(struct file *fp, char __user *puser, size_t n, loff_t *off);
static int dht11_release(struct inode *node, struct file *fp);
#define SET_DQ_OUT (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)) | (0x1)))
#define SET_DQ_IN (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3))))
#define SET_DQ_HIGH (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1)))
#define SET_DQ_LOW (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1)))
#define GET_DQ_STAT (*(pGPFBase+1) & (0x1))
static struct platform_driver dht11_driver = {
.probe = dht11_probe,
.driver.name = "dht11", //用于匹配的名称
};
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = dht11_open,
.read = dht11_read,
.release = dht11_release,
};
static struct miscdevice misc_dht11 = {
.minor = MISC_DYNAMIC_MINOR,
.name = "dht11",
.fops = &fops,
};
static int dht11_open(struct inode *node, struct file *fp)
{
SET_DQ_OUT;
SET_DQ_HIGH;
return 0;
}
static int dht11_release(struct inode *node, struct file *fp)
{
SET_DQ_OUT;
SET_DQ_HIGH;
return 0;
}
static void send_dht11_start(void)
{
SET_DQ_LOW;
mdelay(20);
SET_DQ_HIGH;
SET_DQ_IN;
return;
}
static int check_dht11_reply(void)
{
int cnt = 0;
while (GET_DQ_STAT && cnt < 24)
{
cnt++;
udelay(10);
}
if (cnt >= 24)
{
return -1;
}
while (!GET_DQ_STAT);
while (GET_DQ_STAT);
return 0;
}
static unsigned char dht11_readbyte(void)
{
int cnt = 0;
int i = 0;
unsigned char ret = 0;
for (i = 7; i >= 0; i--)
{
cnt = 0;
while (!GET_DQ_STAT);
while (GET_DQ_STAT)
{
cnt++;
udelay(1);
}
if (cnt > 40)
{
ret |= (0x1 << i);
}
}
return ret;
}
static ssize_t dht11_read(struct file *fp, char __user *puser, size_t n, loff_t *off)
{
int ret = 0;
unsigned char data[5] = {0};
#if 1
send_dht11_start();
ret = check_dht11_reply();
if (-1 == ret)
{
return -1;
}
data[0] = dht11_readbyte();
data[1] = dht11_readbyte();
data[2] = dht11_readbyte();
data[3] = dht11_readbyte();
data[4] = dht11_readbyte();
SET_DQ_OUT;
SET_DQ_HIGH;
if (data[0] + data[1] + data[2] + data[3] == data[4])
{
copy_to_user(puser, data, sizeof(data)-1);
}
else
{
return -2;
}
#endif
return sizeof(data)-1;
}
static int dht11_probe(struct platform_device *device)
{
int ret = 0;
ret = misc_register(&misc_dht11);
if (ret != 0)
{
return -1;
}
pGPFBase = ioremap(device->resource[0].start, device->resource[0].end - device->resource[0].start);
if (NULL == pGPFBase)
{
return -1;
}
return 0;
}
static int __init init_dht11_driver(void)
{
int ret = 0;
ret = platform_driver_register(&dht11_driver);
if (ret != 0)
{
return -1;
}
printk("platform dht11 driver init success!\n");
return 0;
}
static void __exit exit_dht11_driver(void)
{
platform_driver_unregister(&dht11_driver);
printk("platform dht11 driver exit success!\n");
return;
}
module_init(init_dht11_driver);
module_exit(exit_dht11_driver);
MODULE_LICENSE("GPL");
./app
#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> int main(void) { int fd = 0; unsigned char data[4] = {0}; char temp[32] = {0}; char hum[32] = {0}; ssize_t nret = 0; fd = open("/dev/dht11", O_RDWR); if (-1 == fd) { perror("fail to open"); return -1; } sleep(2); #if 1 while (1) { nret = read(fd, data, sizeof(data)); sprintf(temp, "%d.%d", data[2], data[3]); sprintf(hum, "%d.%d", data[0], data[1]); printf("%d, temp = %s, hum = %s\n", nret, temp, hum); sleep(2); } #endif return 0; }