设为首页 加入收藏

TOP

基于S3C2440嵌入式Linux系统下DS18B20驱动源码(一)
2014-11-24 02:04:20 来源: 作者: 【 】 浏览:2
Tags:基于 S3C2440 嵌入式 Linux 系统 DS18B20 驱动 源码

用Linux驱动编程的方法写一个DS18B20的温度传感器驱动,从底层采集温度信息。以下乃本人所写的驱动和测试的源码,嵌入式Linux内核版本为2.6.29,硬件平台是友善之臂的QQ2440,DS18B20引脚连接S3C2440的GPIOB1,程序难免存在一定的漏洞,希望大家指出。


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


typedef unsigned char BYTE;


#define DS18B20_PIN S3C2410_GPB1


#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP


#define DS18B20_PIN_INP S3C2410_GPB1_INP


#define HIGH 1


#define LOW 0


#define DEV_NAME "DS18B20"


#define DEV_MAJOR 232


static BYTE data[2];


// DS18B20复位函数


BYTE DS18b20_reset (void)


{


// 配置GPIOB0输出模式


s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);


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


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


udelay(100);


// 向18B20发送一个下降沿,并保持低电平状态约600微秒


s3c2410_gpio_setpin(DS18B20_PIN, LOW);


udelay(600);


// 向18B20发送一个上升沿,此时可释放DS18B20总线


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


udelay(100);


// 以上动作是给DS18B20一个复位脉冲


// 通过再次配置GPIOB1引脚成输入状态,可以检测到DS18B20是否复位成功


s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);


// 若总线在释放后总线状态为高电平,则复位失败


if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.\r\n"); return 1;}


return 0;


}


void DS18b20_write_byte (BYTE byte)


{


BYTE i;


// 配置GPIOB1为输出模式


s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);


// 写“1”时隙:


// 保持总线在低电平1微秒到15微秒之间


// 然后再保持总线在高电平15微秒到60微秒之间


// 理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平


//


// 写“0”时隙:


// 保持总线在低电平15微秒到60微秒之间


// 然后再保持总线在高电平1微秒到15微秒之间


// 理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平


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


{


s3c2410_gpio_setpin(DS18B20_PIN, LOW); udelay(1);


if(byte & HIGH)


{


// 若byte变量的D0位是1,则需向总线上写“1”


// 根据写“1”时隙规则,电平在此处翻转为高


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


}


else


{


// 若byte变量的D0位是0,则需向总线上写“0”


// 根据写“0”时隙规则,电平在保持为低


// s3c2410_gpio_setpin(DS18B20_PIN, LOW);


}


// 电平状态保持60微秒


udelay(60);


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


udelay(15);


byte >>= 1;


}


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


}


BYTE DS18b20_read_byte (void)


{


BYTE i = 0;


BYTE byte = 0;


// 读“1”时隙:


// 若总线状态保持在低电平状态1微秒到15微秒之间


// 然后跳变到高电平状态且保持在15微秒到60微秒之间


// 就认为从DS18B20读到一个“1”信号


// 理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平


//


// 读“0”时隙:


// 若总线状态保持在低电平状态15微秒到30微秒之间


// 然后跳变到高电平状态且保持在15微秒到60微秒之间


// 就认为从DS18B20读到一个“0”信号


// 理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平


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


{


s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);


s3c2410_gpio_setpin(DS18B20_PIN, LOW);


udelay(1);


byte >>= 1;


s3c2410_gpio_setpin(DS18B20_PIN, HIGH);


s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);


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


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


// 因此把byte的D7为置“1”


if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80;


udelay(60);


}


return byte;


}


void DS18b20_proc(void)


{


while(DS18b20_reset());


udelay(120);


DS18b20_write_byte(0xcc);


DS18b20_write_byte(0x44);


udelay(5);


while(DS18b20_reset());


udelay(200);


DS18b20_write_byte(0xcc);


DS18b20_write_byte(0xbe);


data[0] = DS18b20_read_byte();


data[1] = DS18b20_read_byte();


}


static ssize_t s3c2440_18b20_read(struct file *filp, char *buf, size_t len, loff_t *off)


{


DS18b20_proc();


buf[0] = data[0];


buf[1] = data[1];


return 1;


}


static struct file_operations s3c2440_18b20_fops =


{


.owner = THIS_MODULE,


.read = s3c2440_18b20_read,


};


static int __init s3c2440_18b20_init(void)


{


if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_fops) < 0)


{


printk(DEV_NAME ": Register major failed.\r\n");


return -1;


}


devfs_mk_cdev(MKDEV(DEV_MAJOR, 0),S_IFCH

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇gcc-3.4.6在Ubuntu 9.04下的编译.. 下一篇Linux下C语言程序学习

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: