记得以前学习单片机,首先是流水灯然后是按键、中断、定时器…… 最近几年键盘手机也是渐渐的被触摸屏幕的手机所取代。SIN210开发板上有一块FT液晶屏,并配有一个电阻触摸屏,所以一直没鼓捣按键,今天参考了下SINLINX公司提供的教程,来鼓捣一下按键。。。
SIN210开发板上具有8个按键,电路图如下:
图9-1:User Key
EINT0~7 就是对应的和CPU的GPH0_0 ~ GH0_7 如下图所示:
图9-1-1:User Key
开发板上的按键,是借助linux的input子系统进行的修改。
一、驱动
(1)编辑/kernel/drivers/input/keyboard/s3c-gpio_keys.c 文件
(2)修改 s3c_gpio_keys 结构体
struct s3c_gpio_key s3c_gpio_keys[]= { { .pin = S5PV210_GPH0(0), .eintcfg = 0X0f<<0, .inputcfg = 0<<0, .eint = IRQ_EINT0, }, /*剩下的7个,与这个类似,在这里就不重复了*/ }; }
(3)编辑kernel/arch/arm/mach-s5pv210/mach-smdkv210.c文件
(4)编辑 gpio_buttons 结构体,定义按键的键值
static struct gpio_keys_button gpio_buttons[] = { { .gpio = S5PV210_GPH0(0), .code = 231, .desc = "CALL", .active_low = 1, .wakeup = 1, },
/*剩下的7个,与这个类似,在这里就不重复了*/
};
(5)查询键值请参看文件/kernel_smdkv210/include/linux/input.h
(6)编辑完成后,重新编译内核即可.
二、应用(主要就是写个简单的程序来通过Qt来显示哪个键被按下)
(1)新建一个Qt工程
(2)新建key.c key.h led.c文件如下
//key.c #include "key.h" #include #include #include #include #include #define NOKEY 0 int key_fd=0; struct input_event t; int key_open(const char*devname) { key_fd=open(devname,O_RDWR); printf("KEY driver is ok\n"); if(key_fd<0) { printf("open device %s failed.\n",devname); return -1; } return 0; } int key_read() { if(read(key_fd,&t,sizeof(t))==sizeof(t)) { if(t.type==EV_KEY) if(t.value==0 || t.value==1) { switch(t.code) { case 231: printf("S1 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x11:0x10); break; case 139: printf("S2 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x21:0x20); break; case 158: printf("S3 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x31:0x30); break; case 107: printf("S4 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x41:0x40); break; case 102: printf("S5 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x51:0x50); break; case 30: printf("S6 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x61:0x60); break; case 48: printf("S7 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x71:0x70); break; case 46: printf("S8 %s\n",(t.value)?"Pressed":"Released"); return ((t.value)?0x81:0x80); break; default: break; } } } } int key_close(void){ if(key_fd) close(key_fd); } /************************************/ //led.c #include "key.h" #include #include #include #include #include #define IOCTL_LED_ON 0 #define IOCTL_LED_OFF 1 int led_fd=0; int led_open(const char*devname){ led_fd=open(devname,O_RDWR); printf("LED driver is ok\n"); if(led_fd<0){ printf("open device %s failed.\n",devname); return -1; } return 0; } int led_ioctl(const int no,const int sw){ //led_fd=open("/dev/led",O_RDWR); int num=no; ioctl(led_fd,sw,num); printf("LED%dis open\n",num); return 0; } int led_close(void){ if(led_fd) close(led_fd); } /*********************************/ //key.h #ifndef KEY_H #define KEY_H #ifdef __cplusplus extern "C" { #endif extern int key_open(const char *devname); extern int key_read(); extern int key_close(void); extern int key_fd; extern int led_open(const char *devname); extern int led_ioctl(const int no,const int sw); extern int led_close(void); extern int led_fd; #ifdef __cplusplus } #endif #endif
用到了一个Qt的QSocketNotifier。
QSocketNotifier 用来监听系统文件操作,将操作转换为Qt事件进入系统的消息循环队列。并调用预先设置的事件接受函数,处理事件。一共存在3类事件:read,write,exception.
QSocketNotifier::Read 0 There is data to be read.
QSocketNotifier::Write 1 Data can be written.
QSocketNotifier::Exception 2 An exception has occurred. We recommend against using this.
通过QSocketNotifier来监听是否有按键按下的事件,通过槽和按键处理函数buttonOnclik()连接。
代码如下:
/*mainwindow.h*/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include#include namespace Ui { class MainWindow; //class QSocketNotifier; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected: void paintEvent(QPaintEvent* e); private slots: void buttonClicked(); private: int k_fd; int led_fd; QSocketNotifier* m_notifier; private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H //mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include#include #include "key.h" #define LED1 0 #define LED2 1 #define LED3 2 #define LED4 3 #define LED_ON 0 #define LED_OFF 1 //int led_fd; int mm_key=0,last_key=0; //int m_notifier; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); k_fd=key_open("/dev/input/event0"); if(led_fd==-1) QMessageBox::warning(this, tr("Error"), tr("Not Found /dev/led !")); led_fd=led_open("/dev/led"); if(k_fd==-1) QMessageBox::warning(this, tr("Error"), tr("Not Found /dev/input/event0 !")); m_notifier = new QSocketNotifier(k_fd, QSocketNotifier::Read, this); connect (m_notifier, SIGNAL(activated(int)), this, SLOT(buttonClicked())); } void MainWindow::buttonClicked() { mm_key=key_read(); if(mm_key!=last_key) { last_key=mm_key;update(); } } void MainWindow::paintEvent(QPaintEvent*) { switch(last_key) { case 0x11: ui->KeyDis->setText("S1 is Pressed0!"); led_ioctl(LED1,LED_ON); break; case 0x21: ui->KeyDis->setText("S2 is Pressed!"); led_ioctl(LED1,LED_OFF); break; case 0x31: ui->KeyDis->setText("S3 is Pressed!"); led_ioctl(LED2,LED_ON); break; case 0x41: ui->KeyDis->setText("S4 is Pressed!"); led_ioctl(LED2,LED_OFF); break; case 0x51: ui->KeyDis->setText("S5 is Pressed!"); led_ioctl(LED3,LED_ON); break; case 0x61: ui->KeyDis->setText("S6 is Pressed!"); led_ioctl(LED3,LED_OFF); break; case 0x71: ui->KeyDis->setText("S7 is Pressed!"); led_ioctl(LED4,LED_ON); break; case 0x81: ui->KeyDis->setText("S8 is Pressed!"); led_ioctl(LED4,LED_OFF); break; } } MainWindow::~MainWindow() { led_close(); key_close(); delete ui; }
通过屏幕来显示那个按键被按下,具体显示如下:
图9-2-1:Qt-key显示
图9-2-2:Qt-key显示
图9-2-3:Qt-key显示
图9-2-4:Qt-key显示