• 将DHT11移植到Linux系统上(转)


    由于项目需要,需要将DHT11移植到Linux。驱动程序如下

    [plain] view plain copy
     
    1. #include <linux/kernel.h>  
    2. #include <linux/module.h>  
    3. #include <linux/slab.h>  
    4. #include <linux/input.h>  
    5. #include <linux/init.h>  
    6. #include <linux/errno.h>  
    7. #include <linux/serio.h>  
    8. #include <linux/delay.h>  
    9. #include <linux/clk.h>  
    10. #include <linux/wait.h>  
    11. #include <linux/sched.h>  
    12. #include <linux/cdev.h>  
    13. #include <linux/miscdevice.h>  
    14. #include <linux/gpio.h>  
    15. #include <mach/gpio.h>  
    16. #include <asm-generic/uaccess.h>  
    17. #include <linux/spinlock.h>  
    18. #include <linux/mutex.h>  
    19.   
    20.   
    21. #define DEVICE_NAME "dht11"  
    22. #define PIN S5PV210_GPH0(0)  
    23.   
    24. typedef unsigned char  U8;   
    25. unsigned char buf[6];  
    26. unsigned char check_flag;  
    27. //spinlock_t lock=SPIN_LOCK_UNLOCKED;  
    28.   
    29. //spinlock_t lock=SPIN_LOCK_UNLOCKED;  
    30.   
    31. //DEFINE_SPINLOCK(lock);  
    32. static  DEFINE_MUTEX(mutex);  
    33. int read_one_bit(void)          //从io口中读一个字节  
    34. {  
    35.     gpio_direction_input(PIN);  
    36.     return gpio_get_value(PIN);  
    37. }  
    38.   
    39.   
    40. void gpio_out(int value)   //将io口设置为输出,并设置电平  
    41. {  
    42.     gpio_direction_output(PIN,value);  
    43. }  
    44.   
    45. unsigned char  humidity_read_byte(void)  
    46. {      
    47.     int i=0;  
    48.     int num;   
    49.     unsigned char flag=0;  
    50.     unsigned char data=0;  
    51.       
    52.   
    53.     for(num=0;num<8;num++)  
    54.     {                
    55.           i=0;  
    56.           while(!gpio_get_value(PIN))  
    57.           {  
    58.             udelay(10);  
    59.             i++;  
    60.             if(i>10)  
    61.             break;  
    62.            }  
    63.             flag=0x0;  
    64.             udelay(28);              
    65.            if(gpio_get_value(PIN))  
    66.            {  
    67.             flag=0x01;            
    68.            }  
    69.             i=0;  
    70.            while(gpio_get_value(PIN))  
    71.            {  
    72.             udelay(10);  
    73.             i++;  
    74.             if(i>12)  
    75.             break;  
    76.            }  
    77.            data<<=1;  
    78.            data|=flag;  
    79.     }    
    80.     return data;  
    81. }  
    82.   
    83.   
    84. void humidity_read_data(void)  
    85. {  
    86.     int i=0;  
    87.     gpio_out(0);  
    88.     mdelay(30);  
    89.     gpio_out(1);  
    90.     udelay(20);      
    91.     if(read_one_bit()== 0)  
    92.     {   
    93.         while(!gpio_get_value(PIN))  
    94.         {  
    95.            udelay(5);  
    96.            i++;  
    97.             if(i>20)  
    98.             {  
    99.                 printk("humidity_read_data %d err! ",__LINE__);  
    100.                 break;  
    101.             }  
    102.         }  
    103.         i=0;  
    104.         while(gpio_get_value(PIN))  
    105.         {  
    106.            udelay(5);  
    107.            i++;  
    108.            if(i>20)  
    109.            {  
    110.               printk("humidity_read_data %d err! ",__LINE__);  
    111.               break;  
    112.            }  
    113.         }  
    114.         for(i=0;i<5;i++)  
    115.         buf[i]=humidity_read_byte();    
    116.          
    117.         buf[5]=buf[0]+buf[1]+buf[2]+buf[3];  
    118.   
    119.         if(buf[4]==buf[5])  
    120.         {  
    121.            check_flag=0xff;  
    122.            printk("humidity check pass ");  
    123.            printk("humidity=[%d],temp=[%d] ",buf[0],buf[2]);  
    124.         }  
    125.         else  
    126.         {  
    127.            check_flag=0x0;  
    128.            printk("humidity check fail ");             
    129.         }                     
    130.     }  
    131. }  
    132.   
    133.   
    134. static ssize_t humidiy_read(struct file *file, char __user *buffer, size_t size, loff_t *off)  
    135. {  
    136.         int ret;  
    137.         local_irq_disable();  
    138.         humidity_read_data();  
    139.         local_irq_enable();  
    140.         if(check_flag==0xff)  
    141.         {  
    142.              ret=copy_to_user(buffer,buf,sizeof(buf));  
    143.              if(ret<0){  
    144.               printk("copy to user err ");  
    145.               return -EAGAIN;  
    146.               }  
    147.              else  
    148.              return  0;  
    149.          }  
    150.          else  
    151.              return -EAGAIN;      
    152. }  
    153.   
    154. static int humidiy_open(struct inode *inode, struct file *file)  
    155. {  
    156.     printk("open in kernel ");  
    157.     return 0;  
    158. }  
    159.   
    160. static int humidiy_release(struct inode *inode, struct file *file)  
    161. {  
    162.     printk("humidity release ");  
    163.     return 0;  
    164. }  
    165.   
    166. static struct file_operations humidity_dev_fops={  
    167.     .owner          = THIS_MODULE,  
    168.     .open           = humidiy_open,  
    169.     .read           = humidiy_read,  
    170.     .release        = humidiy_release,  
    171. };  
    172.   
    173. static struct miscdevice humidity_dev = {  
    174.     .minor          = MISC_DYNAMIC_MINOR,  
    175.     .name           = DEVICE_NAME,  
    176.     .fops           = &humidity_dev_fops,  
    177. };  
    178.   
    179. static int __init humidity_dev_init(void)   
    180. {  
    181.     int ret;  
    182.     ret = gpio_request(PIN , "humidity");  
    183.     if (ret){  
    184.       printk("%s: request GPIO %d for humidity failed, ret = %d ", DEVICE_NAME,PIN , ret);  
    185.       return ret;  
    186.     }  
    187.     gpio_direction_output(PIN, 1);  
    188.     ret = misc_register(&humidity_dev);  
    189.     printk("humidity_dev_init ");  
    190.     return ret;  
    191. }  
    192.   
    193. static void __exit humidity_dev_exit(void)  
    194. {  
    195.     gpio_free(PIN);  
    196.     misc_deregister(&humidity_dev);  
    197. }  
    198.   
    199. module_init(humidity_dev_init);  
    200. module_exit(humidity_dev_exit);  
    201.   
    202. MODULE_LICENSE("GPL");  
    203. MODULE_AUTHOR("WWW")  


    测试程序如下

    [plain] view plain copy
     
    1. #include<stdio.h>  
    2. #include<sys/types.h>  
    3. int main()  
    4. {  
    5.     int humidityfd;  
    6.     int ret;  
    7.     char buf[5];  
    8.     unsigned char  tempz = 0;  
    9.     unsigned char  tempx = 0;       
    10.     unsigned char  humidiyz = 0;  
    11.     unsigned char  humidiyx = 0;      
    12.     humidityfd = open("/dev/humidity",0);  
    13.     if(humidityfd<0){  
    14.         printf("/dev/humidiy open fail ");  
    15.         return 0;       }                             
    16.     while(1){         
    17.     ret=read(humidityfd,buf,sizeof(buf));  
    18.                 if(ret<0)  
    19.                 printf("read err! ");  
    20.                 else{  
    21.         humidiyz  =buf[0];    
    22.         humidiyx  =buf[1];    
    23.         tempz     =buf[2] ;       
    24.         tempx     =buf[3];        
    25.         printf("humidity = %d.%d%% ", humidiyz, humidiyx);  
    26.         printf("temp = %d.%d ",tempz,tempx);     
    27.                 }  
    28.         sleep(2);  
    29.     }  
    30.     close(humidityfd);  
    31.     return 0;  
    32. }  

    本想,这驱动调试起来应该简单的。但在调试到过程中,发现采集到的数据有时正确,有时错误,成功率约为50%。于是按照手册微调一下时序,并没有解决问题。网上查阅相关资料,发现都是用单片机来编程的。当程序本来就是以裸奔的思想跑的,为什么移植到Linux会出错呢?从dht11出来的信号都正常啊。误打误撞,使用local_irq_disable这个函数后,读出的数据都正常啦。local_irq_disable通过屏蔽中断标志位,从而禁止内核的抢占。我猜测是Linux是个多任务系统,该系统按照一定的算法(每隔一段时间就会去跑另一段程序,时间不固定),调用一次驱动去读取数据的过程中(时间较长相对于时间片),这期间CPU去做其他事情了,等重新回来读取数据时,有可能错过了时序中的某个片段,从而出现有时读取数据正常,有时错误这种现象。

    http://blog.csdn.net/mike8825/article/details/50804978

  • 相关阅读:
    ArrayList 和 LinkList 的区别
    fork()相关的源码解析
    http协议状态码及其意义
    数据库的死锁相关知识
    JDBC事务的相关知识
    请求http页面的相关过程
    static 关键字的作用
    计算机网络网络层的IP地址划分及子码
    文件的相关操作.
    set集合和深浅拷贝
  • 原文地址:https://www.cnblogs.com/xihong2014/p/7208424.html
Copyright © 2020-2023  润新知