Linux下18b20温度传感器驱动代码及测试实例

时间:2022-04-14 18:12:00

驱动代码:

#include    <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <plat/gpio-cfg.h> #define DEVICE_NAME "TEM0" #define TEM_SHOW_CODE 0x01 //static struct cdev cdev;
struct class *tem_class;
//static dev_t devno;
//static int major = 243;//可以用int alloc_chrdev_region(dev_t *dev,unsigned baseminor,
//unsigned count,const char *name);向系统动态申请未被占用的设备号。 struct tem_dev_t
{
struct cdev cdev;
}tem_dev; /**
* * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
* * @pin pin The pin number to configure.
* * @to to The configuration for the pin's function.
* *
* * Configure which function is actually connected to the external
* * pin, such as an gpio input, output or some form of special function
* * connected to an internal peripheral block.
* *
* * The @to parameter can be one of the generic S3C_GPIO_INPUT, S3C_GPIO_OUTPUT
* * or S3C_GPIO_SFN() to indicate one of the possible values that the helper
* * will then generate the correct bit mask and shift for the configuration.
* *
* * If a bank of GPIOs all needs to be set to special-function 2, then
* * the following code will work:
* *
* * for (gpio = start; gpio < end; gpio++)
* * s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
* *
* * The @to parameter can also be a specific value already shifted to the
* * correct position in the control register, although these are discouraged
* * in newer kernels and are only being kept for compatibility.
* */
unsigned int gpio=; void tem_reset(void)
{
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN());//当x=0时是输入功能,x=1时是输出功能
gpio_set_value(gpio, );
udelay();//延迟0.1ms
gpio_set_value(gpio, );
udelay();
gpio_set_value(gpio, );
udelay();
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN());
} void tem_wbyte(unsigned char data)
{
int i; s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN());
for (i = ; i < ; ++i)
{
gpio_set_value(gpio, );
udelay(); if (data & 0x01)
{
gpio_set_value(gpio, );
}
udelay();
gpio_set_value(gpio, );
udelay();
data >>= ;
}
gpio_set_value(gpio, );
} unsigned char tem_rbyte(void)
{
int i;
unsigned char ret = ; for (i = ; i < ; ++i)
{
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN());
gpio_set_value(gpio, );
udelay();
gpio_set_value(gpio, ); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN());
ret >>= ;
if (gpio_get_value(gpio))
{
ret |= 0x80;
}
udelay();
}
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN()); return ret;
} static ssize_t tem_read(struct file *filp, char *buf, size_t len, loff_t *offset)
{
unsigned char low, high; tem_reset();
udelay();
tem_wbyte(0xcc);
tem_wbyte(0x44); mdelay();
tem_reset();
udelay();
tem_wbyte(0xcc);
tem_wbyte(0xbe); low = tem_rbyte();
high = tem_rbyte(); *buf = low / + high * ; *(buf + ) = (low & 0x0f) * / + (high & 0x0f) * / % ;
return ;
}
/*******************************************************************
*
*ioctl 还不准确,需要改进
* by mhb
*
**********************************************************************/
int tem_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
printk("in the ioctl!!\n");//debug
switch(cmd)
{
case TEM_SHOW_CODE:
{
int i;
unsigned char fc,sn[],crc;
tem_reset();
udelay();
tem_wbyte(0x33);
fc = tem_rbyte;
for (i = ; i < ; i++)
{
/* code */
sn[i]=tem_rbyte;
}
crc=tem_rbyte;
printk("familycode=%x\n",fc);
printk("serialnumber=%x%x%x%x%x%x\n",sn[],sn[],sn[],sn[],sn[],sn[]);
printk("crc=%x\n",crc);
break;
}
default:
{
return - ENOTTY;
}
}
} static struct file_operations tem_fops =
{
.owner = THIS_MODULE,
.read = tem_read,
.ioctl =tem_ioctl,
}; static int __init tem_init(void)
{
int result;
int major;
int minor; cdev_init(&tem_dev.cdev,&tem_fops);/*init cdev*/
tem_dev.cdev.owner=THIS_MODULE;
// devno = MKDEV(major, 0);
// result = register_chrdev_region(devno, 1, DEVICE_NAME);
result = alloc_chrdev_region(&tem_dev.cdev.dev,,,DEVICE_NAME);
major=MAJOR(tem_dev.cdev.dev);
minor=MINOR(tem_dev.cdev.dev);
if(major)
{
printk("majior=%d\n",major);
printk("minor=%d\n",minor);
}else
printk("can not get device num!!\n"); if (result)
{
printk("register failed\n");
return result;
}
#ifdef CONFIG_OK210_BOARD_V2
gpio=S5PV210_MP04();
#else
gpio=S5PV210_GPH3();
#endif
// cdev_init(&cdev, &tem_fops);
// cdev.owner = THIS_MODULE;
// cdev.ops = &tem_fops;
result = cdev_add(&tem_dev.cdev, tem_dev.cdev.dev, );
if (result)
{
printk("cdev add failed\n");
goto fail1;
} tem_class = class_create(THIS_MODULE, "tmp_class");/*在sys目录下创建tmp_class这个类,/sys/class/~*/
if (IS_ERR(tem_class))
{
printk("class create failed\n");
goto fail2;
} device_create(tem_class, NULL, tem_dev.cdev.dev, DEVICE_NAME, DEVICE_NAME);/*自动创建设备/dev/TEM0*/
return ;
fail2:
cdev_del(&tem_dev.cdev);
fail1:
unregister_chrdev_region(tem_dev.cdev.dev, );
return result;
} static void __exit tem_exit(void)
{
device_destroy(tem_class, tem_dev.cdev.dev);
class_destroy(tem_class);
cdev_del(&tem_dev.cdev);
unregister_chrdev_region(tem_dev.cdev.dev, );
} module_init(tem_init);
module_exit(tem_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("mhb");

测试代码:

#include "stdio.h"
#include "sys/types.h"
#include "sys/ioctl.h"
#include "stdlib.h"
#include "termios.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "sys/time.h"
#define TEM_SHOW 0x01
main()
{
int fd;
#if 1
unsigned char buf[];
#else
unsigned int tmp;
#endif
float result; if ((fd=open("/dev/TEM0",O_RDWR | O_NDELAY | O_NOCTTY)) < )
{
printf("Open Device DS18B20 failed.\r\n");
exit();
}
else
{
printf("Open Device DS18B20 successed.\r\n");
while()
{
// read(fd, buf, sizeof(buf));
// result = tmp * 1000;
// result = *(int *)buf;
read(fd, buf, sizeof(buf));
#if 0
printf("%d\n", buf[]);
printf("%d\n", buf[]);
result = (float)buf[];
result /= ;
result += ((float)buf[] * );
#endif
#if 0
// printf("%f .C\r\n", result);
sleep();
#else
printf("%d.%d C\r\n", buf[], buf[]);
sleep();
ioctl(fd,TEM_SHOW,);
#endif
}
close(fd);
}
}