21,619
社区成员
发帖
与我相关
我的任务
分享
驱动代码
/*
* Temperature sensor driver for zc6410
*
register list:
* DQ:EINT8(GPN8)
* GPNCON:0x7F008830
* GPNDAT:0x7F008834
* GPNPUD:0x7F008838
*
* register contorl:
* GPN8[17:16] 00=input 01=output 10=Ext.interrupt[8] 11=reserved
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
//#include <regs-gpio.h>
//#include <mach/hardware.h>
#define DEBUG_18B20 0
#define DEVICE_NAME "ds18b20"
#define DSDATA 0x7F008830
#define DATAOUTP 1
#define DATAINP 0
#define DS18B20_MAGIC 'k'
#define DS18B20_RESET _IO(DS18B20_MAGIC, 0)
static void *pVmem = NULL;
#define s3c6410_gpio_cfgpin(pin, state) \
(state?({unsigned int vmem; vmem = ioread32(pin); vmem &= ~(3<<16); vmem |= 1<<16; iowrite32(vmem, pin);}):({unsigned int vmem; vmem = ioread32(pin); vmem &= ~(3<<16); iowrite32(vmem, pin);}))
#define s3c6410_gpio_setpin(pin, state) \
(state?({unsigned int vmem; vmem = ioread32(pin+4); vmem |= (1<<8); iowrite32(vmem, pin+4);}):({unsigned int vmem; vmem = ioread32(pin+4); vmem &= ~(1<<8); iowrite32(vmem, pin+4);}))
#define s3c6410_gpio_getpin(pin) ((ioread32(pin+4)>>8) & 1)
static ssize_t ds18b20_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
volatile int i, size=count;
unsigned char ddat = 0;
if (size > 2)
size = 1;
for (i=0; i<8; i++)
{
ddat >>= 1;
s3c6410_gpio_cfgpin(pVmem, DATAOUTP);
s3c6410_gpio_setpin(pVmem, 0);
udelay(4); //4us
s3c6410_gpio_setpin(pVmem, 1);
s3c6410_gpio_cfgpin(pVmem, DATAINP);
if ( s3c6410_gpio_getpin(pVmem) )
{
ddat |= 0x80;
}
udelay(80); // >70us
s3c6410_gpio_cfgpin(pVmem, DATAOUTP);
s3c6410_gpio_setpin(pVmem, 1);
udelay(3); // >1us
}
s3c6410_gpio_cfgpin(pVmem, DATAINP);
if(copy_to_user(buff, &ddat, size))
{
return -1;
}
return size;
}
static ssize_t ds18b20_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{
volatile int i, size=count;
char ddat=0;
if (size > 2)
size = 1;
if (copy_from_user(&ddat, buff, size))
{
printk("write data error\n");
return -1;
}
s3c6410_gpio_cfgpin(pVmem, DATAOUTP);
for (i=0; i<8; i++)
{
s3c6410_gpio_setpin(pVmem, 0);
udelay(5); //5us
if (ddat & 0x01)
{
s3c6410_gpio_setpin(pVmem, 1);
}
udelay(80); // >70us
s3c6410_gpio_setpin(pVmem, 1);
udelay(3); // >1us
ddat >>= 1;
}
s3c6410_gpio_cfgpin(pVmem, DATAINP);
return size;
}
static int ds18b20_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
switch(cmd)
{
//case DS18B20_RESET: // reset
case 0: // reset
s3c6410_gpio_cfgpin(pVmem, DATAOUTP);
s3c6410_gpio_setpin(pVmem, 1);
udelay(27);
s3c6410_gpio_setpin(pVmem, 0);
udelay(500); // 500us
s3c6410_gpio_setpin(pVmem, 1);
udelay(27);
s3c6410_gpio_cfgpin(pVmem, DATAINP);
udelay(60);
ret = s3c6410_gpio_getpin(pVmem);
msleep(3);
default:
return -EINVAL;
}
return ret;
}
static int ds18b20_open(struct inode *inode, struct file *file)
{
/* GPN8[17:16] = 00 */
s3c6410_gpio_cfgpin(pVmem, DATAINP);
#if DEBUG_18B20
printk("context of 0x%x is 0x%x\n", DSDATA, ioread32(pVmem));
#endif
return 0;
}
static int ds18b20_release(struct inode *inode, struct file *file)
{
return 0;
}
static struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.open = ds18b20_open,
.release = ds18b20_release,
.unlocked_ioctl = ds18b20_ioctl,
.read = ds18b20_read,
.write = ds18b20_write,
//.compat_ioctl = ds18b20_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &ds18b20_fops,
};
// register ds18b20
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc);
if(!request_mem_region(DSDATA, 0x8, DEVICE_NAME))
goto error;
pVmem = ioremap(DSDATA, 0x8);
printk(DEVICE_NAME"\tinitialized\n");
return ret;
error:
misc_deregister(&misc);
return -EFAULT; /* bad address */
}
// unregister ds18b20
static void __exit dev_exit(void)
{
iounmap(pVmem);
release_mem_region(DSDATA, 0x8);
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("modified by __eabi");
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <error.h>
#include <time.h>
#include <fcntl.h>
#define DS18B20_MAGIC 'k'
#define DS18B20_RESET _IO(DS18B20_MAGIC, 0)
static int fd=0;
static unsigned char a=0;
static unsigned char b=0;
/*****读取温度*****/
static unsigned int ReadTemperature(void)
{
unsigned int t=0;
ioctl(fd, DS18B20_RESET, 0); //初始化
a = 0xcc;
write(fd, &a, 1); //跳过读序号列号的操作
a = 0x44;
write(fd, &a, 1); //启动温度转换
sleep(1);
ioctl(fd, DS18B20_RESET, 0); //初始化
a = 0xcc;
write(fd, &a, 1); //跳过读序号列号的操作
a = 0xbe;
write(fd, &a, 1); //读取温度寄存器
read(fd, &a, 1); //读低8位
read(fd, &b, 1); //读高8位
t = b;
t <<= 8;
t = t | a;
usleep(5000);
return t;
}
int main(int argc, char **argv)
{
int val;
float fval;
fd = open("/dev/ds18b20", O_RDWR);
if (fd < 0)
{
perror("open device ds18b20!");
return -1;
}
while(1)
{
val = ReadTemperature();
val <<= 16;
val >>= 16; // 扩展符号位
printf("Temperature is ");
if (val < 0)
{
printf("-");
val = -val;
}
fval = val >> 4; // 整数
fval += (val & 0x000F) * 0.0625; // 小数
printf("%f \n",fval);
sleep(1);
}
close(fd);
return 0;
}