先贴代码,问题在后面
驱动函数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的薄弱带来的痛苦,求点评和建议