Several useful modules for C51 programming - keyboard scanning module

Publisher:Changsheng520Latest update time:2021-03-25 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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//Use AT89C52 for control

#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;bybySum+=pbyBuf[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;

}

}


Reference address:Several useful modules for C51 programming - keyboard scanning module

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?

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号