使用的传感器:温度传感器DS18B20。
系统平台:s5pv210
操作系统:Android4.0
这是驱动程序drvier.c
/*
* Copyright (c) 2013 Lee Sheen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#ifndef _FS210_GPIO_H_
#define _FS210_GPIO_H_
#define FS210_GPIO_MAJOR 260
#define FS210_GPIO_MINOR 0
#define DEVICE_NAME "fs210_gpio"
#define GPH1CON 0xE0200C20
#define GPH1DAT 0xE0200C24
#define GPH1PUD 0xE0200C28
#define GPC0CON 0xE0200060
#define GPC0DAT 0xE0200064
#define GPC0PUD 0xE0200068
#define GPIO_ON _IOW('G', 0, int)
#define GPIO_OFF _IOW('G', 1, int)
#endif
static dev_t devno;
static int gpio_major = FS210_GPIO_MAJOR;
static int gpio_minor = FS210_GPIO_MINOR;
static struct class *class;
static struct cdev cdev;
static unsigned int *gph1con, *gph1dat, *gph1pud;
static unsigned int *gpc0con, *gpc0dat, *gpc0pud;
spinlock_t lock;
static int gpio_open(struct inode *inode, struct file *filp)
{
gph1con = ioremap(GPH1CON, 4);
gph1dat = ioremap(GPH1DAT, 4);
gph1pud = ioremap(GPH1PUD, 4);
gpc0con = ioremap(GPC0CON, 4);
gpc0dat = ioremap(GPC0DAT, 4);
gpc0pud = ioremap(GPC0PUD, 4);
spin_lock_init(&lock);
printk(KERN_INFO "fs210-gpio: Device Open,init DS18B20.\n");
return 0;
}
static void Init_DS18B2O(void)//Init_DS18B2O
{
unsigned int retvalue=1;
writel((readl(gph1con) & 0xFFFFFFF0) | 0x1, gph1con);//gph1_0,output
writel(readl(gph1dat) | 0x1 , gph1dat);
__udelay(1);
writel(readl(gph1dat) &(0xFFFFFFFE), gph1dat);
__udelay(500);
writel(readl(gph1dat) | 0x1 , gph1dat);
__udelay(20);
writel(readl(gph1con) & 0xFFFFFFF0, gph1con);//gph1_0,input
__udelay(100);
if (!(readl(gph1dat)&0x01))
{
retvalue=0;
}
printk("init is %d\n",retvalue);
}
static int gpio_relrease(struct inode *inode, struct file *filp)
{
iounmap(gph1con);
iounmap(gph1dat);
iounmap(gph1pud);
iounmap(gpc0con);
iounmap(gpc0dat);
iounmap(gpc0pud);
return 0;
}
static unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat=0;
spin_lock(&lock);
for (i=8;i>0;i--)
{
dat>>=1;
writel((readl(gph1con) & 0xFFFFFFF0) | 0x1, gph1con);//gph1_0,output
writel(readl(gph1dat) &(0xFFFFFFFE), gph1dat);
__udelay(2);//
writel(readl(gph1con) & 0xFFFFFFF0, gph1con);//gph1_0,input
__udelay(1);//
if((readl(gph1dat)&0x01))
{ dat |=0x80;}
__udelay(62);
}
spin_unlock(&lock);
return (dat);
}
static void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
writel((readl(gph1con) & 0xFFFFFFF0) | 0x1, gph1con);//gph1_0,output
spin_lock(&lock);
for(i=0;i<8;i++)
{
writel(readl(gph1dat) &(0xFFFFFFFE), gph1dat);
__udelay(15);
if(dat&0x01)
{
writel(readl(gph1dat) | 0x1 , gph1dat);
}
else
{
writel(readl(gph1dat) &(0xFFFFFFFE), gph1dat);
}
__udelay(45);
writel(readl(gph1dat) | 0x1 , gph1dat);
__udelay(1);
dat>>=1;
}
spin_unlock(&lock);
}
static unsigned int ReadTemp(void)
{
unsigned char T_h=0;
unsigned char T_l=0;
unsigned int temp=0;
writel((readl(gph1pud) & 0xFFFc) | 0x02, gph1pud);//gph1_0,pull-up enabled
spin_lock(&lock);
Init_DS18B2O();
spin_unlock(&lock);
__udelay(400);
writel((readl(gph1con) & 0xFFFFFFF0) | 0x1, gph1con);//gph1_0,output
writel(readl(gph1dat) | 0x1 , gph1dat);
WriteOneChar(0xcc);
WriteOneChar(0x44);
mdelay(100);
spin_lock(&lock);
Init_DS18B2O();
spin_unlock(&lock);
__udelay(400);
writel((readl(gph1con) & 0xFFFFFFF0) | 0x1, gph1con);//gph1_0,output
writel(readl(gph1dat) | 0x1 , gph1dat);
WriteOneChar(0xcc);
WriteOneChar(0xBE);
T_l=ReadOneChar();//L
T_h=ReadOneChar();//H
temp=(unsigned int) (((unsigned int)T_h<<8)|T_l);
printk("temp=%x\r\n",temp);
return temp;
}
static int gpio_ioctl(struct file *filp, unsigned int cmd, unsigned int *arg)
{
unsigned int ret;
switch(cmd) {
case GPIO_ON:
ret= ReadTemp();
arg=&ret;
break;
default:
ret = -1;
}
return ret;
}
static struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.open = gpio_open,
.release = gpio_relrease,
.unlocked_ioctl = gpio_ioctl,
};
static int __init gpio_init(void)
{
int ret = 0;
if (gpio_major) {
devno = MKDEV (gpio_major, gpio_minor);
ret = register_chrdev_region(devno, 1, DEVICE_NAME);
} else {
ret = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
gpio_major = MAJOR (devno);
}
if (ret < 0) {
printk(KERN_WARNING "%s %s: Unable to get major!\n", DEVICE_NAME, __func__);
goto err_devno;
}
cdev_init(&cdev, &gpio_fops);
cdev.owner = THIS_MODULE;
ret = cdev_add(&cdev, devno, 1);
if (ret < 0) {
printk(KERN_WARNING "%s %s: Unable to add cdev!\n", DEVICE_NAME, __func__);
goto err_cdev;
}
class = class_create(THIS_MODULE, "fs210-gpio_class");
if (IS_ERR(class)) {
printk(KERN_WARNING "%s %s: Fail to create class\n", DEVICE_NAME, __func__);
goto err_class;
}
device_create(class, NULL, devno, NULL, DEVICE_NAME);
printk(KERN_INFO "Farsight FS210 GPIO Driver.\n");
#if 1
#endif
return 0;
err_class:
device_destroy(class, devno);
err_cdev:
cdev_del(&cdev);
err_devno:
unregister_chrdev_region(devno, 1);
return ret;
}
static void __exit gpio_exit(void)
{
cdev_del(&cdev);
unregister_chrdev_region(devno, 1);
device_destroy(class, devno);
}
MODULE_AUTHOR("Lee Sheen <lx.leesheen@gmail.com>");
MODULE_DESCRIPTION("Farsight FS210 gpio driver");
MODULE_LICENSE("GPL");
module_init(gpio_init);
module_exit(gpio_exit);
这是测试程序test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "fs210-gpio.h"
int main()
{
int dev_fd;
unsigned int temp[2];
float tempvalue=0;
dev_fd = open("/dev/fs210_gpio",O_RDWR | O_NONBLOCK);
if (dev_fd < 0)
{
perror("open");
exit(1);
}
while(1)
{
temp[1]= ioctl(dev_fd,GPIO_ON,temp);
/*
temp[1]&=0xffff;
tempvalue=(float)(temp[1])*0.0625;
*/
if(temp[1]&0x8000)
{
temp[1]= ~temp[1]+1;
temp[1]&=0xffff;
tempvalue=(float)(temp[1])*0.0625;
printf("temp[1] = - %d \r\n",temp[1]>>4);
printf("tempvalue= - %f\r\n",tempvalue);
}
else
{
temp[1]&=0xffff;
tempvalue=(float)(temp[1])*0.0625;
printf("temp[1] = %d \r\n",temp[1]>>4);
printf("tempvalue= %f\r\n",tempvalue);
}
sleep(1);
}
return 0;
}