|
我在S3C2440平台上的Linux系统(2.6内核)下做了一个温度传感器DS18B20的驱动,但是复位不成功,我自己看了好多遍时序图,就是不能找到出问题的地方
请大家帮我看看,到底是什么问题
/*
*文件名字:qq2440_ds18b20.c
*功能描述:数字传感器ds18b20在linux下的驱动程序
*时间:2010-3-5
*版本:v1.0
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/devfs_fs_kernel.h>
#define DEV_NAME "DS18B20"
#define DEV_MAJOR 236
#define DS18B20_PIN S3C2410_GPB1
#define DS18B20_PIN_INP S3C2410_GPB1_INP
#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP
#define SKIP_ROM 0xCC
#define READ_ROM 0X33
#define CONVERT_T 0X44
#define READ_SCRATCHPAD 0XBE
#define HIGH 1
#define LOW 0
#define _DS18B20_DEBUG_
typedef unsigned char u_int8; /*一个字节*/
typedef unsigned int u_int32; /*4个字节*/
typedef unsigned short int u_int16; /*2个字节*/
typedef int int32; /*4个字节*/
typedef char int8; /*1个字节*/
u_int8 data[2];
/*DS18B20复位函数*/
/*复位成功\返回1,否则返回0*/
int32 ds18b20_reset(void)
{
u_int8 i = 0;
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(100);
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
/*delay time 480us~960us*/
udelay(500);
/*向DS18B20发送一个上升沿,释放总线*/
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
/*wait time 15~60us*/
// udelay(80);
udelay(20);
// s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
/*如果复位成功,将产生60~240us的低电平*/
while (s3c2410_gpio_getpin(DS18B20_PIN)) {
if(++i > 30) {
printk("DS18B20 reset failed.\r\n");
return 0;
}
}
#ifdef _DS18B20_DEBUG_
printk("DS18B20 reset success!\n");
#endif
/*DS18B20发送存在脉冲60~240us*/
// udelay(240);
udelay(100);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
return 1;
}
/*S3C2440 send data to DS18B20*/
/*写一个字节*/
void ds18b20_write_byte(u_int8 data)
{
u_int8 i;
/*
*各个写周期之间必须有1us的恢复时间
*每个周期保持60us
*
*写1时:
*保持总线低电平1us~15us之间
*然后保持总线在高电平至少在15us~60us之间
*
*写0时:
*保持总线低电平至少60us
*然后保持总线在高电平至少1us
*/
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(1);
for (i = 0; i < 8; i++) {
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
/*数据先写低位,再写高位*/
if (data & (1 << i)) {
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
// udelay(16); //15+1
}
else {
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
// udelaydd(2); //1+1
}
udelay(60);
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
udelay(1);
/*数据先写低位,再写高位*/
}
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
}
/*S3C2440 recevie data from DB18B20*/
/*读一个字节*/
int32 ds18b20_read_byte(void)
{
u_int8 i = 0;
u_int8 rbyte = 0;
/*
*总线从高电平拉低后,保持至少1us
// *总线在低电平时保持1us~15us
*然后跳到高电平状且保持15us~60us之间
*若总线在我们设它为高电平后在1s内变为低电平,认为读到了0信号
*如果总线不变则认为读到了1信号
*/
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
for (i = 0; i < 8; i++) {
s3c2410_gpio_setpin(DS18B20_PIN, LOW);
udelay(1);
s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// s3c2410_gpio_setpin(DS18B20_PIN, LOW);
/*DS18B20从读时间片产生后的15us输出的数据有效*/
udelay(4);
// udelay(10);
if (s3c2410_gpio_getpin(DS18B20_PIN))
rbyte |= (1 << i);
else
rbyte &= ~(1 << i);
/*等待读一个读时间周期完*/
udelay(60);
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
}
return rbyte;
}
/*温度读取过程*/
int32 ds18b20_proc(void)
{
u_int8 i = 0;
/*
union
{
u_int8 byte[2];
u_int16 word;
}temp;
*/
data[0] = 0;
data[1] = 0;
while (!ds18b20_reset())
{
if (++i > 5) {
#ifdef _DS18B20_DEBUG_
printk("ds18b20_proc error!\n");
#endif
return 0;
}
}
udelay(120);
/*跳过读时序操作*/
ds18b20_write_byte(SKIP_ROM);
/*启动温度测量*/
ds18b20_write_byte(CONVERT_T);
udelay(5);
// s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
// while (!s3c2410_gpio_getpin(DS18B20_PIN));
// s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
while (!ds18b20_reset())
{
if (++i > 5) {
#ifdef _DS18B20_DEBUG_
printk("ds18b20_proc error!\n");
#endif
return 0;
}
}
udelay(200);
ds18b20_write_byte(SKIP_ROM);
/*读取温度寄存器*/
ds18b20_write_byte(READ_SCRATCHPAD);
printk(KERN_INFO"data[0] = %d\n", data[0]);
/*读取低字节*/
data[0] = ds18b20_read_byte();
#ifdef _DS18B20_DEBUG_
// printk(KERN_INFO"temp.data[0] = %d\n", temp.data[0]);
#endif
/*读取高字节*/
data[1] = ds18b20_read_byte();
#ifdef _DS18B20_DEBUG_
// printk(KERN_INFO"temp.data[1] = %d\n", temp.data[1]);
#endif
#ifdef _DS18B20_DEBUG_
// temp.word >>= 4;
// printk(KERN_INFO"temperture.word = %d\n", temp.word);
// printk(KERN_INFO"temp.data[0] = %d\n", temp.data[0]);
// printk(KERN_INFO"temp.data[1] = %d\n", temp.data[0]);
#endif
return 1;
}
/*
static int s3c2440_ds18b20_open(struct inode *inode, struct file *file)
{
s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
temp.word = 0;
// return 1;
}
*/
static ssize_t s3c2440_ds18b20_read(struct file *file, 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_ds18b20_fops = {
.owner = THIS_MODULE,
.read = s3c2440_ds18b20_read,
};
static int __init s3c2440_ds18b20_init(void)
{
/*注册设备号,指定驱动入口指针*/
if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_ds18b20_fops) < 0)
{
printk(DEV_NAME":Register major failed.\r\n");
return -1;
}
devfs_mk_cdev(MKDEV(DEV_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, DEV_NAME);
#ifdef _DS18B20_DEBUG_
printk("DS18B20 init succed!\r\n");
#endif
return 0;
}
static void __exit s3c2440_ds18b20_exit(void)
{
devfs_remove(DEV_NAME);
unregister_chrdev(DEV_MAJOR, DEV_NAME);
}
module_init(s3c2440_ds18b20_init);
module_exit(s3c2440_ds18b20_exit); |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|