/****************************************
* 文件名: ceju.c
* 作者: GTY
* 时间: 2016-11-10
* 文件说明: 超声波测距驱动实现文件
****************************************/
/*头文件*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define EINT14 S3C2410_GPG6//echo
#define E14_IN S3C2410_GPG6_INP
#define E14_OUT S3C2410_GPG6_OUTP
#define EINT15 S3C2410_GPG7//trig
#define E15_IN S3C2410_GPG7_INP
#define E15_OUT S3C2410_GPG7_OUTP
#define EINT19 S3C2410_GPG11//echo
#define E19_IN S3C2410_GPG11_INP
#define E19_OUT S3C2410_GPG11_OUTP
struct cdev cdev; //字符设备结构体,静态分配
dev_t devno; //设备号
unsigned long ret=0x0;
/*宏定义命令*/
#define L 0 //超声波测距命令1
#define H 1 //超声波测距命令2
#define DEVICE_NAME "ceju"
#define chaoshen_MAJOR 230
/****************************************
* 函数名: CEJU_Open()
* 入口参数:struct inode *node:inode文件结构体;struct file *filp:file文件结构体
* 出口参数:返回0
* 函数功能:文件打开函数
****************************************/
int Ceju_Open(struct inode *node, struct file *filp)
{
s3c2410_gpio_cfgpin(EINT15, CPG_OUT); // 配置GPG11输出模式
s3c2410_gpio_cfgpin(EINT19, CPG_OUT); // 配置GPG11输出模式
s3c2410_gpio_setpin(EINT15, 1); // 向18B20发送一个上升沿
s3c2410_gpio_setpin(EINT19, 1); // 向18B20发送一个上升沿
return 0;
}
/****************************************
* 函数名: Ceju_Ioctl()
* 入口参数:struct file *filp:文件结构指针;
unsigned int cmd:控制命令;
unsigned long arg:命令参数
* 出口参数:成功:返回0;失败:返回-EINVAL
* 函数功能:命令控制函数
****************************************/
long Ceju_Ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case L:
s3c2410_gpio_cfgpin(EINT15, E15_OUT);
s3c2410_gpio_setpin(EINT15, 0);
return 0;
case H:
s3c2410_gpio_cfgpin(EINT15, E15_OUT);
s3c2410_gpio_setpin(EINT15, 1);
return 0;
default:
return -EINVAL;
}
}
/****************************************
* 函数名: Ceju_Read
* 入口参数:struct file *filp:文件指针
char __user *buf:存放读取数据的缓冲区
size_t size:读取的数据大小
loff_t *p:文件偏移量
* 出口参数:返回4
* 函数功能:按键读取数据
****************************************/
ssize_t Ceju_Read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
s3c2410_gpio_cfgpin(EINT19, E19_IN);
ret = s3c2410_gpio_getpin(EINT19);
copy_to_user(buf, &ret, 4);
return 4;
}
/*文件操作结构体*/
static struct file_operations ceju_fops =
{
.open = Ceju_Open,
.unlocked_ioctl = Ceju_Ioctl,
.read = Ceju_Read,
};
static char __initdata banner[] = "TQ2440/SKY2440 ceju\n";//打印信息
static struct class *ceju_class;
static int Ceju_Init()
{
int ret;
printk(banner);
ret = register_chrdev(ceju_MAJOR, DEVICE_NAME, &ceju_fops);
if (ret < 0)
{
printk(DEVICE_NAME " can't register major number\n");
return ret;
}//错误处理
ceju_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(ceju_class))
{
printk("Err: failed in tope-leds class. \n");
return -1;
}
device_create(ceju_class, NULL, MKDEV(ceju_MAJOR, 0), NULL, DEVICE_NAME);//创建一个设备节点,节点名为DEVICE_NAME
printk(DEVICE_NAME " initialized\n");//打印信息,内核中的打印用printk函数
return 0;
}
/****************************************
* 函数名: Ceju_Exit()
* 入口参数:无
* 出口参数:无
* 函数功能:模块卸载函数
****************************************/
static void Ceju_Exit()
{
printk(DEVICE_NAME " exit\n");//打印信息,内核中的打印用printk函数
unregister_chrdev(ceju_MAJOR, DEVICE_NAME);//取消注册设备
device_destroy(ceju_class, MKDEV(ceju_MAJOR, 0)); //删掉设备节点
class_destroy(ceju_class); //注销类
}
MODULE_LICENSE("GPL"); //遵守的协议
module_init(Ceju_Init);
module_exit(Ceju_Exit);
以下是应用程序
/****************************************
* 文件名: ceju.c
* 作者: GTY
* 时间: 2016-11-10
* 文件说明: 超声波测距
****************************************/
/*头文件*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
/*宏定义命令*/
#define L 0 //超声波测距命令1
#define H 1 //超声波测距命令2
int main(int argc, char **argv)
{
int fd;
unsigned long ret,timeuse;
int i = 0;
struct timeval start,end;
fd = open("/dev/ceju", O_RDWR);
if (fd<0)
printf("open fail\n");
ioctl(fd,L);
usleep(10);
ioctl(fd,H);
usleep(15);
ioctl(fd,L);
while(1)
{
read(fd, &ret, 4);
if (1 == ret)break;
gettimeofday(&start,NULL);
while(1)
{
read(fd, &ret, 4);
if(0 == ret) break;
}
gettimeofday(&end,NULL);
timeuse = (1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec));
distance = 345* timeuse / 2000000;
printf("ceju is %d cm\n",distance);
// break;
}
}
close(fd);
return 0;
}