一、测试程序:
之前对按键驱动程序原理大概进行了分析,那么现在给出测试程序了。。。
/*********************************************************************************
* Copyright: (C) 2017 qicheng
* All rights reserved.
*
* Filename: mybutton.c
* Description: This file
*
* Version: 1.0.0(04/17/2017)
* Author: yangni <497049229@qq.com>
* ChangeLog: 1, Release initial version on "04/17/2017 03:52:48 PM"
*
********************************************************************************/
#include <stdio.h>
#include"plat_ioctl.h"
#include <errno.h> //for perror()
//for select()
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
//for open()
#include <sys/stat.h>
#include <fcntl.h>
#define PLATDRV_MAGIC 0x60
#define LED_OFF _IO (PLATDRV_MAGIC, 0x18)
#define LED_ON _IO (PLATDRV_MAGIC, 0x19)
#define LED_BLINK _IO (PLATDRV_MAGIC, 0x1A)
#define KEY1 0x1 //1<<1
#define KEY2 0x2 //1<<2
#define KEY3 0x4 //1<<3
#define KEY4 0x8 //1<<4
int main(int argc,char **argv)
{
int fd_button,led_fd;
int retval;
int status_button;
fd_set rfds;
fd_button=open("dev/button",O_RDWR);
if (fd_button<0)
{
perror("open failed!\n");
}
led_fd=open("dev/led",O_RDWR);
if (led_fd<0)
{
perror("open failed!\n");
}
FD_ZERO(&rfds);
FD_SET(fd_button,&rfds);
while(1)
{
retval =select(fd_button+1,&rfds,NULL,NULL,NULL);
if(retval<0)
{
perror("failed!\n");
break;
}
else if(0 == retval)
{
printf("timeout!\n");
continue;
}
else if(FD_ISSET(fd_button,&rfds))
{
read(fd_button, &status_button,sizeof(status_button));
}
if (status_button == KEY1)
{
static int i=1;
switch(i%3)
{
case 1:
ioctl(led_fd,LED_ON,0);
sleep(2);
i++;break;
case 2:
ioctl(led_fd,LED_BLINK,0);
i++;break;
case 0:
ioctl(led_fd,LED_OFF,0);
i++;break;
}
}
if (status_button == KEY2)
{
static int j=1;
switch(j%3)
{
case 1:
ioctl(led_fd,LED_ON,1);
sleep(2);
j++;break;
case 2:
ioctl(led_fd,LED_BLINK,1);
j++;break;
case 0:
ioctl(led_fd,LED_OFF,1);
j++;break;
}
}
if (status_button == KEY3)
{
static int k=1;
switch(k%3)
{
case 1:
ioctl(led_fd,LED_ON,2);
k++;break;
case 2:
ioctl(led_fd,LED_BLINK,2);
k++;break;
case 0:
ioctl(led_fd,LED_OFF,2);
k++;break;
}
}
if (status_button == KEY4)
{
static int n=1;
switch(n%3)
{
case 1:
ioctl(led_fd,LED_ON,3);
n++;break;
case 2:
ioctl(led_fd,LED_BLINK,3);
n++;break;
case 0:
ioctl(led_fd,LED_OFF,3);
n++;break;
}
}
}
close(fd_button);
close(led_fd);
return 0;
}
还有,对于宏定义 KEY1,KEY2,KEY3,KEY4,我们可以定义成1<<1 ,1<<2, 1<<3 , 1<<4,这样会更加直观的体现每个按键所对应的位。
二、select()函数:
测试程序中用到了select()函数。我们来对其进行详细介绍吧!
- FD_ZERO(fd_set *) 清空一个文件描述符集合;
- FD_SET(int ,fd_set *)将一个文件描述符添加到一个指定的文件描述符集合中;
- FD_CLR(int ,fd_set*) 将一个给定的文件描述符从集合中删除;
- FD_ISSET(int ,fd_set* )检查集合中指定的文件描述符是否可以读写。 若可读写,返回大于0的数。
(1)执行fd_set set;FD_ZERO(&set);则set用位表示为 0000,0000 。
(2)若fd = 5 ,则执行 FD_SET(fd,&set)后,set变为 0001,0000 (第5位置为1)
(3)执行select(6,&set,0,0,0)阻塞等待
(5)struct timeval* timeout 是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
(1)当监视的相应的文件描述符集中满足条件时,比如说读文件描述符集中有数据到来时,内核(I/O)根据状态修改文件描述符集,并返回一个大于0 的数。
(2)当没有满足条件的文件描述符,且设置的timeval 监控时间超时时,select函数会返回一个为0的值。