The fourth day of playing 51 single chip microcomputer in 14 days -- want to see the wind, want to see the sea, and want to see how the IO port plays input

preface

Yang Zhi's single chip microcomputer column has many pictures and explanations, so as to reduce some pain on the way of learning single chip microcomputer

Although it's 14 days, I've been getting closer for half a month and only half. After looking at the knowledge behind me, I can't say much. I'm already buying STM32 board, and we still have to focus on 32~
It's been 14 days. It's for the little partners who read this article. Oh, read one article a day, get started easily, and don't be afraid of MCU anymore.
Because I am now, the head is the sea of algorithm problems, and the head is the homework project. Most of the time, I just finish the draft and don't send it out in time. Sorry, ha, forgive me 🌹🌹🌹

Independent key experiment

💒 Project code and effect

#include "reg52.h"

//Use the macro definition to define the key value pressed by each individual key
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0

typedef unsigned int u16;
typedef unsigned char u8;

//Define the pins to be manipulated according to the circuit diagram
sbit KEY1 = P3^1;
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;

//Define LED1 we want to operate
sbit LED1 = P2^0;

//Write the delay function for chattering elimination
void delay_10us(u16 ten_us) 
{
	while(ten_us--);
}


//Check whether the independent key is pressed, and press it to return to the corresponding key value
//mode = 0, press the key for single scan. The next scan can be triggered only after the key is released, so as to prevent multiple triggers after pressing it once 
//mode = 1, continuously scan the key, and the key value of the key will always be returned. The advantage is that it is very convenient to realize the continuous pressing operation 
u8 key_scan(u8 mode) 
{
	static u8 key = 1;
	
	//Support continuous scanning keys
	if(mode) key = 1;
	//Check whether the button is pressed normally
	if(key && (!KEY1 || !KEY2 || !KEY3 || !KEY4)) 
	{
		//Chattering elimination by delay function
		delay_10us(1000);
		//Modify the key value when mode = 0
		key = 0;
		if(!KEY1) 
			return KEY1_PRESS;
		else if(!KEY2)
			return KEY2_PRESS;
		else if(!KEY3)
			return KEY3_PRESS;
		else if(!KEY4)
			return KEY4_PRESS;	
	}else if(KEY1 && KEY2 && KEY3 && KEY4)//These keys are still high level, that is, no key is pressed
		key = 1;

	return KEY_UNPRESS; 
}

int main()
{
	//Accept the result returned by the key handling function 
	u8 key = 0;
	while(1) 
	{
		//At this time, the mode value passed in is 0, indicating a single scan key
		//Then save the value of the scan key in the variable key, and finally control the LED1 state through the if judgment statement. 
		key = key_scan(0);
		if(key == KEY1_PRESS) //Key 1 is indeed pressed
			LED1 = !LED1; 
	}
	return 0;
}

The effect of the experiment is: when you press K1 key, D1 indicator light is on, then press K1 key, D1 indicator light is off, and so on. It's not easy to put this picture, so don't put it~

🌟 Thorough inquiry

🌻 Elementary knowledge of keys

After reading the previous article, the little partner may have made it clear in his mind that if he wants to write the code, he mainly needs to be able to look at the circuit diagram. This problem is the same, which mainly depends on the circuit diagram, but the basic hardware knowledge also needs to be accumulated.


The above is the basic appearance of the keys on the 51 development board. I have an impression. It's good to know it when I see it.

The independent key circuit of 51 single chip microcomputer is composed of a pin of each key connected together and grounded, and the other pins of the key are connected to the IO port of the single chip microcomputer respectively.

Previous articles have introduced the output current of IO port to support the output function of other devices. The input function is used here~

Description of working principle:

One end of the key is grounded and the other end is connected with the IO port of the single chip microcomputer. At the beginning, assign a high level to the IO port (in fact, the default is high level), and then let the single chip microcomputer constantly check whether the IO port becomes a low level. When the key is closed, it is equivalent to that the IO port is connected to the ground through the key, that is, it becomes a low level. If the program checks that the input of the IO port becomes a low level, it indicates that the key is pressed and the corresponding instructions will be executed.


The following voltage signal diagram is more important because it involves chattering elimination
Generally, the switch used for the key is a mechanical elastic switch. When the mechanical contact is opened and closed, the voltage signal is shown in the following figure:

When the key switch is closed, it will not be connected stably immediately, and when it is disconnected, it will not be disconnected at once. Therefore, it is accompanied by a series of jitters at the moment of closing and opening. The jitter time is determined by the mechanical characteristics of the key, generally 5ms to 10ms. This jitter will certainly affect the accuracy of the experiment, so it is necessary to eliminate the jitter.
1, Hardware dithering
Hardware anti chattering is achieved by connecting a capacitor in parallel in the circuit, and the capacitance is 0.1uf.

Anti chattering principle: because the capacitor needs a certain time for charging and discharging, the charging and discharging time is greater than the jitter time, and the hardware anti chattering is realized in turn.
In order to make the circuit simpler, the development board does not configure this kind of circuit for anti chattering, so we need to carry out software anti chattering. In fact, the principle is the same, just ignore the jitter time.
2, Software dithering
① First set the IO port to high level (since the development board IO has pull-up resistance, the default IO is high level).
② Read the IO port level and confirm whether the key is pressed.
③ If the IO level is low, it will be delayed for several milliseconds. The delay here is to discover and ignore the jitter
④ Read the IO level again. If it is still low, it means that the key is pressed.
⑤ If it is not in the jitter range, execute the key control program.

Code design

How to write the code mainly depends on the circuit diagram

It can be seen from this figure that the control pins of the four independent keys are respectively linked to P31, P30, P32 and P33 of 51 single chip microcomputer, and the other end is connected to GND. As for the light we want to use as LED1, do you remember that it is controlled through P20 port.

When we demonstrate, we demonstrate through LED1. If you want to control the lighting or extinguishing of other LED lights by pressing the key, you only need to modify the execution logic after pressing the corresponding key.

Matrix key experiment

💒 Project code and effect

#include "reg52.h"
typedef unsigned int u16; //Redefine the default data type of the system
typedef unsigned char u8;
#define KEY_MATRIX_PORT P1 / / use the macro to define the matrix key control port
#define SMG_A_DP_PORT P0 / / use the macro to define the code port of the nixie tube segment

//The common cathode nixie tube displays segment code data of 0~F
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

/********************************************************************
***********
* Function name: delay_10us
* Function function: delay function, ten_ When us = 1, the delay is about 10us
* Input: ten_us
* Output: None
*********************************************************************
**********/
void delay_10us(u16 ten_us)
{
	while(ten_us--);
}

/********************************************************************
***********
* Function name: key_matrix_ranks_scan
* Function function: use the determinant scanning method to detect whether the matrix key is pressed, and press it to return the corresponding key value
* Input: None
* Output: key_value: 1-16, corresponding to S1-S16 key,
*					0: Key not pressed
*********************************************************************
**********/

u8 key_matrix_ranks_scan(void)
{
	u8 key_value=0;

	KEY_MATRIX_PORT=0xf7;//Assign 0 to the first column and 1 to the rest
	if(KEY_MATRIX_PORT!=0xf7)//Judge whether the keys in the first column are pressed
	{
		delay_10us(1000);//Debounce
		switch(KEY_MATRIX_PORT)//Save the key value after the key in the first column is pressed
		{
			case 0x77: key_value=1;break;
			case 0xb7: key_value=5;break;
			case 0xd7: key_value=9;break;
			case 0xe7: key_value=13;break;
		}
	}while(KEY_MATRIX_PORT != 0xf7);//Wait for the key to release

	KEY_MATRIX_PORT=0xfb;//Assign 0 to the second column and 1 to the rest
	if(KEY_MATRIX_PORT!=0xfb)//Judge whether the keys in the second column are pressed
	{
		delay_10us(1000);//Debounce
		switch(KEY_MATRIX_PORT)//Save the key value after the key in the second column is pressed
		{
			case 0x7b: key_value=2;break;
			case 0xbb: key_value=6;break;
			case 0xdb: key_value=10;break;
			case 0xeb: key_value=14;break;
		}
	}while(KEY_MATRIX_PORT!=0xfb);//Wait for the key to release

	KEY_MATRIX_PORT=0xfd;//Assign 0 to the third column and 1 to the rest
	if(KEY_MATRIX_PORT! = 0xfd)//Judge whether the keys in the third column are pressed
	{
		delay_10us(1000);//Debounce
		switch(KEY_MATRIX_PORT)//Save the key value after the third column key is pressed
		{
			case 0x7d: key_value=3;break;
			case 0xbd: key_value=7;break;
			case 0xdd: key_value=11;break;
			case 0xed: key_value=15;break;
		}
	}while(KEY_MATRIX_PORT!=0xfd);//Wait for the key to release

	KEY_MATRIX_PORT = 0xfe;//Assign 0 to the fourth column and 1 to the rest
	if(KEY_MATRIX_PORT! = 0xfe)//Judge whether the keys in the fourth column are pressed
	{
		delay_10us(1000);//Debounce
		switch(KEY_MATRIX_PORT)//Save the key value after the fourth column key is pressed
		{
			case 0x7e: key_value=4;break;
			case 0xbe: key_value=8;break;
			case 0xde: key_value=12;break;
			case 0xee: key_value=16;break;
		}
	}while(KEY_MATRIX_PORT != 0xfe);//Wait for the key to release

	return key_value;
}
//This lovely software will warn useless modules, Annotation line reversal method first
/********************************************************************
***********
* Function name: key_matrix_flip_scan
* Function function: use the line reversal scanning method to detect whether the matrix key is pressed, and press it to return the corresponding key value
* Input: None
* Output: key_value: 1-16, corresponding to S1-S16 key,
*					0: Key not pressed
*********************************************************************
**********/
/*
u8 key_matrix_flip_scan(void)
{
	static u8 key_value=0;

	KEY_MATRIX_PORT = 0x0f;//Assign 0 to all rows and 1 to all columns
	if(KEY_MATRIX_PORT != 0x0f)//Judge whether the key is pressed
	{
		delay_10us(1000);//Debounce
		if(KEY_MATRIX_PORT!=0x0f)
		{
			//Test column
			KEY_MATRIX_PORT = 0x0f;
			switch(KEY_MATRIX_PORT)//Save behavior 0, the column value after pressing the key
			{
				case 0x07: key_value=1;break;
				case 0x0b: key_value=2;break;
				case 0x0d: key_value=3;break;
				case 0x0e: key_value=4;break;
			}
		
			//Test line
			KEY_MATRIX_PORT=0xf0;

			switch(KEY_MATRIX_PORT)//Save the key value after the column is 0 and the key is pressed
			{
				case 0x70: key_value=key_value;break;
				case 0xb0: key_value=key_value+4;break;
				case 0xd0: key_value=key_value+8;break;
				case 0xe0: key_value=key_value+12;break;
			}
	
			while(KEY_MATRIX_PORT!=0xf0);//Wait for the key to release
		}
	}else 
		key_value=0;

	return key_value;
}
*/
/********************************************************************
***********
* Function name: main
* Function function: main function
* Input: None
* Output: None
*********************************************************************
**********/
void main()
{
	u8 key=0;
	while(1)
	{
		key = key_matrix_ranks_scan();
		if(key!=0)
		//The obtained key value minus 1 is converted into array subscript segment code
		SMG_A_DP_PORT=gsmg_code[key-1];
	}
}

The experimental results show that when the S1-S16 key is pressed, the leftmost nixie tube displays 0 - F.

🌟 Thorough inquiry

The matrix button is a little interesting to me

🌻 Elementary knowledge of matrix keys

If the I/O port of a single-chip microcomputer is too many, it will occupy more I/O resources if each key of the single-chip microcomputer needs to be connected with the I/O port of the single-chip microcomputer. Because I/O port resources are often scarce in single chip microcomputer system, matrix keys are introduced in order to reduce I/O port pins when multiple keys are used.

The matrix keys on 51 single chip microcomputer are arranged in 4 rows and 4 columns with 16 keys of 4 * 4,
·The first line connects one end of each key to form a line;
The first column connects the other end of each key to form a column line,

In this way, there are 4 lines, 4 columns and 8 lines in total. We connect these 8 lines to the 8 I/O ports of the single chip microcomputer, and 16 keys can be detected by scanning the keyboard through the program.
In this way, we can also achieve 9 keys in 3 rows and 3 columns, 25 keys in 5 rows and 5 columns, 36 keys in 6 rows and 6 columns or even more.

Change the soup without changing the dressing. Whether it is an independent key or a matrix key, the basis for the single chip microcomputer to detect whether it is pressed is the same. It is to detect whether the IO port corresponding to a key is low level.
Independent buttons, there is a fixed low level, the overall implementation is good, very simple. Both ends of the matrix key are connected with the IO port of the single chip microcomputer, so it is necessary to program to send the low level through the IO port of the single chip microcomputer during detection. The commonly used detection methods are row column scanning method and line reversal method.

Just look at the following text description of these two methods. Just look at it. There is no need to rush to understand it, because the text description is very abstract. I'll take you to understand it later with the clever code

① Row column scanning method
First send one column as low level, and the other columns are all high level (determine the number of columns in this way), and then immediately take turns to detect whether there is a low level in each row. If a low level of a certain behavior is detected (at this time, we determine the number of rows), we can confirm which row and column the key is currently pressed, send each column as low level in turn in the same way, and then take turns to detect whether each row becomes low level, In this way, all keys can be detected. When a key is pressed, it can be judged which key Ann likes. There is no final conclusion. You can also set the row to low level first and check whether the scanning column has low level.
② Line reversal method
The line reversal method is to make all row lines become low level, detect whether all column lines have low level, and if so, record the column line value; Then turn over again to make all column lines become low-level, and detect the values of all row lines. Since the keys will be pressed, the values of row lines will also change. Record the values of row lines, so that all keys can be detected.

Code design

If you want to write the code of MCU, you still need to see this lovely road map

As can be seen from the above figure:
The 8 control lines from the 4 * 4 matrix key are directly connected to the P1 port of 51 single chip microcomputer.
P17 in the circuit is connected to the first row of the matrix keyboard, and P13 is connected to the first column of the matrix keyboard.

Shallow reading code

Because the amount of code in the matrix key experiment is a little large. If you directly let us contact it, it may be a little brain cracking. Let me take you to understand the logic~

The code is read from the main function.
In the main function, the declaration of variables and the display of nixie tubes according to the results returned by the determinant scanning function need not be repeated, because it is the previous knowledge point~

The point is that let's combine the code to understand the determinant scanning function

This code is very long and looks scary, but it is actually a thought cycle that has been used for several times.

The row column scanning method is described in this way:
First send one column as low level, and the other columns are all high level (the number of columns is determined in this way),
Then check whether there is a low level in each row in turn immediately. If a low level is detected for a certain behavior (at this time, we determine the number of rows)

Put it into the code, that's what you play:
Let the eight serial ports of P1 port become the state of high and low level (0 low and 1 high) in the description. Is it a little confused? Let's be more specific

I want to make the first column 0 and all the others 1 according to the notes,

It can be seen from the circuit diagram that P13, P12, P11 and P10 control columns. When we operate, we also operate according to the circuit diagram.
Making a column low has been achieved.

According to the old rule, it is still necessary to eliminate the chattering, and then detect whether a row is pressed in the current column. The same logic


The display of the other 15 numbers is similar logic. I will not repeat it if I build the wheel repeatedly ~.
Then, the line reversal method is also a similar understanding. Friends can try to simulate it independently. If there are unclear partners, you can confide in me

summary

The knowledge points of this plate with IO port as input cannot be said to be unimportant. Its idea is to reflect the high and low levels through other external devices (keys).
In my opinion, the focus of this article is:
① I know that the IO port can indeed output current to support other external devices, and can also help the operation of other devices through input.
② It can be clearly seen that the amount of code for the knowledge point of keys has increased, and the operation of IO port is no longer a simple one or three. If you practice repeatedly, it is the best way to deepen the use and understanding of IO port.
③ Accumulate some small knowledge to eliminate errors, such as the elimination of chattering in this area

Tags: C Single-Chip Microcomputer 8051 microcontroller

Posted by intermediate on Fri, 06 May 2022 03:16:16 +0300