应用程序-再次请求支援,关于字符设备驱动的程序问题,求帮找错(不好意思没点数了)

问题描述

再次请求支援,关于字符设备驱动的程序问题,求帮找错(不好意思没点数了)

先贴代码,问题在后面

驱动函数pressure。c:

/*

功能:

外部中断4接一个人体红外感应,如果感应到有人体活动(红外模块输出高电平),如果感应不到
人体活动(红外模块输出低电平)(变量red)

外部中断8接了一个按钮开关,如果按钮开关被按下,则输出为低电平,外部中断8管脚应该低电平,
反之,高电平 (变量pre)

只有当设备感应到有人体活动同时检测到按钮开关被按下。即 red == 1,pre == 0,的时候,才打
印HELLO!!!,其他的情况,都打印MISS!!!,举例来说,就是一个凳子上 坐着一个小孩,如果检测不到
小孩在活动,同时检测到凳子没有受到来自小孩的压力的话,报警

*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

volatile unsigned long *gpbcon = NULL; // nLED_2(GPB6)
volatile unsigned long *gpbdat = NULL;
volatile unsigned long *gpfcon = NULL; // EINT4 ( GPF4 )
volatile unsigned long *gpfdat = NULL;
volatile unsigned long *gpgcon = NULL; // EINT8 ( GPG0 )
volatile unsigned long *gpgdat = NULL;
//volatile unsigned long *eintmask = NULL;
//volatile unsigned long *eintpend = NULL;

unsigned int val = 0;
unsigned int red = 1;
unsigned int pre = 0;

static struct class *pressuredrv_class;
static struct class_device *pressuredrv_class_dev;

//等待队列
static DECLARE_WAIT_QUEUE_HEAD(pressure_waitq);

/* 中断事件标志, 中断服务程序将它置1,pressure_read将它清0 */
static volatile int ev_press = 0;

static irqreturn_t pressure_irq(int irq, void *dev_id)
{
if(irq == (IRQ_EINT4 | IRQ_EINT8))
{
red = s3c2410_gpio_getpin(S3C2410_GPF4) & (1 << 4) ? 1:0;
pre = s3c2410_gpio_getpin(S3C2410_GPG0) & (1 << 0) ? 1:0;

            ev_press = 1; /* 表示中断发生了 */
        wake_up_interruptible(&pressure_waitq); /* 唤醒休眠的进程 */
}
    return IRQ_RETVAL(IRQ_HANDLED); /*该返回值代表中断确实真的处理了该中断*/

}

static int pressure_open(struct inode inode, struct file *file)
{
*gpbcon &= ~(0x3<<(06*2)); /
配置GPB6为输出引脚 /

*gpbcon |= (0x1<<(06*2));
//request_irq(IRQ_EINT4, pressure_irq, IRQT_LOW, "PRESSURE", NULL); //设置外部中断4
request_irq(IRQ_EINT4, pressure_irq, IRQT_BOTHEDGE, "PRESSURE", NULL); //设置外部中断4,双边沿触发
/
感应到有人体活动(红外模块输出高电平),感应不了人体活动(红外模块输出低电平)*/
request_irq(IRQ_EINT8, pressure_irq, IRQT_BOTHEDGE, "PRESSURE", NULL); //设置外部中断8,按钮开关,如果按下,低电平,否则,高电平

    return 0;

}

static int pressure_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
wait_event_interruptible(pressure_waitq, ev_press);

    copy_to_user(buf, &red, 4);
    copy_to_user(buf, &pre, 4);
    ev_press = 0; 

    return 0;

}

static ssize_t pressure_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int con = 0;
copy_from_user(&con, buf, 4);
if (con == 1)
{
*gpbdat &= ~(1<<6); //亮灯报警
}
else
{
*gpbdat |= (1<<6); //灭灯
}
return 0;
}

static ssize_t pressure_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT4, NULL);
free_irq(IRQ_EINT8, NULL);
return 0;
}

static struct file_operations pressure_drv_fops = {
.owner = THIS_MODULE,
.open = pressure_open,
.read = pressure_read,
.write = pressure_write,

.release = pressure_close,

};

int major;
static int __init pressure_drv_init(void)
{

major = register_chrdev(0, "pressure_drv", &pressure_drv_fops);
    pressuredrv_class = class_create(THIS_MODULE, "pressure_drv");
    pressuredrv_class_dev = class_device_create(pressuredrv_class, NULL, MKDEV(major, 0), NULL, "PressureDrv");
    gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16);
    gpbdat = gpbcon + 1;
    gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
    gpfdat = gpbcon + 1;
    gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
    gpgdat = gpgcon + 1;
    return 0;

}

static void __exit pressure_drv_exit(void)
{

unregister_chrdev(major, "pressure_drv");
class_device_unregister(pressuredrv_class_dev);
class_destroy(pressuredrv_class);
iounmap(gpbcon);
iounmap(gpfcon);
iounmap(gpgcon);
//iounmap(eintmask);
//iounmap(eintpend);
}

module_init(pressure_drv_init);
module_exit(pressure_drv_exit);

MODULE_LICENSE("GPL");

应用程序app.c:

#include
#include
#include
#include
#include
#include

int main(int argc, char **argv)
{
int fd;
int con = 0;
unsigned int val = 0;
unsigned int red = 1;
unsigned int pre = 0;

    int rc = 0;
    struct timeval tv;

    fd = open("/dev/PressureDrv",O_RDWR);
    if (fd < 0)
    {
            printf("can't open!n");
    }

    while (1)
    {
            read(fd,&red,4); //printf("red = %un",red);
            read(fd,&pre,4); //printf("pre = %un",pre);
            if ((red == 1) && (pre == 0))
            {
                    //usleep(10);
                    tv.tv_sec = 0;
                    tv.tv_usec = 10;
                    select(0, NULL, NULL, NULL, &tv);
                    if ((red == 1) && (pre == 0))
                    {
                            printf("red = %u , pre = %un",red,pre);
                            con = 0;
                            write(fd,&con,4);
                            printf("HELLO!!!n");
                            //while(!((pre == 1) && (red == 0)));
                    }
                    else
                    {
                            printf("red = %u , pre = %un",red,pre);
                            printf("MISS!!!n");
                            con = 1;
                            write(fd,&con,4);
                            //while(!((pre == 1) && (red == 0)));
                    }
            }
            else
                    {
                            printf("red = %u , pre = %un",red,pre);
                            printf("MISS!!!n");
                            con = 1;
                            write(fd,&con,4);

                    }
    }

}

现在的问题是:

能输出pre=0,red=0;pre=0,red=1;pre=1,red=0;pre=1,red=1这 4种情况分别的 HELLO 或 MISS 的情况,但是却是错乱的,
比如说,我明明没有触发 红外模块的时候,这时 red 应该为0,但是输出却是为1,
输出结果跟我实际对红外和按钮开关的操作 有很大的出入,不知道应该是哪里的问题

通过这几天,我感受到C的薄弱带来的痛苦,求点评和建议

时间: 2024-08-30 03:49:46

应用程序-再次请求支援,关于字符设备驱动的程序问题,求帮找错(不好意思没点数了)的相关文章

Linux字符设备驱动总结程序(二)

前面我们讲解了字符设备驱动的一些写法,但是那样写出来的程序只能我们自己用或者自己公司用.因为你没有统一接口,别人不知道你的设备接口是什么,现在我们讲解几种常用的设设备模型. 第一:input输入子系统(键盘,鼠标,触摸屏等等) static struct input_dev *s3c_ts_dev;//定义一个 input_dev结构体s3c_ts_dev = input_allocate_device();//分配input_dev结构体input_register_device(s3c_ts

Linux字符设备驱动编写基本流程

  ---简介 Linux下的MISC简单字符设备驱动虽然使用简单,但却不灵活. 只能建立主设备号为10的设备文件.字符设备比较容易理解,同时也能够满足大多数简单的硬件设备,字符设备通过文件系          统中的名字来读取.这些名字就是文件系统中的特殊文件或者称为设备文件.文件系统的简单结点,一般位于/dev/目录下          使用ls进行查看会显示以C开头证明这是字符设备文件crw--w---- 1 root tty 4, 0 4月 14 11:05 tty0.第一个数字是主设备

【Linux驱动】字符设备驱动

一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流的设备,常见的字符设备有鼠标.键盘.串口.控制台和LED设备等. 2.块设备:是指可以从设备的任意位置读取一定长度数据的设备.块设备包括硬盘.磁盘.U盘和SD卡等. 每一个字符设备或块设备都在/dev目录下对应一个设备文件.linux用户程序通过设备文件(或称设备节点)来使用驱动程序操作字符设备

Linux字符设备驱动框架

字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l /dev的时候,就能看到大量的设备文件,c就是字符设备,b就是块设备,网络设备没有对应的设备文件.编写一个外部模块的字符设备驱动,除了要实现编写一个模块所需要的代码之外,还需要编写作为一个字符设备的代码. 驱动模型 Linux一切皆文件,那么作为一个设备文件,它的操作方法接口封装在struct fi

Linux字符设备驱动

1.预备知识: 应用程序.库.内核.驱动程序的关系 应用程序调用应用程序函数库完成功能应用程序以文件形式访问各种资源应用程序函数库部分函数直接完成功能     部分函数通过系统调用由内核完成   内核处理系统调用,调用设备驱动程序   设备驱动直接与硬件通信 设备类型 字符设备     对字符设备发出读/写请求时,实际的硬件I/O操作一般紧接着发生 块设备     块设备与之相反,它利用系统内存作为缓冲区 网络设备     网络设备是一类特殊的设备,它不像字符设备或块设备那样通过对应的设备文件节

linux驱动-linux字符设备驱动求助:设备号无法释放

问题描述 linux字符设备驱动求助:设备号无法释放 我在驱动中,资源释放时调用了unregister_chrdev_region函数,为什么用rmmod卸载驱动模块之后,/proc/devices里边仍能够显示我的驱动设备啊? lsmod中已经没有我写的驱动模块了. 是因为设备号没能正确释放么? 解决方案 当应用程序打开设备节点时,内核调用相应驱动程序的open()函数.可以在shell中执行以下代码来触发cmos_open()的执行: bash> cat /dev/cmos/0 当应用程序关

Linux内核分析(五)----字符设备驱动实现

原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷,我们都会以虚拟的设备为例进行学习,所以大家不必害怕没有硬件的问题. 今天我们会分析到以下内容: 1.      字符设备驱动基础 2.      简单字符设备驱动实现 3.      驱动测试   l  字符设备基础 1.       字符设备描述结构 在linux2.6内核中,使用cdev结构体描

Linux 字符设备驱动框架详细介绍_Linux

Linux 字符设备驱动框架 字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l /dev的时候,就能看到大量的设备文件,c就是字符设备,b就是块设备,网络设备没有对应的设备文件.编写一个外部模块的字符设备驱动,除了要实现编写一个模块所需要的代码之外,还需要编写作为一个字符设备的代码. 驱动模型 Linux一切皆文件,那么作为一个设备文件,它的操作方

《嵌入式Linux开发实用教程》——4.2 字符设备驱动

4.2 字符设备驱动 Linux操作系统将所有的设备都会看成是文件,因此当我们需要访问设备时,都是通过操作文件的方式进行访问.对字符设备的读写是以字节为单位进行的. 对字符设备驱动程序的学习过程,主要以两个具有代表性且在OK6410开发平台可实践性的字符驱动展开分析,分别为LED驱动程序.ADC驱动程序. 4.2.1 LED驱动程序设计 为了展现LED的裸板程序和基于Linux系统的LED驱动程序的区别与减少难度梯度,在写LED驱动程序之前很有必要先看一下LED的裸板程序是怎样设计的. 1.LE