linux应用程序:键盘双击与长按识别及串口通讯 Home » 编程开发 » linux应用程序:键盘双击与长按识别及串口通讯 以下程序是结合我的驱动编写的应用层程序,双击,单击,长按都能正确识别,效果很好,不知有哪位大侠有更好的结构和算法程序?想借此抛砖引玉,也愿高手们修改指正!QQ:26451602. /*读取键值,控制LED灯亮。0x80-0x85:灭1-6号灯。0x00-0x05:点亮1-6号灯。键值:1-6.修改记录: 2009-10-26: 依据阿潘要求,改为刚按下/按住/释放都要给应用层信号。修改标志:ZMF091026*/#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/select.h>#include <sys/time.h>#include <errno.h>#include <signal.h>#include <pthread.h>#include "sysconfig.h"#include "powercontrolboard.h"/* keyflag: bit4:y/n longkey; bit0:y/n quickkey; bit1:quickkey valid; bit5: key valid; *//* keyflag: bit8-bit11: pressed key num:1-15 */#defineQUICKKEYbit 0#defineQUICKKEYVALbit 1#defineLONGKEYbit 4#defineKEYVALIDbit 5 volatile key_reg_t keyregdat; pthread_t g_LedCheckThreadId;intledrpm_key_reg(int keyfd){volatile int ret, key_val,keyflag=keyregdat.key_flag;ret=read(keyfd, (char *)&key_val,sizeof(key_val));if (ret<0){perror("ledrpm_key_reg:read");goto ERRRT; }if(ret==0)return 0;/* 非阻塞读键盘返回0*/printf("button%x/n",key_val);if(key_val < 0x1000){ /* 初始值处理 */if(key_val==keyregdat.keybuf[0]){SETBIT(keyflag, QUICKKEYVALbit);}else{CLRBIT(keyflag, QUICKKEYVALbit);keyregdat.press_holdtime=0;keyregdat.keybuf[1]=keyregdat.keybuf[2]=0;keyregdat.keybuf[0]=key_val;}}else if (key_val >= 0x2000){ /* 保持值处理 */if(keyregdat.keybuf[0]==key_val-0x2000){keyregdat.keybuf[1]=key_val;keyregdat.press_holdtime++;keyregdat.interval_time=14;}else goto ERRRT;}else{ /* 释放值处理 */if(keyregdat.keybuf[0]==key_val-0x1000){ /*释放值和初始值一样 *//* 先判断是否是长按键 */if (keyregdat.press_holdtime>=21){ CLRALLBIT(keyflag);SETBIT(keyflag, LONGKEYbit);keyflag &=0xf0ff;keyflag |= ((keyregdat.keybuf[0]&0x000f)<<8);memset((char *)&keyregdat, 0, sizeof(key_reg_t));keyregdat.interval_time=14;goto RIGHTRT;}else { /* 不是长按键 */keyregdat.press_holdtime=0;if (keyregdat.keybuf[2]==0){ /* 若是第一次按下,则不判断是否是双击键 */keyregdat.keybuf[2]=key_val;gettimeofday((struct timeval *)&(keyregdat.tv1), NULL);keyregdat.interval_time=7;goto RIGHTRT;}}/*以下判断是否是双击键 */if(keyregdat.keybuf[2]==key_val){ /* 第二次按下释放值一样 */gettimeofday((struct timeval *)&(keyregdat.tv2), NULL);ret=1000000*(keyregdat.tv2.tv_sec-keyregdat.tv1.tv_sec)+keyregdat.tv2.tv_usec-keyregdat.tv1.tv_usec;if(ret<1000000 && ret>0 && ISSETBIT(keyflag, QUICKKEYVALbit)){CLRALLBIT(keyflag);SETBIT(keyflag, QUICKKEYbit);keyflag &=0xf0ff;keyflag |= ((keyregdat.keybuf[0]&0x000f)<<8);memset((char *)&keyregdat, 0, sizeof(key_reg_t));keyregdat.interval_time=14;}else {CLRALLBIT(keyflag);memset((char *)&keyregdat, 0, sizeof(key_reg_t));keyregdat.interval_time=14;}}else goto ERRRT;/* 初始键值相同,不同释放值*/}else goto ERRRT; /* 释放值和初始值不一样,则错误 */}RIGHTRT:keyregdat.key_flag=keyflag;return 0;ERRRT:CLRALLBIT(keyflag);memset((char *)&keyregdat, 0, sizeof(key_reg_t));keyregdat.interval_time=14;keyregdat.key_flag=keyflag;return -1;}void timer1s1_handler(int signo){if(keyregdat.interval_time <14){if(++keyregdat.interval_time>=14){memset((char *)&keyregdat, 0, sizeof(key_reg_t));keyregdat.interval_time=14;printf("clear keyregdat!!/n");}}}void init_sigaction(void){struct sigaction act;act.sa_handler=timer1s1_handler;act.sa_flags=0; //SA_ONESHOT|SA_NOMASK; /* 只能等于0,否则如后面结果是定时到一次就退出 */sigemptyset(&act.sa_mask);if(sigaction(SIGPROF, &act, NULL)==-1)perror("signaction");}void init_time(void){struct itimerval value;value.it_value.tv_sec=0;value.it_value.tv_usec=200000; /* 定时时间改小一点,这样平均误差小一点 */value.it_interval=value.it_value;setitimer(ITIMER_PROF, &value, NULL);}void * ledrpm_fun(void * pa){int led_fd,key_fd,conf_fd,fifo_fd;unsigned char write_value[6]={0x81,0x02,0x83,0x04,0x05,0x06};char dataptr[12];char * p[4];char read_value[4]={5,5,5,5};int i,ret,key_value;i=key_value=0;key_fd=open(KBDFILE,O_RDONLY|O_NONBLOCK, S_IRWXU|S_IRWXG|S_IROTH);if(key_fd<0){perror("cann’t open device /dev/keybutton");exit(1);}led_fd = open(LEDFILE, O_RDWR|O_NONBLOCK, S_IRWXU|S_IRWXG|S_IROTH);if (led_fd < 0) { perror("cann’t open device /dev/ledrpm "); exit(1);}ret = write(led_fd, write_value,4);if (ret < 0) { perror("first write led ");}conf_fd = open(CONFIGFILE, O_RDWR|O_CREAT|O_NONBLOCK, S_IRWXU|S_IRWXG|S_IROTH);if (conf_fd < 0)perror("cann’t open config file:");else{i=lseek(conf_fd, 0, SEEK_SET);if(i==-1)perror("lseek");if((i=read(conf_fd, dataptr, 12)) != 12 ){perror("cann’t read data to dataptr!");printf("read num:%d /n", i);}else{for (i=0; i<4; i++){p[i]=strtok((char *)(dataptr+i*3)," "); // 分割空格字符printf("%s ", p[i]);write_value[i]=strtoul(p[i],NULL,16); // 转成无符号整型}printf("/n write_value:%x,%x,%x,%x /n",write_value[0],write_value[1],write_value[2],write_value[3]);}}ret = read(led_fd, read_value, 4);if(ret==-1){printf("init read led1-4 error!!!/n");exit(1);}else{printf("init read led1:%d,led2:%d,led3:%d,led4:%d *_*/n", read_value[0],read_value[1],read_value[2],read_value[3]);sleep(3);if ((ret=write(led_fd, write_value,4)) == -1) printf("second write led return:%d /n", ret);}init_sigaction();init_time(); for (;;) {if(ledrpm_key_reg(key_fd) == -1)perror("ledrpm_key_reg");if(keyregdat.key_flag & 0x01){ret=(keyregdat.key_flag&0x0f00)>>8;printf("You pressed quick button:%d/n",ret);if(ret>=1 && ret<=6 ){write_value[ret-1] ^=(1<<7);//if(write(led_fd, &write_value[ret-1],1)==-1)if(ioctl(led_fd, write_value[ret-1],1)==-1)printf("write led%d error!!!/n",ret);else{printf("write led%d successful*_* /n",ret); fifo_fd=0;/*if(fifo_fd=open(RPM_FIFO,O_WRONLY|O_NONBLOCK,0755) < 0)perror("fifo write open");if(write(fifo_fd,&write_value[ret-1],1)<0 && errno != ENXIO)perror("fifo write"); else printf("write fifo:0x%x success/n",write_value[ret-1]);close(fifo_fd); */}keyregdat.key_to_sw=write_value[ret-1];g_PowerControlBoard.Start();sleep(1);g_PowerControlBoard.Pause();}keyregdat.key_flag=0;}else if(keyregdat.key_flag & 0x10){ret=(keyregdat.key_flag&0x0f00)>>8;printf("You pressed long button:%d/n",ret);keyregdat.key_flag=0;} }close(conf_fd);close(led_fd);close(key_fd);return 0;}int main(int argc, char** argv){/*if((mkfifo(RPM_FIFO,O_CREAT|O_EXCL|O_NONBLOCK)<0)&&(errno!=EEXIST))printf("cannot create fifoserver/n");if(errno!=EEXIST)printf("/ncreat:%s successful!/n",RPM_FIFO); */g_PowerControlBoard.InitComPort(COM1, B9600);g_PowerControlBoard.Pause();/*电源控制板串口通讯线程开始*/ /*LED检测线程,根据LED状态控制电源状态*/pthread_create((pthread_t *)&g_LedCheckThreadId, NULL, ledrpm_fun, NULL); while (true){sleep(1000);}if(unlink(RPM_FIFO)==-1)perror("unlink RPM_FIFO");return 1;} 当明知不可挽回,唯一补偿的方法就是怀念, 相关文章: qiweigo的专栏 HDU 3018 Ant Trip (欧拉路径) HDU 1116 POJ 1386 Play on Words(欧拉路径) HDU 1878 欧拉回路 (并查集+欧拉回路) POJ 1830 开关问题 高斯消元 POJ 2311 Cutting Game (sg函数) uva10474大理石在哪儿where is the marble? [经典面试题][百度]求比指定数大且最小的“不重复数” cq1042713261的专栏 BZOJ 3566 SHOI 2014 概率充电器 概率DP 你感兴趣的文章: POJ 30742676 数独DFS 为什么我运动后体重增加了? SQL中Delete语句表名不能用别名?! 理光THETA M15有微距吗? OPPO A71采用什么处理器? 哪些球员没有获得过世界杯冠军? 标签云: 亚洲高清电影在线, 免费高清电影, 八戒影院夜间, 八戒电影最新大片, 出轨在线电影, 午夜电影院, 在线影院a1166, 在线电影院, 在线观看美剧下载, 日本爱情电影, 日韩高清电影在线, 电影天堂网, 直播盒子app, 聚合直播, 高清美剧, 高清美剧在线观看 EhViewer-E站, E站, E站绿色版, qqmulu.com, qq目录网, qq网站目录,