[Apprentissage STC MCU] Leçon 9: Utilisation des boutons MCU

[Intrusion dans le résumé du cours de M. Zhu]

La première partie, liste des chapitres

Une manière très importante de travailler dans cette section: interrompez, vous en utiliserez beaucoup dans le futur! L'ensemble du processus de développement embarqué!

1.9.1. Connaissances clés

1.9.2. Programmation indépendante des boutons

1.9.3. Détection et affichage des valeurs clés

1.9.4. Bouton anti-rebond

1.9.5. Détection complète des boutons

1.9.6. L'introduction des interruptions

1.9.7. Utiliser l'interruption externe de la MCU pour traiter les clés

1.9.8. Principe du clavier matriciel

1.9.9. Pratique de la programmation du clavier matriciel


La deuxième partie, introduction du chapitre

Section 1-7: parler des touches indépendantes, section 1-5 parler du mode d'interrogation, section 6-7 parler de la gestion des interruptions, section
8-9: parler du clavier matriciel!

1.9.1 Connaissances clés
    Cette section explique le principe de fonctionnement des clés, la manière dont le CPU gère les clés et la différence entre les clés indépendantes et les clés matricielles.
1.9.2 Programmation des boutons indépendants
    Cette section explique d'abord le schéma de principe et la méthode de câblage des boutons indépendants, puis programme et surveille 1 bouton, et enfin l'étend pour surveiller 8 boutons.
1.9.3 Détection et affichage de la valeur clé
    Cette section combine le contenu d'affichage du tube numérique pour afficher la valeur clé du bouton indépendant sur le tube numérique.
1.9.4 Anti
    - rebond des boutons Cette section explique ce qu'est la gigue et le anti- rebond des boutons, et la programmation réelle est utilisée pour le traitement anti- rebond.
1.9.5 Détection complète des boutons
    Cette section explique le processus complet des boutons (appuyez, maintenez et pop up), et modifiez le code de la leçon précédente pour le faire fonctionner parfaitement.
1.9.6
    L'introduction de l'interruption Cette section introduit le concept d'interruption et permet à chacun de comprendre la signification de l'interruption avec l'exemple de regarder des films et de recevoir une livraison express.
1.9.7. Utiliser l'interruption externe du micro-ordinateur monopuce pour traiter les frappes.
    Cette section se réfère à l'exemple de programme dans le manuel de données pour la programmation réelle à utiliser des interruptions externes pour traiter des frappes indépendantes.
1.9.8 Principe du clavier matriciel
    Cette section explique le principe du circuit et le câblage du clavier matriciel, puis analyse la méthode de détection des touches du clavier matriciel et d'acquisition des valeurs des touches.
1.9.9 Pratique de la programmation du clavier matriciel Dans
    cette section, programmez le clavier matriciel selon la méthode analysée dans la section précédente, obtenez la valeur de la clé et affichez-la sur le tube numérique.
    

Troisième partie, dossier de classe

1.9.1. Connaissances clés

Les boutons sont des appareils très courants et très simples, juste un périphérique d'entrée avec un ressort à l'intérieur!

1.9.1.1 Le principe de fonctionnement du bouton
(1) La structure mécanique interne
Afficher l'image source
équivaut à seulement deux broches, et seules ces deux broches peuvent être connectées au circuit externe!

(2) La connexion du circuit et l'icône dans le diagramme schématique
peuvent être comprises comme une cathode commune!



(3) Connexion du circuit de bouton, résistance de rappel .
C'est le circuit complet du bouton!
Le pull-up consiste à rendre la broche haute par défaut (entrée garantie) , mais la force du pull-up ne peut pas maintenir le sol ( Antaios ), donc le pull-up garantit que l'entrée de la broche IO est à 1 lorsque le bouton n'est pas enfoncé. Après avoir appuyé sur 0, il est définitivement 0.
Maintenant, je sais, appuyez sur le bouton et la valeur transmise au MCU est 0!

Afficher l'image source
La différence entre appuyer et sauter est le problème de la mise à la terre, c'est-à-dire si l'entrée de la broche est 1 ou 0.
(4) Ce que le bouton signifie pour nous: Le bouton est un périphérique d'entrée pour notre CPU, et l'entrée est une opération humaine. La CPU sait si le bouton est enfoncé de l'extérieur en contrôlant si l'entrée de niveau de la broche IO connectée au bouton est 1 ou 0. Cela équivaut à ce qu'une personne entre un signal au CPU en appuyant sur un bouton, et ce signal peut être surveillé par le CPU pour guider le CPU pour effectuer certains travaux.

1.9.1.2. Comment la CPU traite-t-elle le
type d'interrogation bouton (1)? La méthode dite d'interrogation est que le CPU vérifie en permanence si un bouton est enfoncé à un petit intervalle (dizaines de millisecondes), s'il est enfoncé, il traitera le bouton, s'il n'est pas enfoncé, il vérifiera à nouveau plus tard. (Lorsque le bouton est pressé est imprévisible par le CPU)
(2) Type d'interruption, j'en parlerai plus tard, en m'appuyant sur la table des vecteurs d'interruption et la fonction d'interruption!
1.9.1.3. Classification de la connexion du circuit de bouton
Il y a un schéma de principe ci-dessus
(1) Bouton indépendant
    Les boutons sont indépendants les uns des autres!
(2)
    Il existe une corrélation entre les boutons de la matrice !
Carte physique:



1.9.2. Programmation indépendante des boutons

1.9.2.1. Schéma de principe et analyse du câblage
(1) Les 8 boutons indépendants sont connectés de la même manière: une extrémité est connectée à GND, l'autre extrémité est connectée au port du microcontrôleur
(2) Câblage: la prise bouton JP1 est connectée au port P1 , puis le port P1 est connecté. 8 E / S correspondent respectivement à 8 touches (P1.0 correspond à K1, P1.1 correspond à K2 ···· P1.7 correspond à K8)
(3) Pour utiliser la LED pour allumer ou éteindre pour indiquer si la touche est enfoncée, vous devez Câblage LED. Le port P0 est connecté à LEDJ19.

1.9.2.2. Premier bouton du moniteur 1 (utiliser la LED comme indicateur)
(1

Key1 , le microcontrôleur vérifie si le niveau d'entrée de la broche P1.0 correspondant à K1 est à 1 ou 0 à chaque court instant de la boucle. S'il est à 1, cela signifie que la touche n'est pas enfoncée et la LED s'éteint à titre indicatif. Retardez et attendez le test suivant; s'il est à 0, le bouton a été enfoncé et une LED est allumée à titre indicatif.
 

#include <reg52.h>

//当前处理的是Key1,对应P1.0 
//控制的是LED1,对应的是P0.0

sbit KEY1 = P1^0;
sbit LED1 = P0^0;

void delay(void)
{
	unsigned char i = 10;
	unsigned char j = 100;
	while(i--)
		while(j--);
}	

void main(void)
{
	LED1 = 0;
	while(1)
	{
		if(KEY1 == 1)
		{
			//没有按键
			LED1 = 1; //熄灭
		}
		else
		{
			//有按键
			LED1 = 0; //亮
		}
		delay();
	}
}

1.9.2.3 Développez pour surveiller 8 boutons indépendants (c'est plus simple), pensez-y!
Remarque:
(1) Si le nombre de boutons à surveiller est petit, vous pouvez utiliser la surveillance des bits. S'il y en a beaucoup, vous pouvez directement utiliser la variable d'octet de port pour surveiller.
(2) Boutons indépendants Plusieurs boutons sont indépendants les uns des autres, il est donc permis d'appuyer sur plusieurs boutons en même temps sans les affecter. (Le bouton de la matrice ne peut être pressé qu'un seul bouton à la fois, pas plusieurs boutons en même temps ) Essayez d'appuyer sur plusieurs boutons à la fois!

1.9.3. Détection et affichage des valeurs clés

1.9.3.1. Qu'est-ce que le codage clé-valeur  clé
(1) Il existe de nombreuses clés dans les produits généraux. Pour l'ensemble du programme, les clés sont généralement codées, et chaque clé a une valeur de code correspondante, appelée valeur clé de la clé.
(2) Dans un programme formel et relativement volumineux, la partie détection et la partie traitement du bouton sont séparées. La séparation de ces deux parties facilite la programmation de leurs parties respectives, et les deux parties sont reliées par des touches . La partie de surveillance des boutons est responsable de la surveillance des boutons. Une fois qu'un événement de bouton se produit, une valeur de clé est générée, puis la valeur de clé est transmise à la partie de traitement de bouton.

1.9.3.2. Ajouter le tube numérique pour afficher la valeur de la clé
Idée: L'

ensemble du programme comprend 2 parties: la
partie de contrôle des touches: quelle touche est enfoncée, la valeur de la clé est affectée à quelle valeur; la
partie de traitement de clé: la valeur de clé reçue est affichée sur le tube numérique indépendant sur.
Implémentation du code 1:

#include <reg51.h>

/*********************程序说明***************************************
		本代码利用sbit位变量,实现数码管可以显示key1、key2、key3的键值
                      JP1(按键)-P2
				      J8(静态数码管)-P0
        按键是低电平有效,数码管显示要参考之前的静态数码管的段码表(第七课)
	
/*********************变量定义************************************/
sbit key1 = P2^0;
sbit key2 = P2^1;
sbit key3 = P2^2;
typedef unsigned char u8;

// 独立数码管的段码表
u8 val[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

//按键处理函数,将键值显示到数码管
void display(u8 keynum);

void main(void)
{
	
	u8 keynum = 0;
	while(1)
	{
		//按键检测部分
		if(key1 == 0)
		{
			keynum = 1;
		}
		if(key2 == 0)
		{
			keynum = 2;
		}
		
		if(key3 == 0)
		{
			keynum = 3;
		}
		//按键处理部分,数码管显示键值
		display(keynum);
	}
}

void display(u8 keynum)
{
	P0 = val[keynum];
}

Si le code ci-dessus affiche la valeur de clé de chaque touche, vous devez écrire 8 instructions if-else, et si vous appuyez sur key1, puis appuyez sur key2, la valeur de la clé ne change pas (c'est-à-dire que la pression suivante ne peut pas être détectée ) , Y a-t-il un bon moyen?
Au moment critique, M. Bit Operator viendra à la rescousse Implémentation du

code 2: Toutes les valeurs clés peuvent être affichées!

 

#include <reg51.h>

/*********************程序说明***************************************
                      JP1(按键)-P2
					J8(静态数码管)-P0
*/
typedef unsigned char u8;

// 独立数码管的段码表
u8 val[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

//按键处理函数,将键值显示到数码管
void display(u8 keynum);

void main(void)
{
	//键值
	unsigned char keynum = 0;

	while (1)
	{
		//按键检测部分
		unsigned char i = 0;
		//for循环实现了后按的按键也能被检测到
		for (i=0; i<8; i++)
		{
			//0x01<<i(0-7)  分别对应0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
			//& 是判断P2的第i位是否为0
			if ((P2 & (0x01<<i))	== 0)
			{
				keynum = i + 1;
			}
		}
		//按键处理部分
		 display(keynum);
	}
}

void display(u8 keynum)
{
	P0 = val[keynum];
}


1.9.4. Bouton anti-rebond


Cette leçon traite principalement du problème de l'anti-rebond des touches. Qu'est-ce que la gigue? Examinons d'abord un cas!

1.9.4.1. Cas: Appuyez une fois sur le bouton et le tube numérique affichera le numéro plus 1

#include <reg51.h>

/**************代码说明**************************
			本程序实现每按一个按键,数码管数字+1,0-F循环。
				P2--按键
				P0--静态数码管
*************************************************/
sbit key1 = P2^0;

typedef unsigned char u8;

// 独立数码管的段码表
u8 val[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

u8 dnum = 0;  //最开始的数码管显示的值

void AddDisplay(void)
{
	dnum++;
	P0 = val[dnum%16];
}

void delay(void)
{
	u8 i = 100;
	u8 j = 100;
	while(i--)
		while(j--);
}
void main(void)
{
	//键值
	//unsigned char keynum = 0;

	while (1)
	{
		if(key1 == 0)
		{
			AddDisplay();
		}
	}
}

La raison derrière l'observation du phénomène est à cause de la gigue! Parce que vous n’avez pas appuyé assez vite,


1.9.4.2. Qu'est-ce que la gigue?
(1)
Insérez la description de l'image ici
Le graphique du niveau change lorsque le bouton est enfoncé et apparaît. Ce graphique est très clair. Lorsqu'il est enfoncé, l'ascenseur n'est pas assez rapide, donc le bouton va trembler!

(2) Comment générer de la gigue en
    raison de la structure mécanique, véritable dispositif physique, il est inévitable de produire de la gigue lorsqu'il est pressé, généralement de la gigue sera générée lorsqu'il est enfoncé et relâché, le temps de gigue est d'environ 10 ms
    (10 ms est d'environ 10 * 120 cycles whiile)
(3) Risque
     
de gigue: le niveau de la broche change dans la plage de temps de gigue. Si le programme détermine le niveau de la broche dans cette plage pour déterminer s'il y a un bouton, alors Il y a une forte possibilité de mauvaise appréciation.

1.9.4.3 Comment éliminer la gigue
(1) Élimination matérielle de la gigue: utilisez les caractéristiques de charge et de décharge du condensateur pour lisser la bavure de tension générée pendant le processus de gigue, de manière à éliminer la gigue. Cependant, dans les applications pratiques, l'effet de ce procédé n'est souvent pas très bon, et il augmente également le coût et la complexité du circuit, de sorte qu'il n'est pas beaucoup utilisé dans la pratique.

(2) Anti-rebond logiciel. Puisqu'il est impossible d'éliminer complètement la gigue dans le matériel, la conception logicielle doit trouver un moyen d'éviter l'influence causée par la gigue. Il s'agit d'un anti-rebond passif (évasif) .
Ajoutez un délai pour contourner la période de gigue!
 

#include <reg51.h>

/**************代码说明**************************
			本程序实现每按一个按键,数码管数字+1,0-F循环。
				P2--按键
				P0--静态数码管
*************************************************/
sbit key1 = P2^0;

typedef unsigned char u8;

// 独立数码管的段码表
u8 val[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

u8 dnum = 0;  //最开始的数码管显示的值

void AddDisplay(void)
{
	dnum++;
	P0 = val[dnum%16];
}

//利用单片机小精灵
void delay20ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=215;b>0;b--)
        for(a=45;a>0;a--);
}
void main(void)
{
	//键值
	//unsigned char keynum = 0;

	while (1)
	{
		if(key1 == 0)
		{
			delay20ms();
			if(key1 == 0)
					AddDisplay();
					while(!key1);  //避免长按
		}
		delay20ms();
	}
}

1.9.5. Détection complète des boutons

Cette section consiste à implémenter while (! Key1) // Éviter d'appuyer longuement

1.9.6. L'introduction des interruptions

1.9.6.1 Tâche: Le tube numérique indépendant affiche cycliquement 0-F et le bouton commande l'allumage et l'extinction de la LED
(1) L'analyse peut-elle être réalisée?

#include <reg51.h>

/**************接线说明**************************
				P0--静态数码管
				P1.0 LED1
				P1.1 LED2
				P2.0 KEY1
				P2.1 KEY2
*************************************************/

sbit key1 = P2^0;
sbit key2 = P2^1;

sbit led1 = P1^0;
sbit led2 = P1^1;


// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

/*********************************** 函数声明 ***********************/

// 延时函数
void delay(void)
{
	unsigned char i, j;

	for (i=0; i<200; i++)
		for (j=0; j<200; j++);
}

/******************************全局变量定义*************************/

void main(void)
{
	unsigned char i = 0;


	while (1)
	{
		// 任务1:数码管显示
		for (i=0; i<16; i++)
		{
			P0 = val[i];
			delay();
		}
		// 任务2:按键监测及led控制
		if (key1 == 1)
			led1 = 1;
		else
			led1 = 0;

		if (key2 == 1)
			led2 = 1;
		else
			led2 = 0;

	}
}

La pratique a prouvé que la fonction peut être réalisée, mais le moniteur de bouton et la LED de contrôle sont très insensibles. Appuyez rapidement sur le bouton et rebondissez, il n'y a aucun changement de LED! quelle est la raison?
Raison: Faites attention à la boucle for affichée par le tube nixie dynamique. Ce n'est que lorsque la boucle for est complètement terminée que vous pouvez répondre à votre opération de touche! Le microcontrôleur lui-même ne suffit donc pas.

(2) Réalisez progressivement que le micro-ordinateur à une seule puce n'a qu'une seule "tâche de ligne principale".
Le processeur du micro-ordinateur à une seule puce est monocœur et ne peut effectuer qu'une tâche à la fois. La tâche que le microcontrôleur passe le plus de temps s'appelle la tâche de ligne principale , tout comme la tâche ci-dessus. , La tâche principale du CPU dans un laps de temps est d'allumer le tube numérique statique, de contrôler la LED, etc. juste un instant!
Bien que le programme ci-dessus puisse également réaliser le multitâche, il ne peut pas répondre à temps. La tâche principale doit être temporairement arrêtée pour répondre à d'autres tâches. Comment chronométrer le multitâche et répondre à temps?

(3) Comment réagir à temps en multitâche?
Avec interruption (interruption) , voir la section suivante décrit!

1.9.6.2. L'idée d'interruption
(1) "Tâche principale" est une tâche régulière, qui s'exécute
par défaut. (2) Après l'interruption, le CPU suspend la tâche principale et passe à la tâche d'interruption (elle sera transférée en un clin d'œil, bientôt!) , Après avoir terminé, revenez et effectuez la tâche principale.

L'image suivante aide tout le monde à comprendre:

Afficher l'image source
Manuel de développement P105!

1.9.6.3. La signification des interruptions
(1) La capacité de traitement des interruptions permet à la CPU de traiter complètement la tâche principale ( lire un livre ) sans se soucier des tâches d'interruption manquantes (par exemple: répondre au téléphone, ouvrir la porte )
(2) L'interruption est plus appropriée pour le traitement que l'interrogation Les événements asynchrones sont plus efficaces.
(3) Les caractéristiques des événements traités dans l'interruption sont: temps de traitement imprévisible et court (les tâches d'interruption doivent être très courtes, si le temps est trop long, cela affectera la tâche principale!) , Les exigences de réponse sont urgentes.


1.9.7. Utiliser l'interruption externe de la MCU pour traiter les clés

Regardez d'abord le manuel P105 et le schéma

1.9.7.1 Interruptions externes INT0 et INT1

(1) Que sont les interruptions externes?
   La source d'interruption provient de l'extérieur du microcontrôleur, que l'on appelle interruption externe.51 prend en charge 4 interruptions externes. Correspondent respectivement à 4 broches. Chaque interruption externe correspond à une broche IO MCU spécifique (par exemple, INT0 correspond à P3.2, ceci est déterminé par le MCU lors de la conception et ne peut pas être modifié) . Notre logiciel n'a besoin que de faire certaines configurations ( initialisation ) liées à P3.2, et P3.2 peut répondre aux événements d'interruption externes. Lorsque le matériel génère une interruption externe, la CPU recevra un signal d'interruption, puis va exécuter le programme de traitement correspondant à l'interruption externe ( ce programme de traitement est également fourni par notre logiciel ).

(2) À quelle broche l'interruption externe correspond-elle?
Nous utilisons P3.2 pour nous connecter à Key1 (JP1_K1)

1.9.7.2. Ecrire un programme en référence à l'exemple de code dans le manuel de données (Manuel P118)
(1) Utiliser INT0 pour traiter les clés en programmation (P3.2)
(2) Explication du programme

IT0 = 1; //set INT0 interrupt type (1:Falling 0:Low level)
EX0 = 1; //enable INT0 interrupt
EA = 1; //open global interrupt switch

IT0 / EX0 / EA sont trois registres, qui sont en fait des variables binaires, définis par sbit dans reg51.h tout comme P0 et P1!

Le bit de registre de contrôle d'interruption IT0
IT0 est utilisé pour définir le mode de déclenchement de l' interruption INT0 (P3.2) :
= 1 Déclenchement sur front descendant (Falling): Si l'entrée pin a une transition 1-> 0, l'interruption sera déclenchée
= 0 bas Déclenchement de niveau (niveau bas): Tant que l'entrée pin est à 0, l'interruption
INT0 est

déclenchée, c'est P3.2 EX0 Le bit EX0 du registre de validation d'interruption
est le commutateur de INT0 .
= 0 L'  interruption externe est fermée à l'intérieur du microcontrôleur et l' interruption INT0 est interdite. À ce stade , la CPU ne peut pas recevoir les informations d'interruption de INT0, elle ne traitera donc pas INT0;
= 1 Activer l'interruption INT0


Le  registre d'activation d'interruption EA
est un commutateur d'interruption global .
= 0 La CPU protège toutes les demandes d'interruption
= 1 La fonction de l'interruption d'ouverture de la CPU

EA est de permettre aux interruptions de former deux niveaux de contrôle. C'est-à-dire que chaque source d'interruption est d'abord contrôlée par EA; d'autre part, elle est également contrôlée par le propre bit de commande d'activation d'interruption de chaque source d'interruption (EX0).

 Routine de service d'interruption externe

//External interrupt0 service routine
//函数名exint0 可以随便起
void exint0() interrupt 0         //INT0, interrupt 0 (location at 0003H)
{
    P0++;
}

L'interruption externe de INT0 a été configurée dans main. Tant que INT0 a une interruption externe, le sous-programme de service d'interruption sera automatiquement appelé.
 
Modifions sur la base du programme ci-dessus avec des fonctions imparfaites!
 

#include <reg51.h>

/**************代码说明**************************
			本程序采用中断方式,实现了静态数码管显示0-F并且按下Key1时,LED1亮
				P0--静态数码管
				P1.0 LED1
				P3.2 KEY1
*************************************************/

sbit key1 = P3^2;
sbit led1 = P1^0;


// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

/*********************************** 函数声明 ***********************/

// 延时函数
void delay(void)
{
	unsigned char i, j;

	for (i=0; i<200; i++)
		for (j=0; j<200; j++);
}

/******************************中断服务程序*************************/
void Eint_Key() interrupt 0 
{
	led1 = 0;
	delay();
	led1 = 1;
}

/***************************主函数*********************************/
void main(void)
{
	unsigned char i = 0;
	
		//INT0 外部中断开启
		IT0 = 1; 
		EX0 = 1; 
		EA = 1; 
	
		led1 = 1;
	while (1)
	{
		//主线任务
		for (i=0; i<16; i++)
		{
			P0 = val[i];
			delay();
		}
	}
}

1.9.7.3. Résumé
(1) La capacité d'interruption est prise en charge par la conception de la CPU elle-même et n'est pas fabriquée par programmation.
(2) Le programmeur ne doit être responsable que de deux choses: initialiser l'interruption dans le programme principal et définir le gestionnaire d'interruption.
(3) Lorsqu'une condition d'interruption se produit, le matériel détecte et avertit automatiquement le CPU, et le CPU exécute automatiquement le gestionnaire d'interruption. Tous ces éléments sont déterminés lors de la conception du CPU et ne nécessitent aucune intervention de programmation.


1.9.8. Principe du clavier matriciel

1.9.8.1 Analyse du schéma de principe du clavier matriciel

(1) Divisions horizontales et verticales Le
quatre horizontal est un groupe et le quatre vertical est un groupe!
Broches: 1-4 tubes sont horizontaux, 5-8 tubes sont verticaux

(2) Les deux extrémités du bouton sont connectées à différentes broches IO ( les boutons indépendants n'ont qu'une seule broche )
(3) La fonction physique du bouton Aucun changement
Appuyez pour mettre le circuit sous tension et rebondissez pour le désactiver.

1.9.8.2 La touche du clavier matriciel
est le périphérique d'entrée. Tant qu'elle est enfoncée, le programme a besoin de savoir quelle touche est enfoncée.


(1) Le programme envoie en premier (sortie de broche IO) 0x0f

引脚:8 7 6 5 4 3 2 1
电平:0 0 0 0 1 1 1 1

(2) Lisez l'entrée de la broche IO, vous pouvez juger quelle ligne est enfoncée
(3) Le programme envoie
( sortie de la broche IO) 0xf0 (4) À partir des données reçues (entrée de la broche IO) pour juger quelle colonne est enfoncée

   引脚:8 7 6 5 4 3 2 1
输出0x0f
   输入:0 0 0 0 1 1 1 0  0x0e 第0行
         0 0 0 0 1 1 0 1  0x0d 第1行
         0 0 0 0 1 0 1 1  0x0b 第2行
         0 0 0 0 0 1 1 1  0x07 第3行
输出0xf0
   输入:1 1 1 0 0 0 0 0  0xe0 第0列
         1 1 0 1 0 0 0 0  0xd0 第1列
         1 0 1 1 0 0 0 0  0xb0 第2列
         0 1 1 1 0 0 0 0  0x70 第3列

(5) Synthétisez les positions de ligne et de colonne obtenues deux fois, calculez la valeur de la clé

1.9.8.3, les caractéristiques du clavier matriciel
(1) Avantages: économie d' E
/ S mono-puce (2) Inconvénients: vous ne pouvez pas appuyer sur plusieurs touches
en même temps si vous appuyez sur deux en même temps Boutons, quatre boutons seront reconnus


1.9.9. Pratique de la programmation du clavier matriciel

Câblage: P0 - tube numérique statique, P3 - clavier matriciel

Appuyez sur le clavier matriciel et le tube numérique indépendant correspondant affichera la valeur de la clé.
Code

/********接线说明****************
		
			P0--静态数码管
			P3--矩阵键盘(1-8:P3.0-P3.7)
	
*********************************/
#include<reg51.h>

#define SDT P0	//静态数码管
#define KEY P3	//矩阵键盘

typedef unsigned char u8;

void delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

// 独立数码管的段码表
unsigned char val[16] = 
{
	0xc0, 0xf9, 0xa4, 0xb0, 
	0x99, 0x92, 0x82, 0xf8,
	0x80, 0x90, 0x88, 0x83,
	0xc6, 0xa1, 0x86, 0x8e
};

void main(void)
{
	u8 KeyValue; //存放键值
	while(1)
	{
			//检测行
			KEY = 0x0f;
			if(KEY != 0x0f)
			{
				delay10ms(); //消抖
				//第一回合找出行
				switch(KEY)
				{
					case(0x0e): KeyValue = 0; break; //第0行
					case(0x0d): KeyValue = 1; break;
					case(0x0b): KeyValue = 2; break;
					case(0x07): KeyValue = 3; break; //第3行	
					default:									break;
				}
				
				//第二回合找出列
				KEY = 0xf0;
				switch(KEY)
				{
					case(0xe0): KeyValue = KeyValue*4+0; break; //第0列
					case(0xd0): KeyValue = KeyValue*4+1; break;
					case(0xb0): KeyValue = KeyValue*4+2; break;
					case(0x70): KeyValue = KeyValue*4+3; break; //第3列	
					default:									break;
				}
			}
			SDT = val[KeyValue];
		}
}

Lien de téléchargement du programme de cette section: bouton

Cette leçon est terminée!

Je suppose que tu aimes

Origine blog.csdn.net/qq_27148893/article/details/109555122
conseillé
Classement