|
刚开始学linux驱动,摸索了好多天,刚开始GPIO口不知道怎么驱动,上网找了无数资料,测试了无数遍才搞定,希望对刚学linux 驱动的朋友有些帮助!
文件名:DS18B20.c 用途linux 驱动程序
//-------DS18B20.c文件开始-------------------
//Design by 001friend (2009.12.27)
//DS18B20 Drive for linux2.4.20 (target: S3C2440)
//1-wire bus interface drive via GPG7
#ifndef _KERNEL_
#define _KERNEL_
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/version.h>
#include <asm/arch-s3c2440/S3C2440.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/unistd.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#define MAJOR_NUM 98 //主设备号
//*************DS18B20 operation begin********
#define dat_1820_hign GPGDAT|=1<<7;GPGCON&=~(3<<14)
#define dat_1820_low GPGDAT&=~(1<<7);GPGCON=(GPGCON&(~(3<<14)))|(1<<14)
//18B20 reset
unsigned char DS18B20_Reset(void)
{
unsigned char dr=0;
dat_1820_low;
udelay(600); //delay 600uS
dat_1820_hign;
udelay(80); //delay 80uS
if(!(GPGDAT&(1<<7)))
dr=1;
udelay(500); //delay 400uS
return dr;
}
void DS18B20_Write(unsigned char dw)
{
unsigned char wr;
for(wr=0;wr<8;wr++)
{
dat_1820_low;
if(dw&0x01)
{
udelay(5);
dat_1820_hign;
udelay(60);
}
else
{
udelay(75);
}
dat_1820_hign;
dw>>=1;
udelay(3);
}
udelay(5);
}
//read a byte from 1-wire bus
unsigned char DS18B20_Read(void)
{
unsigned char dr,dr1=0;
for(dr=0;dr<8;dr++)
{
dr1>>=1;
dat_1820_low;
udelay(2);
dat_1820_hign;
udelay(10);
if(GPGDAT&(1<<7))
dr1|=0x80;
udelay(60);
}
return dr1;
}
//read the temperature
short DS18B20_ReadTemp(void)
{
float dt3;
short dt;
unsigned char dt1,dt2;
DS18B20_Reset();
DS18B20_Write(0xcc);
DS18B20_Write(0x44);
GPGDAT|=1<<7;GPGCON=(GPGCON&(~(3<<14))) | (1<<14 ); //power supply for DS18B20
mdelay(1000); //delay 1S
dat_1820_hign;
DS18B20_Reset();
DS18B20_Write(0xcc);
DS18B20_Write(0xbe);
dt1=DS18B20_Read();
dt2=DS18B20_Read();
dt=dt2*0x100+dt1;
DS18B20_Reset();
/* if(dt&(1<<15))
{
dt=0xffff-dt+1;
dt3=dt*0.0625*10;
dt=0x8000+dt3;
}
else
// {
dt3=(float)dt*0.0625*10;
dt=dt3;
// }*/
// dt3=((float)dt)*0.0625;
return dt;
}
//*************DS18B20 operation end**********
static ssize_t DS18B20_read(struct file *file, char *buff, size_t size, loff_t *loff_t)
{
short tp;
tp=DS18B20_ReadTemp();
copy_to_user(buff, &tp, sizeof(short));
return sizeof(short);
}
struct file_operations DS18B20_fops=
{
read:DS18B20_read,
};
static int __init DS18B20_init(void)
{
int ret=0;
short tp=0;
dat_1820_hign;
GPGUP&=~(1<<7);
mdelay(1000);
tp=DS18B20_ReadTemp();
printk("temperature is %i\n",tp);
ret=register_chrdev(MAJOR_NUM,"DS18B20",&DS18B20_fops);
if(ret)
{
printk("DS18B20 register failure");
}
else
{
printk("DS18B20 register success\n");
}
return ret;
}
static void __exit DS18B20_exit(void)
{
int ret=0;
dat_1820_hign;
ret=unregister_chrdev(MAJOR_NUM,"DS18B20");
if(ret)
{
printk("DS18B20 unregister failure");
}
else
{
printk("DS18B20 unregister success\n");
}
}
MODULE_LICENSE("GPL");
module_init(DS18B20_init);
module_exit(DS18B20_exit);
//-------DS18B20.c文件结束-------------------
编译步骤
在终端里运行
编译命令 arm-linux-gcc -D__KERNEL__ -D MODULE -I /usr/src/s3c2440_2.4.20/include -c DS18B20.c
编译成功会生成文件 DS18B20.o 这个文件就是我们需要的驱动模块了
注:
arm-linux-gcc 这是交叉编译器(当然你电脑里要首先安装交叉编译器)
/usr/src/s3c2440_2.4.20/include 这是S3C2440 linux内核源代码地址,你的可能不一样
接下来我们需要把 DS18B20.o 通过U盘拷贝到S3C2440开发板上 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|