您的位置:首页 > 运维架构 > Linux

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

2013-08-25 15:32 501 查看
驱动代码:

#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=0;

void tem_reset(void)
{
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));//当x=0时是输入功能,x=1时是输出功能
gpio_set_value(gpio, 1);
udelay(100);//延迟0.1ms
gpio_set_value(gpio, 0);
udelay(600);
gpio_set_value(gpio, 1);
udelay(100);
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
}

void tem_wbyte(unsigned char data)
{
int i;

s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
for (i = 0; i < 8; ++i)
{
gpio_set_value(gpio, 0);
udelay(1);

if (data & 0x01)
{
gpio_set_value(gpio, 1);
}
udelay(60);
gpio_set_value(gpio, 1);
udelay(15);
data >>= 1;
}
gpio_set_value(gpio, 1);
}

unsigned char tem_rbyte(void)
{
int i;
unsigned char ret = 0;

for (i = 0; i < 8; ++i)
{
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));
gpio_set_value(gpio, 0);
udelay(1);
gpio_set_value(gpio, 1);

s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
ret >>= 1;
if (gpio_get_value(gpio))
{
ret |= 0x80;
}
udelay(60);
}
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(1));

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(420);
tem_wbyte(0xcc);
tem_wbyte(0x44);

mdelay(750);
tem_reset();
udelay(400);
tem_wbyte(0xcc);
tem_wbyte(0xbe);

low = tem_rbyte();
high = tem_rbyte();

*buf = low / 16 + high * 16;

*(buf + 1) = (low & 0x0f) * 10 / 16 + (high & 0x0f) * 100 / 16 % 10;
return 0;
}
/*******************************************************************
*
*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[6],crc;
tem_reset();
udelay(400);
tem_wbyte(0x33);
fc = tem_rbyte;
for (i = 0; i < 5; i++)
{
/* code */
sn[i]=tem_rbyte;
}
crc=tem_rbyte;
printk("familycode=%x\n",fc);
printk("serialnumber=%x%x%x%x%x%x\n",sn[5],sn[4],sn[3],sn[2],sn[1],sn[0]);
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,0,1,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(3);
#else
gpio=S5PV210_GPH3(1);
#endif
//    cdev_init(&cdev, &tem_fops);
//    cdev.owner = THIS_MODULE;
//    cdev.ops = &tem_fops;
result = cdev_add(&tem_dev.cdev, tem_dev.cdev.dev, 1);
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 0;
fail2:
cdev_del(&tem_dev.cdev);
fail1:
unregister_chrdev_region(tem_dev.cdev.dev, 1);
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, 1);
}

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[2];
#else
unsigned int tmp;
#endif
float result;

if ((fd=open("/dev/TEM0",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
{
printf("Open Device DS18B20 failed.\r\n");
exit(1);
}
else
{
printf("Open Device DS18B20 successed.\r\n");
while(1)
{
//            read(fd, buf, sizeof(buf));
//            result = tmp * 1000;
//            result = *(int *)buf;
read(fd, buf, sizeof(buf));
#if 0
printf("%d\n", buf[0]);
printf("%d\n", buf[1]);
result = (float)buf[0];
result /= 16;
result += ((float)buf[1] * 16);
#endif
#if 0
//        printf("%f .C\r\n", result);
sleep(1);
#else
printf("%d.%d C\r\n", buf[0], buf[1]);
sleep(1);
ioctl(fd,TEM_SHOW,0);
#endif
}
close(fd);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: