由于需要采集环境温度,参照了网上大神的例子,仿照写了一个DS18B20的驱动。本来应该半天完成的,由于各种小失误(Makefile,接线等问题),耗费了三天的时间。相关时序请查看如下链接DS18B20 Datasheet时序完全解读
int major;
static int ds18b20_drv_open(struct inode *inode, struct file *file)
{
}
static ssize_t ds18b20_drv_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
{
}
static struct file_operations ds18b20_drv_fops = {
.owner = THIS_MODULE,
.open = ds18b20_drv_open,
.read = ds18b20_drv_read,
};
static int ds18b20_drv_init(void)
{
major = register_chrdev(0, "ds18b20_drv", &ds18b20_drv_fops); // 0: 系统自动分配主设备号;注册, 告诉内核
ds18b20_class = class_create(THIS_MODULE, "ds18b20drv");
device_create(ds18b20_class, NULL, MKDEV(major, 0), NULL,"ds18b20"); // /dev/ds18b20
return 0;
}
static void ds18b20_drv_exit(void)
{
device_destroy(ds18b20_class, MKDEV(major, 0));
class_destroy(ds18b20_class);
unregister_chrdev(major, "ds18b20_drv"); // 卸载
}
module_init(ds18b20_drv_init);
module_exit(ds18b20_drv_exit);
MODULE_LICENSE("GPL");
初始化操作
static int ds18b20_init(void)
{
int ret;
s3c2410_gpio_cfgpin(DQ, OUTPUT);
s3c2410_gpio_setpin(DQ, 0);
udelay(600);
s3c2410_gpio_cfgpin(DQ, INPUT);
udelay(75);
ret = s3c2410_gpio_getpin(DQ);
udelay(300);
return ret;
}
写操作
static void ds18b20_write_bit(int val)
{
s3c2410_gpio_cfgpin(DQ, OUTPUT);
if (0 == val)
{
s3c2410_gpio_setpin(DQ, 0);
udelay(2);
s3c2410_gpio_setpin(DQ, 0);
udelay(60);
s3c2410_gpio_cfgpin(DQ, INPUT);
udelay(5);
}
else
{
s3c2410_gpio_setpin(DQ, 0);
udelay(2);
s3c2410_gpio_setpin(DQ, 1);
udelay(60);
s3c2410_gpio_cfgpin(DQ, INPUT);
udelay(5);
}
}
static void ds18b20_write_byte(unsigned char data)
{
int i;
for (i = 0; i < 8; i++)
{
ds18b20_write_bit(data & (1 << i));
}
}
读操作
static int ds18b20_read_ram(unsigned char ram[])
{
int i, j;
for (i = 0; i < 9; i++)
{
unsigned char data = 0x00;
for (j = 0; j < 8; j++)
{
s3c2410_gpio_cfgpin(DQ, OUTPUT);
s3c2410_gpio_setpin(DQ, 1);
udelay(1);
s3c2410_gpio_setpin(DQ, 0);
udelay(2);
s3c2410_gpio_setpin(DQ, 1);
s3c2410_gpio_cfgpin(DQ, INPUT);
if(0 != s3c2410_gpio_getpin(DQ))
data |= (1 << j);
udelay(60);
}
ram[i] = data;
}
return 0;
}
int main(int argc, char **argv)
{
int fd;
int i = 0;
int data = 0;
unsigned char result[9];
float temperature = 0;
DEB_PRINTF("will open fd... \n");
if((fd = open("/dev/ds18b20",O_RDWR|O_NONBLOCK)) < 0 )
{
DEB_PRINTF("open device fail.\n");
return -1;
}
else
{
DEB_PRINTF("Open Device Ds18b20 Successful!!\n");
}
while(1)
{
int m,n, ret;
double val[] = {0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64};
double sum = 0;
DEB_PRINTF("\nWill read temperature...\n");
usleep(100);
ret = read(fd, result, sizeof(result));
if(ret != 9)
{
DEB_PRINTF("read wrong\n");
DEB_PRINTF("ret = %d\n", ret);
return -1;
}
else DEB_PRINTF("read success !\n");
/* 转换计算温度 */
/* 先判断精度 */
if (result[4] & (3<<5) == 0) /* 精度: 9bit */
i = 3;
else if (result[4] & (3<<5) == (1<<5)) /* 精度: 10bit */
i = 2;
else if (result[4] & (3<<5) == (2<<5)) /* 精度: 11bit */
i = 1;
else
/* 精度是 12 bit */
i = 0;
for (; i < 8; i++)
{
if (result[0] & (1 << i))
sum += val[i];
}
for (i = 0; i < 3; i++)
{
if (result[1] & (1 << i))
sum += val[i+8];
}
if (result[1] & (1 << 3))
sum = 0 - sum;
m = (int)sum; /* 3.01, m = 3 */
sum = sum - m; /* 小数部分: 0.01 */
n = sum * 10000; /* 10 */
/* 在串口上打印 */
printf("ds18b20 temperature: %d.%04d\n\r", m, n); /* 3.010v */
fflush(stdout);
sleep(1);
}
close(fd);
return 0;
}