The keyboard scanning module has two working modes, one is automatically called by the clock module, and the other is called by the programmer.
1) Automatically called by the clock module
Include the clock module implementation file (Timer.h) and the keyboard scanning module implementation file (KBScan.c) into the project, and add the TIMER_KBSCANDELAY macro in the Config.h file. The clock module automatically counts the clock interrupts, and when the value defined by the TIMER_KBSCANDELAY macro is reached, the function KBScanProcess() in the keyboard scanning module is automatically called to perform keyboard scanning. In other words, the value of this macro can determine the time to de-jitter the key.
The user should provide two callback functions OnKBScan() and onKeysPressed(). In the OnKBScan function, the keyboard is scanned and the scan code is returned. The scan code type is BYTE by default. When the keyboard size is large and BYTE cannot completely contain the keyboard information, the macro KBVALUE can be redefined in the Config.h file as follows:
#define KBVALUEWORD
In this way, you can use 16-bit keyboard scan codes. If the requirements are not met at this time, you can define the keyboard scan code as a structure, but doing so will increase the amount of code and consume more RAM resources, so it is not recommended.
The scanning module calls OnKBScan to obtain the scan code, and calls the user-definable macro IsNoKeyPressed to determine whether a key is pressed. The default implementation of IsNoKeyPressed is as follows:
#define IsNoKeyPressed(x)((x) == 0x00)
That is, when OnKBScan returns a scan code of 0, it is considered that no key is pressed. If the scan function returns other non-zero scan codes as scan codes for no key pressed, the implementation of the IsNoKeyPressed macro can be redefined in the Config.h file.
When the keyboard scan code is 8 bits (default value), the corresponding scan function is:
BYTE OnKBScan()
When the scanning module detects a key being pressed after software debounce, it will call another callback function onKeysPressed. The function declaration should be as follows:
void onKeyPressed(BYTE byKBValue, BYTE byState)
The type of the parameter byKBValue is BYTE, which is the default value. If other types of scan codes are used, this parameter will be changed to the corresponding type. This value is returned by OnKBScan. Another parameter byState is usually zero. But when the user defines the macro KBSCAN_BRUSTCOUNT in Config.h, and a key on the keyboard is pressed and held, the scan module counts its own calls (note that this is different from the TIMER_KBSCANDELAY macro. TIMER_KBSCANDELAY calls the scan module after the clock interrupts a sufficient number of times, while KBSCAN_BRUSHCOUNT is the number of times the scan module itself is called). When KBSCAN_BRUSTCOUNT is reached, the scan module calls onKeysPressed. At this time, the meaning of the first parameter remains unchanged, and byState becomes 1. At the same time, the counter is reset. After a period of time, onKeysPressed is called with a byState value of 3. In this way, it is very convenient to implement multi-function keys or detect whether a key has been pressed for a long time.
2) Called by the user
The scanning module is called by the user in the program instead of being called by the clock interrupt. The rest is the same as method 1.
Notice:
1) The function KBScanProcess is a non-blocking function. It will return in a very short time and wait for the opportunity to be assigned to it for execution again.
2) The function KBScanProcess is executed outside the clock interruption. Its process can be interrupted by any interruption, but it will not affect the system operation.
3) The maximum value of byState is 250, after which it is reset to zero.
Now let's take a look at some examples to illustrate how to use the above modules.
Hardware environment description:
In order to control a lamp, the microcontroller needs to provide a switch quantity for the control function. The external interface circuit is not described here. It only explains that when the P10 pin of the microcontroller is at a high level, the lamp is off, and when the P10 pin is at a low level, the lamp is on.
It can be controlled by sending commands through the serial port of the computer, or manually controlled by a button (the push button is not a self-locking button) (the button is connected to the P11 pin. When the button is not pressed, the P11 level is high. When the key is pressed, the pin level is connected to a low level). When using the button for manual control, a notification needs to be sent to the computer.
The serial communication command is as follows:
The data packet has 0xff as the header, is 4 bytes long, the second byte is the command code, the third byte is the data, and the last byte is the check bit.
The command and data codes have the following combinations:
(Sent from computer to microcontroller)
0x100x01: The computer controls the light to turn on. (The data bit can be a non-zero value)
0x100x00: The computer controls the light to go out.
(MCU sends to computer)
0x110x01: The MCU executes the control instruction normally and returns. (The data bit can be a non-zero value)
0x110x00: The microcontroller cannot execute the control instruction normally, or the control instruction is wrong (unknown data packet or check error, etc.).
0x120x01: Manual control light on. (Data bit can be non-zero value)
0x120x00: Manual control light off.
Create a project:
Create a folder Projects on the hard disk, and create a Common folder and an Example folder under Projects. Copy the header files and implementation files of each module to the Common folder (this file organization structure is recommended, and other projects can also be created under Projects, and each project shares the code in the Common folder).
Start KeilC IDE, create a new project under Example, and include the implementation files of each module into the project.
Create an Output folder under the Example folder, change the project settings, and use Output as the output folder for output files and List files (it is recommended to use such a structure. When saving the project file, you can simply delete the contents of the Output folder without accidentally deleting useful project files).
Create the project configuration header file Config.h and the project main file Example.c, and add the Exmaple.c file to the project.
Enter the code:
The specific code writing process is omitted. Below is the final Config.h file and Example.c file.
//
//file:Config.h
//
#ifndef_CONFIG_H_
#define_CONFIG_H_
#include #include "../Common/Common.h" //Use custom data types #defineTIMER_RELOAD922 //11.0592MHz crystal, 1ms interrupt period #defineTIMER_KBSCANDELAY40 //40ms re-detection of key status, i.e. 40ms debounce #defineSCOMM_AsyncInterface //Use asynchronous communication service #defineIsPackageHeader(x)((x)==0xff)//Judge whether the package header is 0xff #defineIsPackageTailer(x,y,z)((y)<=(z))//Judge whether the length of the package is sufficient #endif //_CONFIG_H_ // //file:Example.c // #include #include "../Common/Common.h" #include "../Common/Timer.h" #include "../Common/Scomm.h" #include "../Common/KBScan.h" BITgbitLampState=1; //The status of the light, the default is off static void Initialize() { InitTimerModule(); //Initialize the clock module InitSCommModule(0xfd,TRUE); //Initialize the communication module, 11.0592MHz crystal oscillator, //The baud rate is 19200 EA=1; //enable interrupt } void main() { Initialize(); // Initialization while(TRUE) //Main loop { ImpTimerService(); //Implement clock interrupt services, such as keyboard scanning AsyncRecePackage(4); //Receive a 4-byte data packet } } //Respond to clock interrupt events outside the interrupt voidOnTimerEvent() { //donothing } //Control external lights static void TriggerLamp(BITbEnable) { P10=~bEnable; //need reverse control } //Key scan callback function BYTEKBScan() { BITb; P11=1; //Pull the pin level high before reading b=P11; //Read pin status return~b; //Data inversion as scan code } //Calculate checksum static BYTECalcCheckSum(BYTE* pbyBuf, BYTEbyLen) { BYTE by, bySum = 0; for(by=0;by return0–bySum; } //Receive keyboard message callback function void onKeyPressed(BYTE by value, BYTE by State) { BYTEby[4]; if(byState==0) { switch(byvalue) { case0x01: gbitLampState=~gbitLampState; //Invert the light status TriggerLamp(gbitLampState); //Execution control by[0]=0xff; //Construct data packet by[1]=0x12; by[2]=(BYTE)gbitLampState; by[3]=CalcCheckSum(by,3); //Calculate the checksum SendPackage(by,4); //Send data packet break; //Process other scan codes default: break; } } //Received data packet callback function void OnRecePackage(BYTE* pbyBuf, BYTE byBufLen) { BYTEby[4]; by[0]=0xff; by[1]=0x11; if(byBufLen!=4||pbyBuf[3]!=CalcCheckSum(pbyBuf,3)) { by[2]=0; by[3]=CalcCheckSum(by,3); SendPackage(by,4); //Processing length or checksum is incorrect } switch(pbyBuf[1]) { case0x10: gbitLampState=(BIT)pbyBuf[2]; TriggerLamp(gbitLampState); by[2]=1; by[3]=CalcCheckSum(by,3); SendPackage(by,4); //Send successful execution notification break; default://Unknown command by[2]=0; by[3]=CalcCheckSum(by,3); SendPackage(by,4); //Send the notification that the execution was not successful break; } }
Previous article:A New Ultrasonic Distance Measurement System Based on C8051
Next article:How to call each other between C51 file and assembly language file?
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- Award-winning live broadcast: Microchip&avnet series live broadcast third collection
- [Vicor White Paper Recommendation] Power Averaging Design Method with Voltage Regulation: Ideal Power Supply Solution for Pulse Loads
- Bear Pie Huawei IoT Operating System LiteOS Kernel Tutorial - IoT-Studio Introduction and Installation
- How to use C language to find the corresponding value in the table in the microcontroller
- FPGA Implementation of Digital Down-Conversion
- Wireless bridge dedicated to video transmission
- Implementation Method of Software Serial Interface (SCI) Based on C2000
- Ultra-wideband positioning applications
- Share a book: Crazy STM32 practical lectures
- Design and implementation of Ethernet MII interface expansion based on FPGA