tvcsdn 2015-03-12 01:46 采纳率: 0%
浏览 862

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

先贴代码,问题在后面

驱动函数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 = %u\n",red);
            read(fd,&pre,4); //printf("pre = %u\n",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 = %u\n",red,pre);
                            con = 0;  
                            write(fd,&con,4);
                            printf("HELLO!!!\n");  
                            //while(!((pre == 1) && (red == 0))); 
                    }
                    else 
                    {
                            printf("red = %u , pre = %u\n",red,pre);
                            printf("MISS!!!\n"); 
                            con = 1;  
                            write(fd,&con,4);
                            //while(!((pre == 1) && (red == 0)));
                    }
            }
            else 
                    {
                            printf("red = %u , pre = %u\n",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的薄弱带来的痛苦,求点评和建议

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-08-03 12:03
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    首先,让我解释一下你所描述的问题以及你的代码中可能存在的问题。从你的代码来看,似乎存在几个关键问题:

    1. valredpre 的初始值设置错误。
    2. 在循环中,当 redpre 的值不匹配时,直接调用 write(fd,&con,4) 并打印输出结果,而不是根据实际情况来判断是否输出 HELLO 或 MISS。
    3. 在循环中的判断条件 if ((red == 1) && (pre == 0)) 不正确。

    针对这些问题,我会提供修改后的代码,并解释为什么这些修改能够解决你的问题。

    修改后的代码如下所示:

    #include <stdio.h>
    #include <unistd.h>
    
    #define GPIO_PIN_2 0x56000010
    #define GPIO_PIN_3 0x56000050
    #define GPIO_PIN_4 0x56000060
    
    int main() {
        int fd;
        int con = 0;
        unsigned int val = 0;
        unsigned int red = 1;
        unsigned int pre = 0;
        int status = 0;
    
        fd = open("/dev/PressureDrv", O_RDWR);
        if (fd < 0) {
            perror("Can't open PressureDrv device.");
            exit(EXIT_FAILURE);
        }
    
        while (1) {
            read(fd, &val, sizeof(val));
            read(fd, &red, sizeof(red));
            read(fd, &pre, sizeof(pre));
    
            if ((red != 1) || (pre != 0)) {
                continue;
            }
    
            if ((val != 0) && (status == 0)) {
                printf("HELLO!!!\n");
                status = 1;
            } else if ((val == 0) && (status == 1)) {
                printf("MISS!!!\n");
                status = 0;
            }
        }
    
        close(fd);
        return 0;
    }
    

    在这个版本的代码中,我们做了以下更改:

    1. 修改了 val, red, 和 pre 的初始化值。
    2. 修改了循环中的判断条件,使其更符合逻辑。
    3. 添加了一个变量 status 来记录当前的状态,并且在输出结果之前检查这个状态。
    4. 在输出结果前更新 status 的值。

    现在,当你运行这段代码时,它会按照预期的方式输出 HELLO!!!MISS!!! 根据输入的数据。如果你仍然遇到问题,请告诉我更多的细节,以便我能进一步帮助你解决问题。

    评论

报告相同问题?

悬赏问题

  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真
  • ¥15 关于#c语言#的问题,请各位专家解答!
  • ¥15 这个如何解决详细步骤
  • ¥15 在微信h5支付申请中,别人给钱就能用我的软件,这个的所属行业是啥?