kernel里面集成了1-wire(单总线驱动了),只需要的在平台配置文件中配置即可,不管是设备树还是平台外设的头文件。
1、在board-am335xevm.c文件中增加W1-GPIO的头文件。
#include <linux/w1-gpio.h>
2、配置W1-GPIO所使用的管脚
/* add w1-gpio */
static void w1_enable_external_pullup(int enable)
{
gpio_set_value(GPIO_TO_PIN(1, 27), enable);
}
static struct w1_gpio_platform_data w1_gpio_pdata = {
.pin = GPIO_TO_PIN(1, 27),
.is_open_drain= 0,
//.enable_external_pullup = w1_enable_external_pullup,
};
static struct platform_device w1_device = {
.name = "w1-gpio",
.id = -1,
.dev.platform_data= &w1_gpio_pdata,
};
/*
static struct pinmux_config w1_gpio_pin_mux[] = {
{"gpmc_a11.gpio1_27", OMAP_MUX_MODE7 },//| AM33XX_PIN_OUTPUT},
{NULL, 0},
};
*/
static void w1_init(int evm_id, int profile )
{
int err;
//setup_pin_mux(w1_gpio_pin_mux);//我配置了这个管脚一直没有办法读取管脚状态
err = platform_device_register(&w1_device);
if (err)
pr_err("failed to register w1-gpio\n");
else
pr_info("w1-gpio connected to GPIO1_27\n");
}
3、在make menuconfig中配置
支持w1-gpio和ds18b20驱动:
这是重新编译新内核并烧写重启。
Device Drivers --->
<*> Dallas's 1-wire support --->
--- Dallas's 1-wire support
1-wire Bus Masters --->
<*> GPIO 1-wire busmaster
1-wire Slaves --->
<*> Thermal family implementation
/nfsswap # cd /sys/devices/w1_bus_master1/
/sys/devices/w1_bus_master1 # ls
28-0316423ecfff w1_master_name
driver w1_master_pointer
power w1_master_pullup
subsystem w1_master_remove
uevent w1_master_search
w1_master_add w1_master_slave_count
w1_master_attempts w1_master_slaves
w1_master_max_slave_count w1_master_timeout
/sys/devices/w1_bus_master1 # cd 28-0316423ecfff/
/sys/devices/w1_bus_master1/28-0316423ecfff # ls
driver id name power subsystem uevent w1_slave
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
e2 01 4b 46 7f ff 0c 10 00 : crc=00 YES
e2 01 4b 46 7f ff 0c 10 00 t=30125
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
e2 01 4b 46 7f ff 0c 10 00 : crc=00 YES
e2 01 4b 46 7f ff 0c 10 00 t=30125
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
e1 01 4b 46 7f ff 0c 10 c5 : crc=c5 YES
e1 01 4b 46 7f ff 0c 10 c5 t=30062
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
e1 01 4b 46 7f ff 0c 10 c5 : crc=c5 YES
e1 01 4b 46 7f ff 0c 10 c5 t=30062
/sys/devices/w1_bus_master1/28-0316423ecfff #
/sys/devices/w1_bus_master1/28-0316423ecfff # cd /sys/bus/w1/
/sys/bus/w1 # ls
devices drivers_autoprobe uevent
drivers drivers_probe
/sys/bus/w1 # cd devices/
/sys/bus/w1/devices # ls
28-0316423ecfff w1_bus_master1
/sys/bus/w1/devices # cd 28-0316423ecfff/
/sys/devices/w1_bus_master1/28-0316423ecfff # ls
driver id name power subsystem uevent w1_slave
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
de 01 4b 46 7f ff 0c 10 c3 : crc=c3 YES
de 01 4b 46 7f ff 0c 10 c3 t=29875
/sys/devices/w1_bus_master1/28-0316423ecfff # cat w1_slave
de 01 4b 46 7f ff 0c 10 c3 : crc=c3 YES
de 01 4b 46 7f ff 0c 10 c3 t=29875
/sys/devices/w1_bus_master1/28-0316423ecfff #
另外一种是注册成一个char字符设备:
驱动源代码:
/*********************************************************************************
* Copyright: (C) 2015 songyong<handy_skyoutlook.com>
* All rights reserved.
*
* Filename: ds18b20drv.c
* Description: This file
*
* Version: 1.0.0(2017年06月22日)
* changer: zue
* ChangeLog: 1, Release initial version on "2017年06月22日"
*
********************************************************************************/
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<linux/gpio.h>
#include<linux/types.h>
#include<asm/irq.h>
#include<linux/device.h>
#include<linux/kdev_t.h>
#include<linux/cdev.h>
#include<linux/errno.h>
#include<asm/uaccess.h>
#include <linux/gpio.h>
#include <linux/phy.h>
#include <linux/gpio.h>
#define D_MAJOR 0
#define D_MINOR 0
#define DEV_NAME "ds18b20"
static int ds18b20_major = D_MAJOR;
static int ds18b20_minor = D_MINOR;
/* Convert GPIO signal to GPIO pin number */
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
#define W1GPIO GPIO_TO_PIN(1,27)
struct ds18b20_device
{
struct class *sy_class;
struct cdev cdev;
};
static struct ds18b20_device dev;//若使用指针,记得给指针开辟空间。
static unsigned int ds18b20_reset(void)
{
int err;
gpio_direction_output(W1GPIO,0);
gpio_set_value(W1GPIO,1);
udelay(10);
gpio_set_value(W1GPIO,0);
udelay(600);
gpio_set_value(W1GPIO,1);
udelay(60);
gpio_direction_input(W1GPIO);
udelay(400);
err = gpio_get_value(W1GPIO);
//err = s3c2410_gpio_getpin(DQ);
return err;
}
static unsigned int ds18b20_write(unsigned char data)
{
unsigned int i;
gpio_direction_output(W1GPIO,0);
for (i = 0; i < 8; i++) //只能一位一位的读写
{
gpio_set_value(W1GPIO,0);
udelay(5);
if(data & 0x01)
{
gpio_set_value(W1GPIO,1);
udelay(60);
}
else udelay(60);
data >>= 1; //从最低位开始判断;每比较完一次便把数据向右移,获得新的最低位状态
gpio_set_value(W1GPIO,1);
udelay(1);
}
return 2;
}
static unsigned int ds18b20_read(void)
{
unsigned int i ;
unsigned char data = 0x00;
for (i =0; i < 8 ; i++)
{
gpio_direction_output(W1GPIO,1);
gpio_set_value(W1GPIO,1);
udelay(1);
gpio_set_value(W1GPIO,0);
udelay(2);
gpio_set_value(W1GPIO,1);
gpio_direction_input(W1GPIO);
data >>= 1;
if(0 != gpio_get_value(W1GPIO))//s3c2410_gpio_getpin(DQ))
data |= 0x80; //最低位数据从data的最高位放起,边放边右移直到读取位完毕。
udelay(60);
}
return data;
}
static ssize_t read_ds18b20(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
unsigned char Data[2] = {0x00, 0x00};
unsigned long err;
int flag;
flag = ds18b20_reset();
if(flag <= 0)
{
printk("ds18b20 init fail!\n");
return -1;
}
ds18b20_write(0xcc);
ds18b20_write(0x44);
ds18b20_reset();
if(flag <= 0)
{
printk("ds18b20 init fail!\n");
return -1;
}
ds18b20_write(0xcc);
ds18b20_write(0xbe);
Data[0] = ds18b20_read();
Data[1] = ds18b20_read();
ds18b20_reset();
err = copy_to_user(buf, Data, sizeof(Data));
return err? -EFAULT:count;
}
#if 1
static int open_ds18b20(struct inode *inode, struct file *filp)
{
int flag = 0;
flag = ds18b20_reset();
if(flag)
{
printk("open ds18b20 successful!\n");
}
else printk("open ds18b20 failed!\n");
return 0;
}
#endif
static int release_ds18b20(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations fops={
.owner = THIS_MODULE,
.read = read_ds18b20,
.open = open_ds18b20,
.release = release_ds18b20,
};
static int __init ds18b20_init(void)
{
int result,err;
dev_t devno = 0;
int ret=0;
if(ds18b20_major)
{
devno = MKDEV(ds18b20_major, ds18b20_minor);
result = register_chrdev_region(devno, 1, DEV_NAME);
}
else{
result = alloc_chrdev_region(&devno, ds18b20_minor, 1, DEV_NAME);
ds18b20_major = MAJOR(devno);
}
if(result < 0)
{
printk(KERN_ERR "%s can't use major %d\n",DEV_NAME, ds18b20_major);
}
printk("%s use major %d\n",DEV_NAME, ds18b20_major);
cdev_init(&dev.cdev,&fops);
dev.cdev.owner = THIS_MODULE;
err = cdev_add(&dev.cdev, devno, 1);
if(err)
{
printk(KERN_NOTICE"ERROR %d add ds18b20\n",err);
goto ERROR;
}
dev.sy_class = class_create(THIS_MODULE, DEV_NAME);
device_create(dev.sy_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEV_NAME);
printk(KERN_NOTICE"Ds18b20 is ok!\n");
ret = gpio_request(W1GPIO,"gpio1_27");
if (ret < 0)
pr_warning("w1-gpio Unable to request GPIO_W1_PULLUP_ENABLE\n");
return 0;
ERROR:
printk(KERN_ERR"%s driver installed failure.\n",DEV_NAME);
cdev_del(&dev.cdev);
unregister_chrdev_region(devno, 1);
return err;
}
static void __exit ds18b20_exit(void)
{
dev_t devno = MKDEV(ds18b20_major, 0);
cdev_del(&dev.cdev);
device_destroy(dev.sy_class,devno);
class_destroy(dev.sy_class);
unregister_chrdev_region(devno, 1);
printk(KERN_NOTICE"bye ds18b20!\n");
}
module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("zue");
/*********************************************************************************
* Copyright: (C) 2015 songyong<handy_skyoutlook.com>
* All rights reserved.
*
* Filename: ds18b20drv.c
* Description: This file
*
* Version: 1.0.0(2017年06月22日)
* changer: zue
* ChangeLog: 1, Release initial version on "2017年06月22日"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/********************************************************************************
* Description:
* Input Args:
* Output Args:
* Return Value:
********************************************************************************/
int main (int argc, char **argv)
{
int fd;
int i = 0;
int data = 0;
unsigned char result[2];
float temperature = 0;
printf("will open fd... \n");
if((fd = open("/dev/ds18b20",O_RDWR|O_NONBLOCK)) < 0 )
{
perror("open device fail.\n");
return -1;
}
else printf("Open Device Ds18b20 Successful!!\n");
while(1)
{
int ret;
printf("\nWill read temperature...\n");
usleep(100);
ret = read(fd, result, sizeof(result));
if(ret != 2)
{
printf("read wrong\n");
exit(0);
}
else printf("read success !\n");
data = (int)result[1];
data <<=8;
data = data | result[0];
temperature =data * 0.0625 ;
printf("Temperature = %.2f ℃\n",temperature);
fflush(stdout);
sleep(1);
}
close(fd);
return 0;
} /* ----- End of main() ----- */
[ 316.888937] ds18b20 use major 250
[ 316.893126] Ds18b20 is ok!
/nfsswap #
/nfsswap #
/nfsswap # ./DS18B20ts
will open fd... [ 321.254457] open ds18b20 successful!
Open Device Ds18b20 Successful!!
Will read temperature...
read success !
Temperature = 29.88 ℃
Will read temperature...
read success !
Temperature = 29.81 ℃
Will read temperature...
read success !
Temperature = 29.81 ℃
Will read temperature...
read success !
Temperature = 29.81 ℃
Will read temperature...
read success !
Temperature = 29.81 ℃
Will read temperature...
read success !
Temperature = 29.81 ℃