驱动源码 #include #include #include #include #include #include #include #include #include #include
#include #include #include #include #include #include
/* 引脚相关定义 */
#define DQ S3C2410_GPF(0)
#define DQ_OUTP
S3C2410_GPIO_OUTPUT
#define DQ_INP S3C2410_GPIO_INPUT
/* 设置DQ引脚为输出 */
#define DQ_OUT s3c2410_gpio_cfgpin(DQ,DQ_OUTP)
/*
设置DQ引脚为输入 */
#define DQ_IN s3c2410_gpio_cfgpin(DQ,DQ_INP)
/* 打开上拉电阻
*/
#define DQ_UP s3c2410_gpio_pullup(DQ,1)
/* 读取DQ状态 */
#define DQ_STA
s3c2410_gpio_getpin(DQ)
/* 拉低DQ */
#define DQ_L
s3c2410_gpio_setpin(DQ,0)
/* 拉高DQ */
#define DQ_H
s3c2410_gpio_setpin(DQ,1)
/* 设备名称 */
#define DEV_NEME “ds18b20”
struct ds18b20_dev{
dev_t devno; //设备号
int major; //主设备号
char *data;
//缓冲区
struct cdev cdev; //内嵌字符设备结构
};
struct ds18b20_dev *ds18b20_device;
/* 初始化DQ18B20,返回0表示初始化成功1表示失败 */
unsigned int init_ds18b20(void)
{
unsigned int dat = 0;
DQ_OUT;
DQ_H; //复位DQ
udelay(10);
DQ_L; //拉低DQ,发出reset脉冲
udelay(600);
DQ_H;
udelay(65);
DQ_IN; //设置DQ为输入,准备读取presence脉冲
dat = DQ_STA; //读取DQ状态,dat=0表示初始化成功,dat=1
表示失败
udelay(50);
DQ_OUT;
DQ_H; //复位DQ
udelay(50);
return dat;
}
/* Write a char */
void write_char(unsigned char dat)
{ unsigned int i
= 0;
DQ_OUT;
for(i=8;i>0;i–){
DQ_L; //拉低DQ,开始写时序
udelay(10);
if(dat&0x01)
DQ_H; //拉高DQ,写1
else
DQ_L;
//拉低DQ,写0
udelay(60);
DQ_H; //复位DQ
udelay(10);
dat
>>=1;
}
}
/* Read a char */
unsigned char read_char(void)
{ unsigned int i=
0;
unsigned char dat =
0;
for(i=8;i>0;i–){
DQ_OUT;
DQ_L;
udelay(2);
dat >>=1;
DQ_H;
udelay(2);
DQ_IN;
udelay(10);
if(DQ_STA)
dat
|=0x80;
udelay(60);
}
return dat;
}
/* Read temperature */
int read_temperature(void)
{ unsigned int msb
=0;
unsigned int lsb =0;
if(init_ds18b20()){
printk(KERN_WARNING “DS18B20:init_ds18b20
failed1”);
return -1;
}
write_char(0xCC);
//跳过读取ROM
write_char(0x44); //开始温度转换
/* 此处必须有一个较长的延时,等待温度转换完成
* 不然可能读出默认值1360 */
msleep_interruptible(900);
//此处延时较长,应该改用非忙等待。 感谢aimybee提醒~
if(init_ds18b20()){
printk(KERN_WARNING
“DS18B20:init_ds18b20 failed2”);
return -1;
}
write_char(0xCC);
//跳过读取ROM
write_char(0xBE); //读取寄存器
lsb = read_char();
//前两个寄存器的值分别为温度的低位和高位
msb = read_char();
msb <<=8;
return msb+lsb;
}
int ds18b20_open(struct inode *inode,struct file *filp)
{ DQ_UP;
//打开上拉电阻
DQ_OUT;
return 0;
}
ssize_t ds18b20_read(struct file *filp,char __user *buf ,size_t count ,
loff_t *f_pos)
{ int temperature;
temperature =
read_temperature();
sprintf(ds18b20_device->data,”%dn”,temperature);
if(temperature < 0){
printk(KERN_WARNING “DS18B20:Read temperature
failed!”);
return
-EFAULT;
}
if(copy_to_user(buf,ds18b20_device->data,sizeof(ds18b20_device->data))){
return
-EFAULT;
}
return sizeof(ds18b20_device->data);
}
struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.read =
ds18b20_read,
.open = ds18b20_open,
};
int __init init_module(void)
{ int result,err;
/* 初始化ds18b20_device 结构体
*/
ds18b20_device = kmalloc(sizeof(struct
ds18b20_dev),GFP_KERNEL);
if(!ds18b20_device){
result = -ENOMEM;
goto
fail_malloc_device;
}
memset(ds18b20_device,0,sizeof(struct
ds18b20_dev));
cdev_init(&ds18b20_device->cdev,&ds18b20_fops);
ds18b20_device->cdev.owner
= THIS_MODULE;
/* 分配设备号 */
result =
alloc_chrdev_region(&ds18b20_device->devno,0,1,DEV_NEME);
ds18b20_device->major
= MAJOR(ds18b20_device->devno);
if(result <0 ){
printk(KERN_WARNING
“DS18b20:cat’t get major %d”,ds18b20_device->major);
return
result;
}
printk(KERN_INFO “DS18b20:major = %d
“,ds18b20_device->major);
/* 分配缓冲区 */
ds18b20_device->data =
kmalloc(20,GFP_KERNEL);
if(!ds18b20_device->data){
result =
-ENOMEM;
goto
fail_malloc_data;
}
memset(ds18b20_device->data,0,20);
err =
cdev_add(&ds18b20_device->cdev,ds18b20_device->devno,1);
if(err)
printk(KERN_WARNING
“DS18b20:Error %d adding ds18b20”,err);
printk(KERN_INFO “DS18b20:init_module”);
return result;
fail_malloc_data:
kfree(ds18b20_device->data);
fail_malloc_device:
unregister_chrdev_region(ds18b20_device->devno,1);
kfree(ds18b20_device);
return
result;
}
void __exit cleanup_module(void)
{
unregister_chrdev_region(ds18b20_device->devno,1);
kfree(ds18b20_device->data);
kfree(ds18b20_device);
printk(KERN_INFO
“DS18b20:cleanup_module”);
}
module_init(init_module);
module_exit(cleanup_module);
MODULE_AUTHOR(“Issac”);
MODULE_LICENSE(“GPL”);