开发板是s5p6818的,编写arm-liunx的驱动代码,但是运行以后无法读取数据
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h> /*杂项字符设备头文件*/
#include <linux/fs.h> /*文件操作集合*/
#include <linux/delay.h> /*延时函数*/
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include<linux/timer.h>
#include<linux/jiffies.h>
#include <linux/ioport.h>
/*DS18B20 GPIO接口:GPIOA30*/
/*定义指针,用于接收虚拟地址*/
/*volatile unsigned int *DS18B20_GPIOAOUTENB;//*DS18B20_GPACON;//设置ds18b20为1输出/0输入模式
volatile unsigned int *DS18B20_GPIOAOUT;//*DS18B20_GPADAT;//寄存器对应的地址0xC001_A000,输出高低电平
volatile unsigned int *DS18B20_GPIOAPAD;//--------------------------------------------------------------
#define DS18B20_INPUT() {*DS18B20_GPIOAOUTENB &= ~(1<<30);}
#define DS18B20_OUTPUT() {*DS18B20_GPIOAOUTENB |= (1 << 30);}*/
volatile unsigned int *DS18B20_GPIODOUTENB;//*DS18B20_GPACON;//设置ds18b20为1输出/0输入模式
volatile unsigned int *DS18B20_GPIODOUT;//*DS18B20_GPADAT;//寄存器对应的地址0xC001_A000,输出高低电平
volatile unsigned int *DS18B20_GPIODPAD;//--------------------------------------------------------------
#define DS18B20_INPUT() {*DS18B20_GPIODOUTENB &= ~(1<<0);}
#define DS18B20_OUTPUT() {*DS18B20_GPIODOUTENB |= (1 << 0);}
/*
函数功能:等待DS18B20的回应
返回1:未检测到DS18B20的存在
返回0:存在
*/
unsigned char DS18B20_Check(void)
{
unsigned char retry=0;//u8
DS18B20_INPUT();
while((*DS18B20_GPIODPAD & (1<<0))&& retry<200)//----------------------------------------
{
retry++;
udelay(1);
};
if(retry>=200) return 1;
else retry=0;
while(!(*DS18B20_GPIODPAD &(1 << 0))&&retry<240)//----------------------------------------
{
retry ++;
udelay(1);
};
if(retry>=240)
return 1;
return 0;
//else
//return 1;
}
/*写一个复位函数*/
unsigned char DS18B20_reset(void)
{
DS18B20_OUTPUT();
*DS18B20_GPIODOUT |= (1 << 0);
udelay(1);
*DS18B20_GPIODOUT &= ~(1 << 0);
udelay(750);
*DS18B20_GPIODOUT |= (1 << 0);
udelay(30);
DS18B20_INPUT();
while((*DS18B20_GPIODPAD & (1<<0)));
udelay(480);
*DS18B20_GPIODOUT |= (1 << 0);
}
/*
从DS18B20读取一个位
返回值:1/0
*/
unsigned char DS18B20_Read_Bit(void)
{
unsigned char data;
DS18B20_OUTPUT();
*DS18B20_GPIODOUT |= (1 << 0);//
udelay(2);
*DS18B20_GPIODOUT &= ~(1 << 0);//out 0;//--------------------------
udelay(3);
*DS18B20_GPIODOUT |= (1 << 0);//out 1;//-----------------------
udelay(5);
DS18B20_INPUT();
if((*DS18B20_GPIODPAD & (1 << 0))) data=1;
else data=0;
udelay(50);
*DS18B20_GPIODOUT |= (1 << 0);
printk(KERN_INFO "我读到啦%d\r\n",data);
udelay(1);
return data;
}
/*
从DS18B20读取一个字节
返回值:读到的数据
*/
unsigned char DS18B20_Read_Byte(void)
{
//local_irq_disable();
unsigned char i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=dat>>1;
if(j) //主机对总线采样的数 判断-------读数据-1就是1,否则就是0
dat |= 0x80; //先收低位数据--一步一步向低位移动>>
}
//local_irq_enable();
return dat;
}
/*
写一个字节到DS18B20
dat:要写入的字节
*/
void DS18B20_Write_Byte(unsigned char dat)
{
unsigned char j;
unsigned char testb;
DS18B20_OUTPUT();
//DS18B20_INPUT();
for(j=1;j<=8;j++)
{
udelay(1);//
testb= dat&0x01;
dat=dat>>1;
if(testb)
{
DS18B20_OUTPUT();
*DS18B20_GPIODOUT &= ~(0x1<<0);//----------------------------拉低
udelay(2);
*DS18B20_GPIODOUT |= (0x1 << 0);//out 1//------------------------拉高
udelay(60);
DS18B20_INPUT();
if((*DS18B20_GPIODPAD & (1 << 0)))
printk(KERN_INFO "yi我write 1啦\r\n");
}
else
{
DS18B20_OUTPUT();
*DS18B20_GPIODOUT &= ~(1<<0);//---------------------------拉低
udelay(60);
DS18B20_INPUT();
if(!(*DS18B20_GPIODPAD & (1 << 0)))
printk(KERN_INFO "ling我write 0啦\r\n");
DS18B20_OUTPUT();
*DS18B20_GPIODOUT |= (1 << 0);//out 1---------------------拉高
udelay(2);
}
}
}
/*
从ds18b20得到温度值
精度:0.1C
返回值:温度值 (-550~1250)
*/
short DS18B20_Get_Temp(void)
{
unsigned short aaa;
//unsigned char temp=1;
unsigned char LT,HT;
unsigned char result[2]={};
local_irq_disable();
unsigned int temp=1;
temp=DS18B20_reset();
if(!temp)
{
printk(KERN_INFO "我复位啦\r\n");
}
DS18B20_Write_Byte(0xcc);//进入接收模式
DS18B20_Write_Byte(0x44);//执行温度测量和AD转换
DS18B20_reset();
DS18B20_Write_Byte(0xcc);//skip rom
DS18B20_Write_Byte(0xbe);//convert
LT=DS18B20_Read_Byte();//LSB
HT=DS18B20_Read_Byte();//MSB
local_irq_enable();
aaa=(((unsigned short)HT<<8)|LT);
//----------------------------------------
printk(KERN_INFO "读取温度值%d%d\n",HT,LT);
return aaa;
}
/*
杂项字符设备注册示例----->DS18B20
*/
static int s5p6818_open(struct inode *my_inode,struct file *my_file)
{
/*映射物理地址*/
/*DS18B20_GPIOAOUTENB=ioremap(0xC001A004,4);
DS18B20_GPIOAOUT=ioremap(0xC001A000,4);
DS18B20_GPIOAPAD=ioremap(0xC001A018,4);*///-------------------------------------------------
DS18B20_GPIODOUTENB=ioremap(0xC001D004,4);
DS18B20_GPIODOUT=ioremap(0xC001D000,4);
DS18B20_GPIODPAD=ioremap(0xC001D018,4);
printk(KERN_INFO "DS18B20初始化成功!\r\n");
/*设置ds18b20为输出模式*/
//*DS18B20_GPIOAOUTENB &= ~(1 << 30);
//*DS18B20_GPIOAOUTENB |= (1 << 30);
*DS18B20_GPIODOUTENB |= (1 << 0);
return 0;
}
static int s5p6818_release(struct inode *mynode,struct file *my_file)
{
/*释放虚拟地址*/
/*iounmap(DS18B20_GPIOAOUTENB);
iounmap(DS18B20_GPIOAOUT);
iounmap(DS18B20_GPIOAPAD);*///---------------------------------------------------------------
iounmap(DS18B20_GPIODOUTENB);
iounmap(DS18B20_GPIODOUT);
iounmap(DS18B20_GPIODPAD);
printk(KERN_INFO "DS18B20释放成功\r\n");
return 0;
}
static ssize_t s5p6818_read(struct file *my_file,char __user *buf, size_t len, loff_t *loff)
{
/*读取温度信息*/
short temp = DS18B20_Get_Temp();
copy_to_user(buf,&temp,2);//拷贝温度至应用层
return 0;
}
static ssize_t s5p6818_write(struct file *my_file,const char __user *buf, size_t len, loff_t *loff)
{
return 0;
}
/*文件操作集合*/
static struct file_operations s5p6818_fops=
{
.open=s5p6818_open,
.read=s5p6818_read,
.write=s5p6818_write,
.release=s5p6818_release
};
/*
核心结构体
*/
static struct miscdevice s5p6818_misc=
{
.minor=8, /*自动分配次设备号*/
.name="DS18B20", /*设备文件,指定/dev/生成的文件名称*/
.fops=&s5p6818_fops
};
static int __init DS18B20_dev_init(void)
{
printk(KERN_INFO "--> ds18b20 register\n");
int ret;
/*杂项设备注册*/
ret = misc_register(&s5p6818_misc);
if(ret)
printk(KERN_INFO "misc register failed\n");
else
printk(KERN_INFO "misc register success\n");
return 0;
}
static void __exit DS18B20_dev_exit(void)
{
/*杂项设备注销*/
misc_deregister(&s5p6818_misc);
}
module_init(DS18B20_dev_init);
module_exit(DS18B20_dev_exit);
MODULE_LICENSE("GPL");
快两个星期试了各种办法都不行,如果是时序错误,我也按照数据手册写了,怎么会不行呢。好奇怪啊
能够正确读取温度
无法读取数据的报错是社么啊
可能是 udelay 函数用的不对。这个函数等待延时的参数是微秒,ds18b20需要的延时应该是毫秒。
你可以用示波器测试一下看看波形
你好请问你解决了嘛 我也需要用到sp56818接ds18b20 弄了好几天没进展