微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > arm上的18b20驱动程序,有问题,请大家给调试下

arm上的18b20驱动程序,有问题,请大家给调试下

时间:10-02 整理:3721RD 点击:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>   //定义module_init和module_exit宏
#include <linux/fs.h>       //定义file_operations结构体和register_chrdev_region等函数
#include <linux/cdev.h>     //定义cdev_init cdev_add cdev_del函数
#include <asm/uaccess.h>    //定义copy_to_user和copy_from_user函数
#include <asm/io.h>         //定义inl和outl、__raw_readl和__raw_writel等IO口读写宏
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-n.h>
#include <mach/map.h>
#include<linux/delay.h>
#define DS18B20_DEVICE_NAME "DS18B20"
#define DS18B20_DEVICE_FILENAME "/dev/DS18B20"
typedef unsigned char uchar ;
//////////////////////设定寄存器使io为输入状态/////////////
void shuru(void )
{
uint tmp;
tmp=readl(S3C64XX_GPNCON);     //设置GPN寄存器,使用GPN的io口可以输入输出,读出GPNCON内部存的值
  tmp &= 0xFFFCFFFF;             //设置寄存器的16口为0,17口为0使其为输入状态
  writel(tmp,S3C64XX_GPNCON); //在写入回到GPNCON中,设定为输入io
}
///////////////////////设定寄存器使io为输出状态/////////////////////////////
void shuchu(void)
{
uint tmp;
tmp=readl(S3C64XX_GPNCON);    //设置GPN寄存器,使用GPN的io口可以输入输出,读出GPNCON内部存的值
tmp |= 0x00010000;  //设置寄存器的16口为1,17口为0
  writel(tmp,S3C64XX_GPNCON); //在写入回到GPNCON中,设定为输出io
}
//////////////////////////把io口拉高////////////////////
void tmph(void)
{
uint tmp;
  tmp=readl(S3C64XX_GPNDAT); //读取p1.30口的值
tmp|=0x00000100;  //把io口电平拉高
   writel(tmp,S3C64XX_GPNDAT); //写入到18b20
}
//////////////////////////把io口拉低////////////////////
void tmpl(void)
{
uint tmp;
  tmp=readl(S3C64XX_GPNDAT); //读取p1.30口的值
tmp&=0xFFFFFEFF;  //把io口电平拉低
   writel(tmp,S3C64XX_GPNDAT); //写入到18b20
}
///////////////////////////////初始化18b20/////////////////////////
uchar reset(void)
{
uint tmp;
uchar fuwei;
shuchu();   //设置为输出状态
tmph();    //拉高io口
tmpl();    //拉低io口
udelay(400);   //延迟400us
tmph();    //拉高io口
udelay(80);   //延迟80us
tmp=readl(S3C64XX_GPNDAT);      //读出GPNSAT内部存的值
udelay(150);   //延迟150us
tmp&=0x00000100;
tmp>>=8;
fuwei=tmp;
tmph();
return fuwei;   //返回存在信号
}
////////////////////写一个位进去////////////////////
void  wrbt(uchar bite)
{
shuchu();
tmpl();    //把io口拉低
if(bite==1)   
tmph();    //把io拉高
udelay(30);   //延迟30us
tmph();    //释放总线
udelay(15);   //稍作延迟
}
/////////////////读一个位出来////////////////////////
uchar rdbt(void)
{
uint i=0;
uchar m=0;
shuru();
tmpl();    //拉低
udelay(1);
tmph();    //拉高
udelay(10);   //延时不得超过4us
i=readl(S3C64XX_GPNDAT); //读取io口的值
udelay(10);
i=(i>>8);   //读出的值(第一次为最低位)
m=(i&0x01);
printk("%daaaaa\n ",m);
return m;   //返回读出的值
}
//////////////////写一个字节/////////////////////////
void wrbyte(uchar k)
{
uchar i=0,tmp=0;
for(i=0;i<8;i++)
{
  tmp=(k>>i);  //先写第一位数值
  tmp=tmp&0x01;  
  wrbt(tmp);  //调用函数写入值
  udelay(100);  //延时保证写入
}
}
///////////////////读一个字节//////////////////////////
uchar rdbyte(void)
{
uchar i=0,n=0,tmp=0;
for(i=0;i<8;i++)
{
  n=rdbt();
  n=(n<<i);
  tmp=tmp+n;
  udelay(100);
}
return tmp;
}
int DS18B20status=0;
////////////////////////////////////////////////////////////////////////////////////////////
//    实际工作部分      ///
///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////打开设备文件,并初始化设备文件//////////////////////////
int DS18B20_open(struct inode *inode,struct file *file)
{
  uchar fuwei;
  printk("DS18B20 open\n");
  fuwei=reset();
udelay(20);
if(fuwei)
printk("no node at here\n");
else
printk("There is a node\n");
  return 0;
}
//////////////////////////////////关闭文件操作///////////////////////////////////
int DS18B20_release(struct inode *inode,struct file *file)
{
uint tmp;
shuru();
tmp=readl(S3C64XX_GPNDAT);
tmp &= 0xFFFFFEFF;
writel(tmp,S3C64XX_GPNDAT);
printk("DS18B20 close\n");
   
return 0;
}
///////////////////////////////////////读温度传感器并转还为温度值///////////////////////////////////////
static ssize_t DS18B20_read(struct file *filp,unsigned char __user *buf,size_t count,loff_t *ppos)
{
uchar arry[2]={0};
reset();
udelay(420);//////////////////////////////////////////
wrbyte(0xcc);   //给传感器写一个skipROM命令
wrbyte(0x44);   //写一个温度转换命令convertT
mdelay(1000);/////////////////////////////////////////////
reset();          //等待转换成功
udelay(400);//////////////////////////////////////////
wrbyte(0xcc);   //一个skipROM命令
wrbyte(0xbe);   //写一个读取命令
arry[0]=rdbyte();   //读取低八位
arry[1]=rdbyte();   //读取高八位
// buf[0]=arry[0];
// buf[1]=arry[1];  
/* if(arry[1]>>8!=0)  //如果高八位不为0则为负摄氏温度
{
  arry[1]=~arry[1]; //
  arry[0]=~arry[0];
  arry[0]+=1;  //取反加一,求出原码
}
*/ *buf=arry[0]/16+arry[1]*16; //
*(buf+1)=(arry[0]&0x0f)*10/16+(arry[1]&0x0f)*100/16%10;
//copy_to_user(buf,&DS18B20status,1);
printk("DS18B20 read\n");
printk("%d  %d  \n",arry[0],arry[1]);
printk("bufaaaaaaddddddddddddddd = %d\n",*(buf+1));
    return 0;
}
////////////////////////////////////////写温度值////////////////////////////////////////////////////
static ssize_t DS18B20_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos)
{
reset();
wrbyte(0xCC);
wrbyte(0x4E);
wrbyte(buf[0]);  // 写入上限值
wrbyte(buf[1]);  //写入下限值
wrbyte(0x48);  //把暂存器的值复制到E2存储器
printk("DS18B20 write\n");
return 0;
}
long int DS18B20_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)  //IO口控制函数,操作的时寄存器,cmd微操作命令,传递一个参数arg
{
   //uint tmp;
   printk("DS18B20 ioctl\n");
   /*switch(cmd)
       {
          case 0: tmp=readl(S3C64XX_GPNDAT);
                  tmp &= 0xFFFFBFFF;
                  writel(tmp,S3C64XX_GPNDAT);
                  printk("BEEP1 OFF\n");
                  return 0;
          case 1: tmp=readl(S3C64XX_GPNDAT);
                  tmp |= 0x00004000;
                  writel(tmp,S3C64XX_GPNDAT);
                  printk("BEEP1 ON\n");
                  return 0;
          default: printk("unsupported command\n");
                   return -EINVAL;
       }*/
return 0;
   
}
static struct file_operations DS18B20_fops=
{
    .owner   = THIS_MODULE, //拥有该结构模块的指针,避免在操作时被卸载,一般初始化为THIS_MODULE
    .open    = DS18B20_open, //对外提供打开操作
    .release = DS18B20_release, //当file结构指针释放时,调用次函数,即:当最后一个打开该设备文件的用户调用close时,将调用此函数
    //release 函数的主要任务是清理未结束的输入/输出操作、释放资源、用户自定义排他标志的复位等
    .read    = DS18B20_read, //对外提供读操作
    .write   = DS18B20_write, //对外提供写操作
    .unlocked_ioctl   = DS18B20_ioctl, //该函数是特殊的控制函数,可以通过它向设备传递控制信息或从设备取得状态信息,即为io控制函数
};
static struct cdev DS18B20_devs;
int major=0;
static void DS18B20_setup_cdev(struct cdev *dev,int minor,struct file_operations *fops)
{
    int err,devno=MKDEV(major,minor);//把0和原来生成的设备号再合并到一块去 ,再生成一个设备号,表示有一个设备
    cdev_init(dev,fops);
    dev->owner=THIS_MODULE;
    dev->ops=fops;  //把dev的ops设置成为fops
    err=cdev_add(dev,devno,1); //向内核注册新生成的devno信息,1表示和设备关联的的设备书目
    if(err)   //判断设备是否存活,如果cdev_add()调用成功的话,设备就可以使用了,外部的应用程序对它的操作,内核就会允许了
        {
             printk("Error %s adding DS18B20 %d\n",KERN_ALERT,minor);
                printk("Error %d adding DS18B20 %d\n",err,minor);
        }
}
static int DS18B20_init(void)
{
    int result;
    dev_t dev=MKDEV(major,0); //申请设备,major为主设备号,0为次设备号,表示自动分配设备号
    if(major)   //表示如果已经有了主设备号,就直接注册设备号
        {
            result=register_chrdev_region(dev,1,DS18B20_DEVICE_NAME);
        }
    else   //如果没有主设备号,
        {
            result=alloc_chrdev_region(&dev,0,1,DS18B20_DEVICE_NAME);//自动申请主设备号
            major=MAJOR(dev); //通过访问设备号,获得主设备号
        }
    if(result<0)
        {
            printk("DS18B20:unable to get major %s\n",KERN_ALERT);//报告错误,立即采取措施宏为1
            printk("DS18B20:unable to get major %d\n",major);
            return result;
        }
DS18B20_setup_cdev(&DS18B20_devs,0,&DS18B20_fops);//这里的0表示的是第一个设备,因为咱们就有一个设备,以后在使用中,不一定是一个,拿着就是变量两
printk(KERN_ALERT"The major of DS18B20 device is %d\n",major);
printk("The major of DS18B20 device is %d\n",major);
return 0;
}
static void DS18B20_cleanup(void)
{
cdev_del(&DS18B20_devs);
unregister_chrdev_region(MKDEV(major,0),1);
printk("DS18B20 device uninstalDS18B20\n");
printk(KERN_ALERT"DS18B20 device uninstall\n");
}
module_init(DS18B20_init);
module_exit(DS18B20_cleanup);
MODULE_LICENSE("Dual BSD/GPL");

框架没问题,但时序好像有问题,给解决下,看看哪儿的事l

知道时序就自己找一下时序的问题,单总线对时序要求严格

看看

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top