Android DHT11驱动


struct dht11_sensor_dev{struct cdev cdev;unsigned long pin;unsigned char value[5];unsigned char lock;unsigned int irq;struct timeval lasttv;int bitcount;int bytecount;int started;struct timer_list timer;void (*write_bit)(unsigned long pin, char bit);void (*delay)(short t);};static struct dht11_sensor_dev *dht11_dev;struct class *dht11_class;static int major = DEVICE_MAJOR;static inline void usdelay(short t){return ndelay(t * 1000);}static inline void gpio_write_bit(unsigned long pin, char bit){gpio_set_value(pin, bit);}#if 0static char gpio_read_bit(unsigned long pin){return gpio_get_value(pin) ? 1 : 0;//return gpio_get_value(pin);}static void gpio_write_bit_dir(unsigned long pin, char bit){if (bit)gpio_direction_input(pin);elsegpio_direction_output(pin, 0);}static void gpio_write_bit_val(unsigned long pin, char bit){gpio_set_value(pin, bit);}static int dht11_get_temperature(struct dht11_sensor_dev *dev){return dev->value[0] * 1000 + dev->value[1];}static int dht11_get_humidity(struct dht11_sensor_dev *dev){return dev->value[2] * 1000 + dev->value[3];}#endifstatic irqreturn_t dht11_interrupt(int irq, void *dev_id){struct dht11_sensor_dev *dev = (struct dht11_sensor_dev *)dev_id;struct timeval tv;long deltv = 0;int signal = 0, data = 0;signal = gpio_get_value(dev->pin);do_gettimeofday(&tv);deltv = tv.tv_sec - dev->lasttv.tv_sec;data = (int)(deltv * 1000000 + (tv.tv_usec - dev->lasttv.tv_usec)); dev->lasttv = tv;if(dev->bytecount == 5) return IRQ_HANDLED;if((signal == 1) & (data > 40)){dev->started = 1;return IRQ_HANDLED;}if((signal == 0) & (dev->started == 1)){if(data > 80)return IRQ_HANDLED;if(data < 30){dev->bitcount++;if(dev->bitcount == 8){dev->bitcount = 0;dev->bytecount++;}return IRQ_HANDLED;}if (data > 60)//55 dev->value[dev->bytecount] = dev->value[dev->bytecount] | (0x80 >> dev->bitcount);dev->bitcount++;if(dev->bitcount == 8){dev->bitcount = 0;dev->bytecount++;}}return IRQ_HANDLED;}static int setup_interrupts(void){int result;dht11_dev->irq = gpio_to_irq(dht11_dev->pin);result = request_irq(dht11_dev->irq, dht11_interrupt, IRQ_TYPE_EDGE_BOTH, DEVICE_NAME, (void *)dht11_dev);switch (result) {case -EBUSY:printk(KERN_ERR "*%s(): IRQ %d is busy\n", __func__, dht11_dev->irq);return -EBUSY;case -EINVAL:printk(KERN_ERR "*%s(): Bad irq number or handler\n", __func__);return -EINVAL;default://printk(KERN_INFO "*%s():Interrupt %04x obtained\n", __func__, dht11_dev->irq);break;}return 0;}static void clear_interrupts(void){free_irq(dht11_dev->irq, (void *)dht11_dev);    if(gpio_request(dht11_dev->pin, DEVICE_NAME)){printk(KERN_INFO "[%s] gpio_request \n", __func__);return;}s3c_gpio_cfgpin(dht11_dev->pin, S3C_GPIO_OUTPUT);s3c_gpio_setpull(dht11_dev->pin, S3C_GPIO_PULL_NONE);//s5p_gpio_set_drvstr(dht11_dev->pin, S5P_GPIO_DRVSTR_LV2);gpio_set_value(dht11_dev->pin, 1);gpio_free(dht11_dev->pin);}static int dht11_reset(struct dht11_sensor_dev *dev){    if(gpio_request(dht11_dev->pin, DEVICE_NAME)){printk(KERN_INFO "[%s] gpio_request \n", __func__);return -1;}//s3c_gpio_cfgpin(dht11_dev->pin, S3C_GPIO_OUTPUT);s3c_gpio_cfgpin(dht11_dev->pin, S3C_GPIO_OUTPUT);s3c_gpio_setpull(dht11_dev->pin, S3C_GPIO_PULL_NONE);//s5p_gpio_set_drvstr(dht11_dev->pin, S5P_GPIO_DRVSTR_LV2);gpio_set_value(dht11_dev->pin, 1);dev->write_bit(dev->pin, 0);msleep(18);dev->write_bit(dev->pin, 1);s3c_gpio_cfgpin(dev->pin, S3C_GPIO_INPUT);dev->delay(20);gpio_free(dht11_dev->pin);return 0;}static int dht11_checksum(struct dht11_sensor_dev *dev){char tmp = 0;tmp = dev->value[0] + dev->value[1] + dev->value[2] + dev->value[3];if(tmp != dev->value[4]){//printk(KERN_INFO "[%s] %d %d\n", __func__, dev->value[4], tmp);return 0;}return 1;}static int dht11_sensor_open(struct inode *inode, struct file *filp){if(dht11_dev->lock)return -EBUSY;try_module_get(THIS_MODULE);dht11_dev->lock = 1;return 0;}static int dht11_sensor_release(struct inode *inode,struct file *filp){module_put(THIS_MODULE);dht11_dev->lock = 0;return 0;}static ssize_t dht11_sensor_read(struct file *filp,char __user *buf,size_t size,loff_t *f_pos){unsigned long length =(size>48)? 48:size;int result = 0;char msg[48];dht11_dev->started = 0;dht11_dev->bitcount = 0;dht11_dev->bytecount = 0;dht11_dev->value[0] = 0;dht11_dev->value[1] = 0;dht11_dev->value[2] = 0;dht11_dev->value[3] = 0;dht11_dev->value[4] = 0;if(!dht11_reset(dht11_dev)){do_gettimeofday(&dht11_dev->lasttv);setup_interrupts();}else{dprint("*%s(): reset fail \n", __func__);return -1;}msleep(20);clear_interrupts();//for(i = 0; i < 48; i++) dht11_dev->msg[i] = -1;sprintf(msg, "Humidity=%d.%d%%\nTemperature=%d.%dC\nResult=%d\n%c",\dht11_dev->value[0], dht11_dev->value[1], \dht11_dev->value[2], dht11_dev->value[3], \dht11_checksum(dht11_dev), '\0');length = strlen(msg);dprint(KERN_INFO "*%s(): length %lu\n", __func__, length);#if 0while (length && *ptr) {put_user(*(ptr++), buf++);length--;result++;}put_user('\0', buf++);result++;*f_pos += result;return result;#elseresult=copy_to_user(buf, msg + *f_pos, length);//*f_pos += length;*f_pos = 0;//if(result) return length - result;//else result = length;return length;#endif}#if 0static ssize_t dht11_sensor_write(struct file *filp,const char __user *buf,size_t size,loff_t *f_pos){return 0;}#endifstatic struct file_operations dht11_sensor_fops={.owner = THIS_MODULE,.read = dht11_sensor_read,.open = dht11_sensor_open,.release = dht11_sensor_release,};static void dht11_sensor_setup_cdev(struct dht11_sensor_dev *dev,int minor,struct file_operations *fops){int err, devno = MKDEV(major, minor);cdev_init(&(dev->cdev), fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = fops;err=cdev_add(&(dev->cdev), devno, 1);if(err){printk(KERN_NOTICE"erro %d adding %s %d\n",err,DEVICE_NAME,minor);}}int __init dht11_sensor_init(void){int result;dev_t devno=MKDEV(major,0);if(major){result = register_chrdev_region(devno, 1, DEVICE_NAME);}else{result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);}if(result < 0){printk(KERN_WARNING"%s: unable to get major %d\n",DEVICE_NAME,major);return result;}dht11_dev=kmalloc(sizeof(struct dht11_sensor_dev),GFP_KERNEL);if(!dht11_dev){result=-ENOMEM;goto fail_malloc;}dht11_class = class_create(THIS_MODULE, DEVICE_NAME);device_create(dht11_class, NULL, MKDEV(DEVICE_MAJOR, 0), NULL, DEVICE_NAME);dht11_sensor_setup_cdev(dht11_dev, 0, &dht11_sensor_fops);dht11_dev->pin = GPIO_DOUT;dht11_dev->delay = usdelay;dht11_dev->write_bit = gpio_write_bit;        result = gpio_request(dht11_dev->pin, DEVICE_NAME);if(result){printk(KERN_INFO "[%s] gpio_request \n", __func__);goto fail_gpio;}//s3c_gpio_cfgpin(dht11_dev->pin, S3C_GPIO_OUTPUT);s3c_gpio_cfgpin(dht11_dev->pin, S3C_GPIO_OUTPUT);s3c_gpio_setpull(dht11_dev->pin, S3C_GPIO_PULL_NONE);//s5p_gpio_set_drvstr(dht11_dev->pin, S5P_GPIO_DRVSTR_LV2);gpio_set_value(dht11_dev->pin, 1);//gpio_direction_output(dht11_dev->pin, 1);gpio_free(dht11_dev->pin);return 0;fail_gpio:kfree(dht11_dev);fail_malloc:unregister_chrdev_region(MKDEV(major,0),1);return result;}void  __exit dht11_sensor_exit(void){cdev_del(&dht11_dev->cdev);device_destroy(dht11_class, MKDEV(major, 0));class_destroy(dht11_class);//gpio_free(dht11_dev->pin);kfree(dht11_dev);unregister_chrdev_region(MKDEV(major, 0), 1);//printk("%s device uninstalled OK!\n", DEVICE_NAME);}module_init(dht11_sensor_init);module_exit(dht11_sensor_exit);MODULE_AUTHOR("jvaemape");MODULE_DESCRIPTION("S3C GPIO MQ2 Drive");MODULE_LICENSE("Dual BSD/GPL");


更多相关文章

  1. 代码中设置drawableleft
  2. android 3.0 隐藏 系统标题栏
  3. Android开发中activity切换动画的实现
  4. Android(安卓)学习 笔记_05. 文件下载
  5. Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
  6. 技术博客汇总
  7. android 2.3 wifi (一)
  8. AndRoid Notification的清空和修改
  9. Android中的Chronometer

随机推荐

  1. Android(安卓)无法查看外部依赖jar的源码
  2. Android(安卓)TextView中显示单行过长的
  3. Android中ProgressDialog的简单使用.
  4. ANDROID ADB工具使用
  5. android 中使文本(TextView 、button等可
  6. Android:adb常用命令汇总
  7. Android:控件GridView的使用
  8. android布局属性详解
  9. android 自定义SeekBar
  10. Android消息机制不完全解析(上)