Design of ARM matrix keyboard and its linux driver implementation

Publisher:心怀感恩Latest update time:2021-03-16 Source: eefocusKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

In embedded system development, keyboard is often used to realize human-computer interaction. This article introduces a method to directly use ARM's I/O port to expand the matrix keyboard. At the same time, taking the TQ2440 development board as an example, the hardware circuit connection and the corresponding Linux driver design method are explained in detail.


1 Introduction


ARM microprocessors have been widely used in industrial control, consumer electronics, communication systems and other fields. Matrix keyboard is a commonly used keyboard form, which designs the keys into M rows and N columns, so that a total of M+N signal lines are required, but M×N keys can be driven, which greatly saves I/O resources. This article introduces a method of using the GPIO port of the TQ2440 development board to expand a 5×4 matrix keyboard, and rearranges all the keys into the form of a handheld terminal keyboard for easy operation.


2. Hardware Design


This design expands a matrix keyboard with 5 rows and 4 columns, as shown in Figure 1. The row lines ROW1-ROW5 are connected to the interrupt pins EINT8, EINT9, EINT11, EINT13, and EINT14 of the S3C2440 [1]. These interrupt pins are connected to 10kΩ pull-up resistors to pull the interrupt pin level high to ensure that the interrupt will not be triggered when the key is idle. The column lines COL1-COL4 are connected to the ordinary I/O ports GPF3, GPF4, GPG7, and GPG10 of the S3C2440. The issue that needs to be noted here is: Make sure that the interrupts used by the row lines are not used by other Linux devices, otherwise it will cause the initialization of this driver or other drivers to fail.


Design of ARM matrix keyboard and its linux driver implementation


Considering the commonness and convenience of the keys of handheld terminal devices, only the first 18 keys of the matrix keyboard are taken and they are rearranged as shown in Figure 2. The Ent key has dual functions, namely confirmation function (short press) and power on/off function (long press), which will be implemented in the driver.


Design of ARM matrix keyboard and its linux driver implementation


3. Linux driver design for matrix keyboard


3.1 Keyboard driver overview


The driver is the interface between the operating system kernel and the hardware device. The device driver shields the application from the hardware details, allowing the application to operate the hardware device like operating an ordinary file [2]. The driver does not have a main function. It uses a module initialization function as its entry point, and it stops running after completing the initialization and waits for system calls.


The driver is part of the Linux kernel, so the Linux expression should be used in programming. First, define the column I/O port as an array: col_table[] = {S3C2410_GPF3, S3C2410_GPF4, ...}, and define the row I/O port as a structure:


button_irqs [] ={ {IRQ_EINT8,S3C2410_GPG0,S3C2410_GPG0_EINT8, 0,“R1″},


{IRQ_EINT9,S3C2410_GPG1,S3C2410_GPG1_EINT9, 1,”R2″},


…}.//interrupt number (irq), pin (pin), pin setting, serial number, name


The matrix keyboard is registered to the system as a Linux character device. We first register the matrix keyboard device to the system, including the device number, device name and file_operations structure; the member functions of the file_operations structure are the main content of the character device driver design. These functions will actually be called when the application performs Linux open(), write(), read(), close() and other system calls [3]. The user has no write operation on the keyboard, and the member functions of its file_operations structure are open(), read(), close(), and poll().


The interrupt registration and row and column initialization are implemented when the keyboard is opened (i.e. in the open() function). The interrupt registration includes: interrupt number, interrupt entry program, interrupt mode, interrupt name and code. The key statement is: request_irq (button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_FALLING, button_irqs[i].name, (void*)&button_irqs[i]). IRQ_TYPE_EDGE_FALLING means falling edge trigger. Then perform row and column initialization: set the row line as interrupt and enable pull-up. In Linux, its expression is:


s3c2410_gpio_cfgpin(button_irqs[i].


pin, S3C2410_GPIO_SFN2); //Set the i-th row pin to interrupt


s3c2410_gpio_pullup(button_irqs[i].


pin, 1); //Pull up the pin in row i


Set the column line to output and set it to low level. The statements are expressed in the same way. Due to space limitations, they are not listed here one by one.


The read() function is used to read data from the device. This function allows the program to enter sleep mode when no key is pressed. The key code is:


static DECLARE_WAIT_QUEUE_HEAD(button_waitq); //Generate a waiting queue head queue named button_waitq


static volatile int ev_press = 0; //Set to 1 to indicate a key is pressed


When ev_press is 0, execute the statement: wait_event_interruptible (button_waitq, ev_press), and the program will enter sleep mode. When ev_press is 1, copy the data from kernel space to user space. The key statement is:


copy_to_user(buff, (const void *) key_values, min(sizeof(key_values), count)); //buff is a pointer to user space, key_values ​​is a pointer to kernel space, and the last parameter is the number of bytes to copy from kernel space to user space. We take the minimum value between the actual size and the size specified by the user. Returns zero if the data is copied successfully; returns the number of bytes of data that were not copied successfully if an error occurs.


The close() function closes the matrix keyboard device and releases the registered interrupt. The key statement is: free_irq (button_irqs[i].irq, (void *) &button_irqs[i]).


The Poll() function implements polling. If there is no key data, the Linux poll_wait function is called to wait; if there is key data, the select function will return immediately.


3.2 Interrupt processing and keyboard scanning program


The name of the interrupt processing function is buttons_interrupt registered above. The specific program flow is shown in Figure 3. When a key is pressed, the row and column where the key is located is turned on. The low level of the column pulls down the level of the row, thereby triggering an interrupt. Then, enter the interrupt processing function. Due to the problem of key jitter, it is unreliable to determine that a key is pressed based on the triggering of an interrupt alone, so a timer is used to delay 10ms before entering the keyboard scanning function.


Design of ARM matrix keyboard and its linux driver implementation


The keyboard scanning program of this design adopts the method of determining the row first and then the column, and finally performs certain operations on the rows and columns to obtain the key value. First determine the row: scan row by row to determine whether there is a row pin at a low level. If so, save the row value (row). Continue to determine the column: set the low level column by column. When the column is pressed, the row will be low again, thereby determining the column (column). Then perform operations on the rows and columns: k=row*4+column, then each key of the matrix keyboard corresponds to the key number 0-19. After the keyboard layout is in the form shown in Figure 2, we only take the first 18 keys of the matrix keyboard (key numbers 0-17), and save the key value as k+1. For the Ent key, the length of time it is pressed distinguishes whether it is a confirmation function or a power on/off function. The pressing time is less than 0.5 seconds for the confirmation function, and the pressing time is greater than 1.6 seconds for the power on/off function. The time between 0.5 seconds and 1.6 seconds is considered an invalid operation. The timing method is:


If the line is still at a low level and the integer cnt is less than 1700: delay 1ms, cnt++; the pressing time is obtained according to the cnt value.


The power on/off function is saved as key number 18, key value 19.


4. Driver Testing


The test program belongs to the upper-level application program, and the keyboard operation can be realized by directly calling the interface provided by the keyboard driver. We call the open() function to open the matrix keyboard device, and then call the read() function to read the keyboard data and save it to the array defined by ourselves, and finally use the printf() function to display the test results.


This function was applied to my project, and the accuracy and response time of keyboard input met the design requirements.


5. Summary


This article introduces a method to expand the matrix keyboard directly from the ARM I/O port. It does not require the addition of other interface components, the design is fast and practical, and the driver is implemented under the Linux system, providing a solution for expanding the handheld terminal keyboard for ARM embedded devices.


Keywords:ARM Reference address:Design of ARM matrix keyboard and its linux driver implementation

Previous article:U-Boot transplantation for embedded systems based on S3C2410A
Next article:Several implementation methods of print function in ARM

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号