S3C2440温度传感器DS18B20驱动开发及应用测试

由于需要采集环境温度,参照了网上大神的例子,仿照写了一个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");

DS18B20操作

初始化操作
	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;
}

测试结果如图
S3C2440温度传感器DS18B20驱动开发及应用测试_第1张图片

你可能感兴趣的:(S3C2440温度传感器DS18B20驱动开发及应用测试)