[Linux下menuconfig與Kconfig基礎知識概要](https://www.cnblogs.com/chorm590/p/13977818.html)
[編譯器](https://hackmd.io/@ofAlpaca/ryNNXAuoQ/https%3A%2F%2Fhackmd.io%2Fs%2FB1aGFRW6Q?type=book)
[Android makefile 變數名稱定義](https://www.cnblogs.com/chenbin7/archive/2013/01/05/2846863.html)
[Linux 基本觀念](https://dywang.csie.cyut.edu.tw/dywang/linuxSystem/linuxSystem.html)
[HAL - 硬體驅動](https://hackmd.io/@AlienHackMd/B1rTpFrxi)
[Android編譯系統](https://hackmd.io/@AlienHackMd/SJ_1iUIw_#Android-%E7%B7%A8%E8%AD%AF%E7%B3%BB%E7%B5%B11)
[跟我一起寫makefile PDF版](https://seisman.github.io/how-to-write-makefile/Makefile.pdf)
[跟我一起寫makefile 網頁版](https://seisman.github.io/how-to-write-makefile/introduction.html)
[【小常識】從按鈕開關看上拉pull-up電阻下拉電阻是蝦密碗糕](https://www.arduino.cn/thread-13186-1-1.html)
[探討Designated Initializers](https://meetonfriday.com/posts/39485259/)
之後有空可以玩玩看 -> [可编程像素屏](https://www.youtube.com/watch?v=ExfKmG-m1SY)
---
[溫濕度datasheet](https://cdn-shop.adafruit.com/datasheets/DHT11-chinese.pdf)
```clike=
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <asm-generic/uaccess.h>
#include <linux/spinlock.h>
#define DEVICE_MAJOR 232
#define DEVICE_NAME "dht11"
#define PIN EXYNOS4_GPX0(6)
typedef unsigned char U8;
unsigned char buf[6];
//DEFINE_SPINLOCK(lock);
unsigned char check_flag;
int data_in(void)
{
gpio_direction_input(PIN);
return gpio_get_value(PIN);
}
void gpio_out(int value) //set gpio is output
{
gpio_direction_output(PIN,value);
}
void humidity_read_data(void)
{
int i=0,j=0;
int num;
unsigned char flag=0;
unsigned char data=0;
gpio_out(0);
mdelay(30);
gpio_out(1);
udelay(40);
if(data_in() == 0)
{
while(!gpio_get_value(PIN))
{
udelay(5);
i++;
if(i>20)
{
printk("error data!\n");
break;
}
}
i=0;
while(gpio_get_value(PIN))
{
udelay(5);
i++;
if(i>20)
{
printk("error data!\n");
break;
}
}
}
for(i = 0;i < 5;i++)
{
for(num = 0;num < 8;num++)
{
j = 0;
while( !gpio_get_value(PIN) )
{
udelay(10);
j++;
if(j > 40)
break;
}
flag = 0x0;
udelay(28);
if( gpio_get_value(PIN) )
{
flag = 0x01;
}
j = 0;
while( gpio_get_value(PIN) )
{
udelay(10);
j++;
if(j > 60)
break;
}
data<<=1;
data|=flag;
}
buf[i] = data;
}
buf[5] = buf[0] + buf[1] + buf[2] + buf[3];
if(buf[4] == buf[5])
{
check_flag = 0xff;
printk("humidity check pass\n");
printk("humidity=[%d],temp=[%d]\n", buf[0], buf[2]);
}
else
{
check_flag = 0x0;
printk("humidity check fail\n");
}
}
static ssize_t humidiy_read(struct file *file, char* buffer, size_t size, loff_t *off)
{
int ret;
local_irq_disable();
humidity_read_data();
local_irq_enable();
if(check_flag == 0xff)
{
ret = copy_to_user(buffer,buf,sizeof(buf));
if(ret < 0)
{
printk("copy to user err\n");
return -EAGAIN;
}
else
{
return 0;
}
}
else
{
return -EAGAIN;
}
}
static int humidiy_open(struct inode *inode, struct file *file)
{
printk("open in kernel\n");
return 0;
}
static int humidiy_release(struct inode *inode, struct file *file)
{
printk("humidity release\n");
return 0;
}
static struct file_operations humidity_dev_fops={
owner : THIS_MODULE,
open : humidiy_open,
read : humidiy_read,
release : humidiy_release,
};
static struct class *dht_class;
static int __init humidity_dev_init(void)
{
/*
* Register device
*/
int ret;
ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &humidity_dev_fops);
if (ret < 0) {
printk(KERN_INFO "%s: registering device %s with major %d failed with %d\n",
__func__, DEVICE_NAME, DEVICE_MAJOR, DEVICE_MAJOR );
return(ret);
}
printk("DHT11 driver register success!\n");
dht_class = class_create(THIS_MODULE, "dht11");
if (IS_ERR(dht_class))
{
printk(KERN_WARNING "Can't make node %d\n", DEVICE_MAJOR);
return PTR_ERR(dht_class);
}
device_create(dht_class, NULL, MKDEV(DEVICE_MAJOR, 0), NULL, DEVICE_NAME);
printk("DHT11 driver make node success!\n");
// Reserve gpios
if( gpio_request( PIN, DEVICE_NAME ) < 0 ) // request pin 2
{
printk( KERN_INFO "%s: %s unable to get TRIG gpio\n", DEVICE_NAME, __func__ );
ret = -EBUSY;
return(ret);
}
// Set gpios directions
if( gpio_direction_output( PIN, 1) < 0 ) // Set pin 2 as output with default value 0
{
printk( KERN_INFO "%s: %s unable to set TRIG gpio as output\n", DEVICE_NAME, __func__ );
ret = -EBUSY;
return(ret);
}
return 0;
}
static void __exit humidity_dev_exit(void)
{
gpio_free(PIN);
unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);
}
module_init(humidity_dev_init);
module_exit(humidity_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("WWW");
```