根据上一篇可以在内核里增加自己的驱动
这次我们让程序跑起来
app可以从驱动中提取出自己想要的值
发现传感器在arm上 有明显抖动
所以读取数值之前,大约要进行15次的数据读取,才能得到正常的数据
测试结果
最后app得到的数据已经稳定
代码
second_drv.c
#include<linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <linux/gpio.h>
#include <asm/gpio.h>
#include <asm/delay.h>
#include <linux/clk.h>
#include <mach/gpio.h>
#include <mach/soc.h>
#include <mach/platform.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/errno.h>
#include <linux/serio.h>
#include <linux/wait.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/gpio.h>
#include <linux/gpio.h>
#define CFG_IO_X6818_Humity (PAD_GPIO_B + 29)
static struct class *seconddrv_class;
static struct class_device *seconddrv_class_dev;
volatile unsigned long *gpbcon;
volatile unsigned long *gpbdat;
int data_in(void) {
gpio_direction_input(CFG_IO_X6818_Humity);
return gpio_get_value(CFG_IO_X6818_Humity);
}
/*************************************************
*管教设置为输出
*************************************************/
void data_out(int data) {
gpio_direction_output(CFG_IO_X6818_Humity, data);
}
void DHT11_Rst(void)
{
data_out(0); //SET OUTPUT
mdelay(20);//拉低至少18ms
data_out(1); //DQ=1
udelay(30); //主机拉高20~40us
}
u8 DHT11_Check(void)
{
u8 retry=0;
while (data_in()&&retry<100)//DHT11会拉低40~80us
{
retry++;
udelay(1);
};
if(retry>=100)return 1;
else retry=0;
while (!data_in()&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
udelay(1);
};
if(retry>=100)return 1;
return 0;
}
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(data_in()&&retry<100)//等待变为低电平
{
retry++;
udelay(1);
}
retry=0;
while(!data_in()&&retry<100)//等待变高电平
{
retry++;
udelay(1);
}
udelay(40);//等待40us
if(data_in())return 1;
else return 0;
}
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
u8 DHT11_Read_Data(u8 *temp,u8 *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];
*temp=buf[2];
}
}else return 1;
return 0;
}
static int second_drv_open(struct inode *inode, struct file *file)
{
//gpio_direction_input(CFG_IO_X6818_Humity);
return 0;
}
ssize_t second_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
/* 返回4个引脚的电平 */
unsigned int dht11_vals[2];
u8 temperature;
u8 humidity;
int i ;
for (i = 0;i<15;i++)
{
DHT11_Read_Data(&temperature,&humidity);
mdelay(2000);
printk("the tem is %d,hum is %d\n",temperature,humidity);
}
DHT11_Read_Data(&temperature,&humidity);
printk("the tem is %d,hum is %d\n",temperature,humidity);
mdelay(2000);
dht11_vals[0] = temperature;
dht11_vals[1] = humidity;
copy_to_user(buf, dht11_vals, sizeof(dht11_vals));
return sizeof(dht11_vals);
}
static struct file_operations sencod_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = second_drv_open,
.read = second_drv_read,
};
int major;
static int second_drv_init(void)
{
major = register_chrdev(0, "second_drv", &sencod_drv_fops);
seconddrv_class = class_create(THIS_MODULE, "second_drv");
seconddrv_class_dev = device_create(seconddrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */
return 0;
}
static void second_drv_exit(void)
{
unregister_chrdev(major, "second_drv");
device_unregister(seconddrv_class_dev);
class_destroy(seconddrv_class);
return 0;
}
module_init(second_drv_init);
module_exit(second_drv_exit);
MODULE_LICENSE("GPL");
seconddrvtest.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/termios.h>
int main()
{
int fd;
int ret ;
unsigned int dht11_vals[2];
fd = open("/dev/buttons", 0);
if (fd < 0)
{
printf("can't open!\n");
}
read(fd, dht11_vals, sizeof(dht11_vals));
printf("end the tem is %d,hum is %d\n",dht11_vals[0],dht11_vals[1]);
close(fd);
return 0;
}
Makefile
#内核要提前编译好
KERN_DIR = /home/scholar/Desktop/6818GEC/kernel
#-C 是转到后面的目录'$(KERN_DIR)',使用这个目录下面的 Makefile 编译
#M是指当前目标是什么
#moudule 是指目标
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += second_drv.o