问题描述
- 再次请求支援,关于字符设备驱动的程序问题,求帮找错(不好意思没点数了)
-
先贴代码,问题在后面驱动函数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
#includevolatile 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
#includeint 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的薄弱带来的痛苦,求点评和建议