|
程序网上参考的,也看了datasheet没有问题啊。
可是到这里
while(Read_DS()==0)
{
printk(DEVICE_NAME " Convert....\n");
msdelay(50);
err++;
if(err==10)
{
printk(DEVICE_NAME " Convert fail\n");
return -1;
}
}
就过不去了。
老是转换失败。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "DS18B20"
#define DS18B20_MAJOR 250 //这里要确定自己的这个主设备号 mknod /dev/DS18B20 c 250 0
#define DS_PIN S3C2410_GPB1 //这可以找一个自己方便的管脚,只要是引出的GPIO都可以
#define OUT S3C2410_GPB1_OUTP //设置成输出端口
#define IN S3C2410_GPB1_INP //设置成输入端口
#define DIS_UP 1
#define EN_UP 0
#define Search 0x00F0 //好型没怎么用啊!!
#define Read_ROM 0x0033 //just for one
#define Skip_ROM 0x00CC //跳rom的时序
#define Convert 0x0044 //ds18b20的固定时序,管脚识别到该信号开始对测到的温度进行转换
#define Write 0x004E //TH---TL---Config
#define Read 0x00BE //ds18b20的固定时序,管脚识别到该信号时开始从外界获取温度
#define bit_9 0x001F
#define bit_10 0x003F
#define bit_11 0x005F
#define bit_12 0x007F
#define uint16 unsigned int
//unsigned int ROM_DATA[8];
void usdelay(unsigned int i) //延时 i us 对于不同系统可能会有所差别,请适当修改
{
unsigned int j;
for(i=i;i>0;i--)
for(j=90;j>0;j--);
}
void msdelay(unsigned int i) //延时 i us
{
for(i=i;i>0;i--)
usdelay(1000);
}
void SetL(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,0);
}
void SetH(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,1);
}
unsigned int Read_DS(void)
{
unsigned int i;
s3c2410_gpio_cfgpin(DS_PIN,IN);
s3c2410_gpio_pullup(DS_PIN,EN_UP);
__asm("nop");
__asm("nop");
__asm("nop");
i=s3c2410_gpio_getpin(DS_PIN);
if(i!=0)
i=1;
return i;
}
unsigned int ds_start(void) //初始化ds18b20
{
unsigned int flag=1;
int err=0;
/*
During the initialization sequence the bus master transmits (TX) the reset pulse by pulling the 1-Wire bus low for a minimum of 480us.
The bus master then releases the bus and goes into receive mode (RX).
When the bus is released, the 5k pullup resistor pulls the 1-Wire bus high.
When the DS18B20 detects this rising edge, it waits 15us to 60us and then transmits a presence pulse by pulling the 1-Wire bus low for 60us to 240us.
*/
SetH();
usdelay(2);
SetL();
usdelay(600); //560延时要大于480u
SetH();
usdelay(1); //稍作延时
while(Read_DS()!=0) //ds18B20初始化成功会返回一个低电平,此时跳出循环,执行下面的操作
{
printk(DEVICE_NAME " Wait....\n");
usdelay(5);
err++; //扫描最多次数.
if(err==20)
{
printk(DEVICE_NAME " Start fail\n");
return -1;
}
}
printk(DEVICE_NAME " Start sucess\n");
flag=0;
SetH(); //初始化成功后赋为高电平准备从外界读入温度
usdelay(400);
return flag;
}
void ds_send(unsigned int uidata) //发送一个字节数据
{
unsigned int i;
printk("The send data is %d\n",uidata);
for(i=0;i<8;i++)
{
/*
Both types of write time slots are initiated by the master pulling the 1-Wire bus low.
To generate a Write 1 time slot, after pulling the 1-Wire bus low,
the bus master must release the 1-Wire bus within 15us. When the bus is released, the 5k pullup resistor will pull the bus high.
To generate a Write 0 time slot, after pulling the 1-Wire bus low,
the bus master must continue to hold the bus low for the duration of the time slot (at least 60us).
*/
SetL();
usdelay(3);
if((uidata&1)!=0) //写1
{
SetH();
usdelay(80); //保持高电平60us
}
else
{
usdelay(80); //写低电平直接保持
SetH();
}
uidata>>=1;
}
}
unsigned int ds_read(void) //接收一个字节数据
{
unsigned int uidata=0;
unsigned int i;
for(i=0;i<8;i++)
{
SetL();
/*
A read time slot is initiated by the master device pulling the 1-Wire bus low for a minimum of 1us and then releasing the bus
*/
usdelay(2); //2 3 保持至少1us
// s3c2410_gpio_setpin(DS_PIN,1); //放1
// s3c2410_gpio_cfgpin(DS_PIN,IN); //设置为输入
SetH();
/*
Output data from the DS18B20 is valid for 15us after the falling edge that initiated the read time slot.
*/
usdelay(7); //1 2 3 4 5(e)
if(Read_DS()==1)
uidata+=0x0100;
uidata>>=1;
/*
All read time slots must be a minimum of 60us in duration with a minimum of a 1us recovery time between slots.
*/
usdelay(65); //延时60us,满足读时隙的时间长度要求
SetH(); //释放总线
}
printk("--- The recieve data is %d\n",uidata);
return uidata;
}
void ds_init(unsigned int TH,unsigned int TL,unsigned int bit_nmb)
{
SetH();
usdelay(80);
if(ds_start()==0) //初始化成功
{
ds_send(Skip_ROM); //复位
ds_send(Write); //跳过ROM匹配,报警设定
ds_send(TH); //TH
ds_send(TL); //TL
ds_send(bit_nmb); //转换位数
}
}
unsigned int read_tem(void)
{
unsigned int th,tl;
int err=0;
ds_init(100,0,bit_12);
th=tl=0;
if(ds_start() != 0)
{
return -1;
}
ds_send(Skip_ROM);
ds_send(Convert);
msdelay(50);
while(Read_DS()==0)
{
printk(DEVICE_NAME " Convert....\n");
msdelay(50);
err++;
if(err==10)
{
printk(DEVICE_NAME " Convert fail\n");
return -1;
}
}
if(ds_start() != 0)
{
return -1;
}
ds_send(Skip_ROM);
ds_send(Read);
tl=ds_read();
th=ds_read();
th<<=8;
tl|=th;
printk("the th data is %d\n",th);
printk("the tl data is %d\n",tl);
printk("read_tmp success\n");
return tl;
}
static int ds18b20_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,unsigned long arg)
{
return 0;
}
static ssize_t ds18b20_read(struct file *pFile, uint16 __user *pData, size_t count, loff_t *off )
{
uint16 tmp,ret;
tmp =read_tem();
ret=copy_to_user(pData, &tmp, sizeof(tmp)); //将读取得的DS18B20数值复制到用户区
if(ret>0)
{
printk("copy data failed\n");
return -1;
}
return 0;
}
static struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.ioctl = ds18b20_ioctl,
.read = ds18b20_read,
};
static int __init ds18b20_init(void)
{
int ret;
ret = register_chrdev(DS18B20_MAJOR, DEVICE_NAME, &ds18b20_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
s3c2410_gpio_cfgpin(DS_PIN, OUT);
s3c2410_gpio_setpin(DS_PIN, 1);
printk(DEVICE_NAME " initialized\n");
printk("<0>""initialized\n");
return 0;
}
static void __exit ds18b20_exit(void)
{
unregister_chrdev(DS18B20_MAJOR, DEVICE_NAME);
printk(DEVICE_NAME " rmmodule\n");
}
module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_AUTHOR("benjamin_xc@163.com"); // 驱动程序的作者
MODULE_DESCRIPTION("DS18B20 Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|