DS18B20 driver writing--miscellaneous device framework registration

DS18B20 Driver Writing – Miscellaneous Device Framework Registration

  The most popular explanation for a device driver is "to drive a hardware device to act." The driver directly deals with the underlying hardware, according to the specific working mode of the hardware device, reads and writes the registers of the device, completes the polling of the device, interrupt processing, DMA communication, and maps the physical memory to the virtual memory, etc., and finally enables the communication device to send and receive data. , so that the display device can display text and pictures, and the storage device can record files and data.
  The driver program is the connection bridge between the application layer and the hardware layer. The application layer only completes application logic development and interface design, while the driver layer handles hardware configuration and implements relevant interface functions of the application layer.
  Miscellaneous device: A type of character device, the major device number of which is 10.

1. Introduction to DS18B20

  DS18B20 is a digital temperature sensor produced by Dallas Semiconductor Company. It is the first temperature sensor in the world that supports "one-line bus" interface. The measurement temperature range is -55°C ~ +125°C, and the accuracy is ±0.5°C. The resolution is 9~12 bits. Support 3V ~ 5.5V input voltage. Strong anti-interference ability.
  Each DSl820 includes a unique 64-bit long sequence number, which is stored in the ROM (read-only memory) inside the DSl820. The first 8 bits are the product type code (DSl820 code is 10H), the next 48 bits are the unique serial number of each device, and the last 8 bits are the CRC (cyclic redundancy check) code of the previous 56 bits.
insert image description here

pin illustrate
GND land
DQ Digital signal pin
VDD Power pin 3V~5.5V

  DS18B20 responds the temperature value of the device in the form of 9 digits.
  DS18B20 adopts single-bus communication, only need to connect DQ pin with CPU, and share ground with CPU. Each DS18B20 has a unique 64-bit lithography ROM, so multiple DS18B20 modules can be connected to one data line.

  • Single bus protocol features
  • Bus protocol: one data line can mount multiple devices (DS18B20 distinguishes devices through 64-bit lithography ROM);
  • Half-duplex communication: the data line can only send or receive data at the same time;

2. DS18B20 drive timing

2.1 Send reset pulse and detect presence signal

insert image description here
insert image description here
  The DS18B20 initialization process first needs to send a reset pulse: a low-level signal of at least 480us. Next, the bus is released, and DS18B20 starts to return the presence signal: a low level of 60~240us. Finally, the bus is released and the module initialization is completed.

/*发送复位信号,检测存在脉冲*/
static u8 ds18b20_CheckRst(void)
{
    
    
	u8 time=0;
	DS18B20_OUT_MODE();/*输出模式*/
	DS18B20_OUT(0);/*总线拉低*/
	udelay(600);/*至少480us低电平*/
	DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/
	udelay(15);
	DS18B20_INPUT_MODE();/*输入模式*/
	while(DS18B20_IN)
	{
    
    
		time++;
		udelay(1);
		if(time>=100)return 1;/*等待存在脉冲失败*/
	}
	time=0;
	while(!DS18B20_IN)
	{
    
    
		time++;
		udelay(1);
		if(time>=250)return 2;//模块出错
	}
	return 0;	
}

2.2 Write one bit data timing

insert image description here
  To implement writing one byte of data, the first thing to implement is the timing of writing one bit of data. Divided into writing 1 and writing 0. The first is that the bus is pulled low to generate a write gap (at least 1us). Then write 0 or 1 to the data line DQ, the cycle time is 60us, and finally release the bus (the bus is pulled high, at least 1us) , so far, the writing data is completed.

DS18B20_OUT_MODE();/*输出模式*/
DS18B20_OUT(0);//总线拉低,产生写间隙时间
udelay(2);
if(dat&0x01)DS18B20_OUT(1);
else DS18B20_OUT(0);
udelay(60);//写周期时间
DS18B20_OUT(1);//释放总线
udelay(2);
dat>>=1;//继续发送下一位数据

2.3 Read one bit data timing

insert image description here
  To read data, the host first needs to generate a read gap: the bus is pulled low, and the low level signal is at least 1us. Then release the bus, read data within 15us, the cycle time of reading data is 60us, and finally release the bus: the bus is pulled high, at least 1us. At this point, reading one bit of data is completed.

DS18B20_OUT_MODE();/*输出模式*/
DS18B20_OUT(0);//总线拉低,产生读间隙时间
udelay(2);
DS18B20_INPUT_MODE();//配置为输入模式
udelay(12);//等待数据到来
data>>=1;
if(DS18B20_IN)data|=0x80;
udelay(50);//读数据时间
DS18B20_OUT(1);//恢复总线为空闲电平
udelay(2);

3. DS18B20 related commands

  • Jump instruction 0xCC
      This instruction allows the controller to use memory operation commands without providing a 64-bit lithography ROM. It is used when there is only one DS18B20 on the bus. If there are more than one, conflicts will occur.
  • Start a temperature conversion 0x44
      This command completes a temperature conversion. After executing this command, DS18B20 keeps waiting. If the bus is followed by a read gap after sending this command, and DS18B20 is in data conversion, it will output a 0, and if the temperature conversion is completed, it will output 1. If parasitic power is used, the bus must be pulled high after this command is sent and kept for 500ms.
  • Read data once 0xBE
      This command is used to read the content in the scratchpad, which can read 9 bytes of data continuously. If you only want to read temperature data, you only need to read the first two bytes.
    insert image description here
  • Read ROM 0x33
      This command can read the 64-bit photolithography ROM data of DS18B20, this command can only be used when there is one device on the bus.
  • Match ROM 0x55
      This command can be used to match the ROM of DS18B20. Only when it completely matches the 64-bit lithography ROM of DS1820 can it respond to the following memory commands. This command is used when there is more than one device on the bus.
  • Search ROM 0xF0
      When the system starts for the first time, it is impossible to confirm how many devices are on the bus or the lithographic ROM of the device. Searching ROM allows the controller to identify the 64-bit lithographic ROM of all devices on the bus by elimination .

4. DS18B20 collects a temperature step

  Powered by external power supply, and there is only one DS18B20 module on the bus
insert image description here

5. Write DS18B20 driver and register through miscellaneous devices

  • Development Platform

Development platform: Ubuntu18.04
Compiler: arm-linux-gcc
Hardware platform: tiny4412 based on Cortex-A9 4-core 1.5GHZ
development board Kernel: Linux3.5

#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/delay.h>

#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

static unsigned int ds18b20_gpio=EXYNOS4_GPB(4);//GPB_4
#define DS18B20_OUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT)/*输出模式*/
#define DS18B20_INPUT_MODE()  s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_INPUT)/*输入模式*/
#define DS18B20_OUT(x)   gpio_set_value(ds18b20_gpio,(x))
#define DS18B20_IN   		gpio_get_value(ds18b20_gpio)
/*发送复位信号,检测存在脉冲*/
static u8 ds18b20_CheckRst(void)
{
    
    
	u8 time=0;
	DS18B20_OUT_MODE();/*输出模式*/
	DS18B20_OUT(0);/*总线拉低*/
	udelay(600);/*至少480us低电平*/
	DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/
	udelay(15);
	DS18B20_INPUT_MODE();/*输入模式*/
	while(DS18B20_IN)
	{
    
    
		time++;
		udelay(1);
		if(time>=100)return 1;/*等待存在脉冲失败*/
	}
	time=0;
	while(!DS18B20_IN)
	{
    
    
		time++;
		udelay(1);
		if(time>=250)return 2;//模块出错
	}
	return 0;	
}
/*写一个字节函数*/
static void ds18b20_writeDat(u8 dat)
{
    
    
	int i=0;
	DS18B20_OUT_MODE();/*输出模式*/
	for(i=0;i<8;i++)
	{
    
    
		DS18B20_OUT(0);//总线拉低,产生写间隙时间
		udelay(2);
		if(dat&0x01)DS18B20_OUT(1);
		else DS18B20_OUT(0);
		udelay(60);//写周期时间
		DS18B20_OUT(1);//释放总线
		udelay(2);
		dat>>=1;//继续发送下一位数据
	}
}
/*读取1字节数据*/
static u8 ds18b20_readDat(void)
{
    
    
	int i=0;
	u8 data=0;
	for(i=0;i<8;i++)
	{
    
    
		DS18B20_OUT_MODE();/*输出模式*/
		DS18B20_OUT(0);//总线拉低,产生读间隙时间
		udelay(2);
		DS18B20_INPUT_MODE();//配置为输入模式
		udelay(12);//等待数据到来
		data>>=1;
		if(DS18B20_IN)data|=0x80;
		udelay(50);//读数据时间
		DS18B20_OUT(1);//恢复总线为空闲电平
		udelay(2);
	}
	return data;
}

/*获取一次温度数据*/
static u16 ds18b20_GetTemp(void)
{
    
    
	u8 L,H;
	u16 temp;
	if(ds18b20_CheckRst())return 0xffff;
	ds18b20_writeDat(0xcc);
	ds18b20_writeDat(0x44);
	while(ds18b20_readDat()!=0xff);/*等待温度转换完成*/
	if(ds18b20_CheckRst())return 0xffff;
	ds18b20_writeDat(0xcc);
	ds18b20_writeDat(0xbe);/*读取一次温度*/
	L=ds18b20_readDat();
	H=ds18b20_readDat();
	temp=H<<8|L;
	return temp;
}
static int ds18b20_open(struct inode *inode, struct file *file)
{
    
    
	printk("open函数调用成功\n");
	if(ds18b20_CheckRst())
	{
    
    
		printk("DS18B20初始化失败\n");
	}
	return 0;
}
static int ds18b20_release(struct inode *inode, struct file *file)
{
    
    
	printk("release函数调用成功");
	return 0;
}
long ds18b20_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    
    
	int dir=_IOC_DIR(cmd);/*数据读写方向,00无参数,10用户层读,01用户层写,11可读写*/
	int type=_IOC_TYPE(cmd);/*魔术,标志符*/
	int size=_IOC_SIZE(cmd);/*arg的字节数*/
	printk("dir=%d,type=%c,size=%d\n",dir,type,size);
	int ret;
	u16 temp=ds18b20_GetTemp();/*获取一次温度*/
	ret=copy_to_user((void *)arg, &temp,size);
	return 4-ret;
}
static  struct file_operations ds18b20_fops=
{
    
    
	.open			=ds18b20_open,
	.release		=ds18b20_release,
	.unlocked_ioctl	=ds18b20_ioctl
};

/*杂项设备结构体*/
static struct miscdevice ds18b20_drv=
{
    
    
	.minor	=MISC_DYNAMIC_MINOR,/*255,有内核自动分配*/
	.name	="ds18b20",//设备节点名字
	.fops	=&ds18b20_fops,//文件操作集合
};
static int __init wbyq_ds18b20_init(void)
{
    
    
	/*1.GPIO注销*/
	gpio_free(ds18b20_gpio);
	/*2.注册GPIO*/
	gpio_request(ds18b20_gpio,"DS18B20");
	/*配置GPIO模式*/
	s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT);
	gpio_set_value(ds18b20_gpio,1);/*上拉*/
	/*注册杂项设备*/
	misc_register(&ds18b20_drv);
	return 0;
	
}
/*驱动释放*/
static void __exit wbyq_ds18b20_cleanup(void)
{
    
    
    printk("驱动出口,驱动注销成功\n");
	/*注销杂项设备*/
	misc_deregister(&ds18b20_drv);
	/*注销GPIO*/
	gpio_free(ds18b20_gpio);
}
module_init(wbyq_ds18b20_init);//驱动入口函数
module_exit(wbyq_ds18b20_cleanup);//驱动出口函数

MODULE_LICENSE("GPL");//驱动注册协议
MODULE_AUTHOR("it_ashui");
MODULE_DESCRIPTION("Exynos4 ds18b20 Driver");

insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/weixin_44453694/article/details/126770763