Hardware introduction:This article mainly implements a general keyboard framework, which can be easily changed to different keyboard functions. Here we have implemented two types of buttons, four independent buttons and four rows scan keyboards.
Four buttons are like this: four buttons respectively one end of the ground, the other end is connected to the pull resistance after the input of the microcontroller P1.0-P1.3 port; in this way, when the press the button, the microcontroller to the low level, when the single chip microcomputer is released, the input signal of the upstream resistor is fixed to a high level.
4*4 keys: the input signal of a row is equipped with a mulberry resistance. When no buttons are pressed, the system is high by default. The column scanning signal line is directly connected to the key column line. When the key is read, the single-chip microcomputer provides a low-level signal (column-by-column scan) to read the line signal to determine which button is specific. The circuit diagram is roughly as follows:
In the figure, in is the column scanning line of the keyboard, and out is the line signal line of the output of the keyboard. Scan can also scan by line. At this time, in is the line of scanning, and the column signal line output by the out button. My program scans by column (the principle of row and column scanning is the same, but the row and column are exchanged ).
At the same time, the scanf function with 4*4 buttons is transplanted, and the previously implemented printf function is also added, A complete system that can interact with input and output is built. The printf function of the liquid crystal adds a function to return the lattice. You can return the lattice and re-enter the input when an incorrect number is entered.
Program Implementation:
First, let's talk about the program structure. The program implements a cyclic queue to store the pressed key values. It can save the latest four buttons to prevent key loss; the program uses the interrupt mode to press the key. Every 16 ms (with an interval interrupted by the watchdog), the program reads the key once to determine whether the key value is valid. If the value is valid, it is placed in the queue, waiting for reading.
Implementation of cyclic queue: array is used. To determine whether the queue is full, the last element of the array is not used to store the key value:
/********************* Macro definition **************** *******/# DefineKeysize 4// Key value queue# DefineLength keysize + 1// Number of queue array elements /********************************* ******************//******************** ** key-value queue ********************* // keysize (length-1) key code loop queue occupies one element SpaceCharKey [length];
Function: when the team is full, the team leaves the team to save the latest four buttons.
VoidAddkeycode (CharKeycode ){If(Rear + 1) % length = front)// Full team{Front = (front + 1) % length;// Team out} Key [rear] = keycode; Rear = (Rear + 1) % length ;}
Dispatch function: the dispatch function is the function that reads keys for calling in other places.
CharReadkey (){CharTemp;// If (Rear = front) return '\ 0'; // No buttonsWhile(Rear = front); temp = Key [Front]; front = (front + 1) % length;ReturnTemp ;}
Keyprocess: this function is the keyboard processing function, which needs to be called every 10 ms-20 ms time. Here it is put into the 16 Ms interrupt of the watchdog timer. The function flow chart and function content are as follows:
Void Keyprocess (){ Static char KeyValue = 0xff; // Key ID, key value Static char Addedflag = 0; // Add queue flag Char Keyval = getkey (); If (Keyval = 0xff) // No buttons {KeyValue = 0xff; addedflag = 0; Return ;} If (KeyValue = 0xff) // No buttons in the previous status {KeyValue = keyval; Return ;} If (KeyValue! = Keyval) // Different from the previous button {KeyValue = keyval; // Save the new key value Return ;} If (Addedflag = 1) // Added to the queue { Return ;} Addedflag = 1; addkeycode (keycode [keyval]);}
This function completes the button determination and compares it with the previous one to determine whether the button is valid. Then, it determines whether to save the button based on whether the button has been stored in the queue.
This function needs to be interrupted once every 10 ms-20 ms:
# PragmaVector = wdt_vector _ interruptVoidWdt_isr () {keyprocess ();}
This is a scheduled interruption at an interval of 430 monitoring dogs. It is set to interrupt every 16 Ms:
Wdtctl = wdt_adly_16;// The Internal timer mode of the watchdog is 16 Ms.Ie1 | = wdtie;// Enable watchdog interruption
The getkey function is called in keyprocess. This function needs to be provided by the user to meet special key requirements. Here we provide two instances: four keys and four matrix keyboards.
The getkey function of the four buttons:
CharGetkey (){If(P1in & 0x0f) = 0x0e ){Return0 ;}If(P1in & 0x0f) = 0x0d ){Return1 ;}If(P1in & 0x0f) = 0x0b ){Return2 ;}If(P1in & 0x0f) = 0x07 ){Return3 ;}Return0xff ;}
Here, the original key value of each key is output, and 0xff is output if no key is provided. This is also required when the getkey function is provided. If no key is set, 0xff is returned.
Translate the corresponding original key value into the required key code and use the array keycode:
CharKeycode [] ="0123";/* When there are 4 buttons */
Here it is converted into an ascii code output, which can be changed as needed.
4*4 matrix keyboard: getkey:
CharGetkey () {p1dir | = 0xf0;// Output with four digits in heightFor(IntI = 0; I <4; I ++) {p1out = 0xef <I;For(IntJ = 0; j <4; j ++ ){If(P1in & (0x01 <j) = 0 ){Return(I + 4 * j );}}}Return0xff ;}
The column-based scan is used. You can change the scan mode to another scan mode. You only need to obtain the original key value. If no key is set, 0xff is returned.
Keycode, translated into ASCII code:
CharKeycode [] ="0123456789 abcdef"
At this point, the normal keyboard program ends. You only need to add key. C to the call, including key. h. After keyinit is called, you can use the normal read key. I will not go into detail here.
Scanf port: For scanf port transplantation, an ascii code entry must also have a carriage return key. Only in this way can scanf be used to input data, in this case, when the input data is incorrect, you can modify the backspace and press a backspace key.
Keyboard structure:
1 |
2 |
3 |
Return |
4 |
5 |
6 |
Retained |
7 |
8 |
9 |
Retained |
Retained |
0 |
Retained |
Enter |
Hold key with character '\ 0', press ENTER' \ n' ungete '\ B'
So: keycode:
CharKeycode [] ="123 \ b456 \ 000789 \ 0 \ 0000 \ 0 \ r";/* 4*4, scanf port */
When \ 0 is followed by a number in the string, '\ 000' must be used; otherwise,C LanguageThe compiler considers that \ 0 and the number following it as a character.
To port scanf, You need to implement the getchar function. Here it is similar to the previous getchar function and put it in the getchar. c file. The content is as follows:
# Include <Stdio. h> # Include "Key. H" # Define Line_length 20 // The size of the row buffer, which determines the maximum number of characters entered per line/* Special ASCII Code definition in the standard terminal device. Do not modify it */ # Define Inbacksp 0x08 // ASCII <-- (Return key) # Define Indelete 0x7f // ASCII <del> (DEL key) # Define Ineol '\ R' // ASCII <CR> (enter key) # Define Inlf '\ N' // ASCII <LF> (Press ENTER) # Define Inskip '\ 3' // ASCII control-C # Define Ineof '\ X1a' // ASCII Control-Z # Define Outdelete "\ X8 \ X8" // VT100 backspace and clear # Define Outskip "^ C \ n" // ^ C and New Line # Define Outeof "^ Z" // ^ Z and return EOF Int Getchar (){ Static char Inbuffer [line_length + 2]; // Where to put chars Static char PTR; // Pointer in buffer Char C; While (1 ){ If (Inbuffer [PTR]) // If the buffer zone contains characters Return (Inbuffer [PTR ++]); // Returns characters one by one. PTR = 0; // The buffer pointer returns to zero until the sending is complete. While (1) // If there are no characters in the buffer, wait for the characters to be entered. {C = readkey (); // Waiting to receive one character = key to porting If (C = ineof &&! PTR)// = EOF = Ctrl + z { // Valid only when other characters are not entered Printf (outeof ); // Display the EOF on the terminal Return EOF; // Return EOF (-1) } If (C = indelete | C = inbacksp) // = Return or delete key = { If (PTR) // Buffer Value {PTR --;// Remove a character from the buffer Printf (outdelete ); // At the same time, the display also deletes a character }} Else if (C = inskip) // = Cancel the key Ctrl + c = {Printf (outskip ); // Terminal display jumps to the next line PTR = line_length + 1; // = 0 Terminator = Break ;} Else if (C = ineol | C = inlf) // = '\ R' press ENTER =' \ n' press ENTER {Putchar (inbuffer [PTR ++] ='\ N' ); // Terminal line feed Inbuffer [PTR] = 0; // Add the terminator (null) at the end) PTR = 0; // Clear the pointer Break ;} Else if (PTR <line_length) // = Normal character = { If (C> = '' ) // Delete characters earlier than 0x20 {// Save to the buffer zone Putchar (inbuffer [PTR ++] = C );}} Else // The buffer is full. {Putchar ( '\ 7' ); // = 0x07 beep, PC echo }}}}
Here is a detailed function that supports backspace and other keys.
You can simplify it:
IntGetchar (){ReturnReadkey ();}
To implement scanf call, you also need to set it. For detailed settings, refer to: MSP430 library <4> transplantation of printf and scanf functions; set the library to cLib; in option-General option-library configuration.
In this way, the scanf port of the keyboard is completed. to use it, you only need to include the stdio. h file, and then initialize the keyboard.
Example:
Here, the example implements simple interaction between the keyboard and the LCD. When the keyboard inputs data, the LCD is displayed normally, just like the keyboard and the screen during C language debugging. Of course, there is no such richness.
The LCD part uses the original program. Here, in order to support backspace when input errors occur, the original printf function is added with backspace support. For more information, see <4> transplantation of printf and scanf functions (updated) in the MSP430 library ).
Program Files (lcd12864.c, printf. c) add the file lcd12864.h. After the LCD is initialized, the printf can be used to output the content to be displayed to the LCD.
Keyboard: Add key. c, including key. h, add getchar. c. initialize the keyboard in the program. Then set the Lib used as cLib. For specific settings, see <4> printf and scanf functions of the MSP430 library. Then you can use the keyboard and LCD to complete simple interaction with the 430 microcontroller.
For more information, see the sample project and Main. C.
# Include<Rjx16x. h># Include<Stdio. h># Include"Lcd12864.h"# Include"Key. H"LongA;VoidMain (Void){// Stop watchdog timer to prevent time out ResetWdtctl = wdtpw + wdthold; clkinit (); lcdinit (); keyinit (); _ Eint ();While(1) {printf ("Enter a number :"); Scanf ("% LD", & A); printf ("The entered number is: % lD", A); _ Nop ();}}
In this way, you can use a keyboard to input data to the single-chip microcomputer. At the same time, you can easily know whether there is a problem with the data input.
The keyboard library is here. You are welcome to discuss any shortcomings.