tq2440连接到温度传感器DS18B20

原文:洛洛晨风

用到的为GPG111即GPIO对应的EINT19,它好像连到的是摄像头管脚的,由于没有CMOS摄像头,故拿来用一下,其他的管脚也是可以的。驱动的加载同以前一样,在内核中添加对应动态模式M等,然后make SUBDIR=driver\char\ modules生成.ko文件,发送到开发板上,加载。说明以下,insmod没问题,就是rmmod执行不了。这个问题现在没有解决,但不影响使用。./测试文件名,就会显示温度。

------已验证,可正常执行及显示。开发板TQ2440

TQ2440内核为2.6.30.4下DS18B20的驱动程序:

###############DS18B20的驱动程序############

 

#include<linux/platform_device.h>

#include <linux/delay.h>

#include <linux/fs.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/uaccess.h>

#include <linux/clk.h>

#include<mach/regs-gpio.h>

#include <mach/io.h>

#include <mach/map.h>

#include<mach/regs-clock.h>

 

#define   DQ         S3C2410_GPG11

#define   CPG_IN      S3C2410_GPG11_INP

#define   CPG_OUT     S3C2410_GPG11_OUTP

 

#define DEVICE_NAME "tq18b20" //自定义驱动称为“tq18b20”。

#define DS18B20_MAJOR 210

static int opencount = 0;

static char data[2];

//ds18b20复位,返回0成功,返回1失败

static unsigned char init_ds18b20(void)

{

unsigned char ret =0;

 

s3c2410_gpio_cfgpin(DQ,CPG_OUT);   // 配置GPG11输出模式

//s3c2410_gpio_pullup(DQ,0);

s3c2410_gpio_setpin(DQ,1); // 向18B20发送一个上升沿,并保持高电平状态约100微秒

udelay(100);

s3c2410_gpio_setpin(DQ,0); // 向18B20发送一个下降沿,并保持低电平状态约500微秒

udelay(500);

 

s3c2410_gpio_setpin(DQ,1); //将18b20总线拉高,以便在15~60us后接收18b20发出的存在脉冲

udelay(50);

 

s3c2410_gpio_cfgpin(DQ,CPG_IN);  //通过再次配置GPG11引脚成输入状态,可以检测到DS18B20是否复位成功

//若存在脉冲是一个60~240us的低电平信号,则通信双方已达成基本的协议

ret =s3c2410_gpio_getpin(DQ);   //接下来是控制器与18b20的数字通信

udelay(200);

return ret;

}

 

//向18b20写一个字节

static void write_onechar(char data)

{

unsigned char i = 0;

s3c2410_gpio_cfgpin(DQ, CPG_OUT); //配置GPG11输出模式

s3c2410_gpio_pullup(DQ, 1);

for(i=0; i<8; i++)

{

s3c2410_gpio_setpin(DQ, 0);   //每一位的发送前至少15us低电平起始位

udelay(15);   

s3c2410_gpio_setpin(DQ,data&0x01); //在采样时间内,如果控制器将总线拉高,表示写1,拉低表示写0

udelay(60);

s3c2410_gpio_setpin(DQ, 1);

udelay(2);

data >>=1;

}

}

 

//从18b20读一个字节

static unsigned char read_onechar(void)

{

unsigned char i;

unsigned chardata=0;

for(i=0;i<8; i++)

 {

 

s3c2410_gpio_cfgpin(DQ,CPG_OUT); // 配置GPG11输出模式

  s3c2410_gpio_setpin(DQ, 0);  //读时间间隙时也是必须先有主机产生至少1us的低电平,表示读时间的起始

  udelay(1);

  data >>= 1;

  s3c2410_gpio_setpin(DQ, 1);

  s3c2410_gpio_cfgpin(DQ, CPG_IN);  

  if(s3c2410_gpio_getpin(DQ))   // 若总线在我们设它为低电平之后若1微秒之内变为高

  // 则认为从DS18B20处收到一个“1”信号

data |= 0x80;

  udelay(50);

 }

return data;

}

 

//18b20的读函数,读出温度

static ssize_t read_ds18b20(struct file *filp, char*buffer,

      size_t count, loff_t *ppos)

{

if(init_ds18b20())//初始化成功,init_ds18b20()返回值为0,否则为1

 return-1;

 

write_onechar(0x0cc);//跳过读序列号的操作

write_onechar(0x44);//启动温度转换

udelay(5);

while(init_ds18b20());

udelay(200);

write_onechar(0x0cc);//跳过读序列号的操作

write_onechar(0x0be);//读取温度寄存器

 

data[0] = read_onechar();//读低8位

data[1] = read_onechar();//读高8位

// copy_to_user(buffer,&data, 2);

buffer[0]=data[0];

buffer[1]=data[1];

return 1;

}

 

//对应应用程序的open函数

static int open_ds18b20(struct inode *node, struct file*file)

{

unsigned char flag;

 

if(opencount == 1)

 return-EBUSY;

 

flag =init_ds18b20();

 

if(flag&0x01)

 {

  printk("uable to open device!\n");

  return -1;

 }

else

{

  opencount++;

  printk("device opened!\n");

  return 0;

}

}

 

static int release_ds18b20(struct inode *node, struct file*file)

{

opencount--;

printk("devicereleased!\n");

return 0;

}

 

static struct file_operations ds18b20_fops = {

.owner = THIS_MODULE,

.read =read_ds18b20,

.release =release_ds18b20,

.open =open_ds18b20,

};

 

static char __initdata banner[] = "TQ2440/SKY2440ds18b20\n";//打印信息

static struct class *ds18b20_class;

static int __init ds18b20_init(void)

{

int ret;

printk(banner);

ret = register_chrdev(DS18B20_MAJOR,DEVICE_NAME, &ds18b20_fops);

if (ret < 0)

{

printk(DEVICE_NAME " can'tregister major number\n");

return ret;

}//错误处理

 

ds18b20_class = class_create(THIS_MODULE,DEVICE_NAME);

if(IS_ERR(ds18b20_class))

{

printk("Err: failed intope-leds class. \n");

return -1;

}

device_create(ds18b20_class, NULL,MKDEV(DS18B20_MAJOR, 0), NULL,DEVICE_NAME);//创建一个设备节点,节点名为DEVICE_NAME

printk(DEVICE_NAME "initialized\n");//打印信息,内核中的打印用printk函数

return 0;

}

static void __exit ds18b20_exit(void)

{

printk(DEVICE_NAME "exit\n");//打印信息,内核中的打印用printk函数

unregister_chrdev(DS18B20_MAJOR,DEVICE_NAME);//取消注册设备

device_destroy(ds18b20_class,MKDEV(DS18B20_MAJOR, 0)); //删掉设备节点

class_destroy(ds18b20_class);   //注销类

}

module_init(ds18b20_init);

module_exit(ds18b20_exit);

MODULE_LICENSE("GPL");//遵循的协议

 

############以上DS18B20的驱动程序#######################

 

 

 

 

 

 

###############以下为TQ2440下DS18B20的测试程序###########################

 

#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"

 

main()

{

 intfd;

unsigned char buf[2];

 floatresult;

 

 if((fd=open("/dev/tq18b20",O_RDWR | O_NDELAY | O_NOCTTY))< 0)

 {

   printf("Open Device DS18B20failed.\r\n");

   exit(1);

 }

else

 {

   printf("Open Device DS18B20successed.\r\n");

   while(1)

   {

      read(fd, buf, 1);

      result = (float)buf[0];

      result /= 16;

      result += ((float)buf[1] * 16);

 if(result<100)

 {

      printf("%f .C\r\n", result);

      sleep(1);

      }

   }

   close(fd);

 }

}

 

###########################################################################

http://blog.sina.com.cn/s/blog_67d069a90100p7q6.html
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值