Lab2 Mic4235

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 16

UQÀM Microcontrôleur MIC4235

Département de Génie Microélectronique

Lab. #2 : Clavier et Afficheur LCD

I. But du laboratoire et matériel requis :

Le but du laboratoire est d'encoder un clavier matriciel afin de générer un code ASCII
correspondant à chaque touche du clavier sur l’écran LCD..

Matériel requis:

- clavier matriciel 4x3


- LCD Lumex LCM-SO1602
- système de développement à microcontrôleur MPS430-RF2500
- plaquette de montage, fils, etc...
- un potentiomètre entre 10K et 20K

II. Partie #1 : Encodeurs de claviers

Introduction
Une des applications majeures des microcontrôleurs est la réalisation de claviers d'ordinateurs
intelligents. L’usage de microcontrôleurs dans ce domaine se traduit non seulement par un prix
de revient moins élevé qu'avec des circuits discrets, mais permet aussi de changer la signification
d'une touche à souhait.

Identification des touches pesées sur un clavier


Il existe deux types fondamentaux d'encodage de claviers, dépendant de la structure mécanique
du clavier utilisé.

Encodage linéaire :

Dans ce cas, le clavier est organisé de manière à ce que


toutes ses touches partagent une borne commune.
L'identification de la touche enfoncée se fait en scrutant
individuellement toutes les touches jusqu'à ce qu'on détecte
un changement d'état dans l'une d'elles.

Cette technique est relativement simple, mais le nombre de


lignes d'e/s requis pour le microcontrôleur est égal au
nombre de touches, et peut excéder rapidement la capacité
du microcontrôleur.
Encodage matriciel :

Dans ce cas, le clavier est organisé en une matrice,


et c'est l'intersection d'une ligne avec une colonne
qui permet d'identifier la touche enfoncée. Port // ...
L'identification de la touche enfoncée peut se faire
de deux façons :

a) "1" mobile : On génère un « 1 » sur chaque ...


colonne en succession jusqu'à ce que la lecture des
lignes donne un "1" sur l'une d'elles. Le numéro de
la ligne et celui de la colonne qui a généré le « 1 »
donnent les coordonnées de la touche enfoncée. Des résistance de tirage sont requises pour les
lignes afin de lire un « 0 » sur les lignes inactives.

b) Renversement de lignes : On envoie un "1" sur toutes les colonnes simultanément et on fait
une lecture des lignes. Si une touche est enfoncée, un "1" apparaîtra sur la ligne correspondante.
On renvoie alors le code lu des lignes vers les colonnes, ce qui fera apparaître un "1" apparaîtra
dans l’une d’elles. Les positions des deux ‘1" lus donnent les coordonnées de la touche
recherchée. Cette technique est potentiellement plus rapide que la précédente (2 étapes au lieu de
n, n étant le nombre de colonnes, pour la précédente), mais elle demande des résistances de
tirage aussi bien pour les lignes que pour les colonnes.

Dans les deux cas, si un clavier possède m rangées de n clés, l’identification des clés pesées
requière l’utilisation de m+n lignes de ports parallèles, au lieu de mxn pour un clavier linéaire.

Problèmes connexes

Après avoir enfoncé ou relâché une touche d’un clavier, un certain délai (jusqu’à 10 ms) s’écoule
durant lequel le ressort de rappel situé sous la touche subit plusieurs rebondissements, créant
ainsi de faux contacts. Cette situation impose l’attente que le délai de rebondissement soit achevé
avant d’essayer d’identifier la touche pesée ou relâchée. Cela mène au pseudo-code suivant pour
le programme pilote du clavier :

Clavier_Touche:
{
Attendre que le clavier devienne actif
Identifier touche
Attendre la fin du délai de rebondissement
Vérifier que la même touche est toujours enfoncée

Attendre que le clavier devienne inactif


Attendre la fin du délai de rebondissement
Vérifier que le clavier est toujours inactif
retourner les coordonnées de la touche dans l=affirmative
}
L’approche précédente fonctionne bien mais n’est pas efficace ; le temps passé dans les boucles
d’attente pourrait être mis à profit pour exécuter d’autres tâches. Une meilleure solution consiste
à mettre en œuvre le pilote du clavier suivant le modèle d’un automate à états finis. L’idée est de
générer des interruptions périodiques et, à chaque interruption, de vérifier une des étapes
précédentes et mettre à jour un compteur d’étape, sauvegardé en mémoire, s’il y a lieu. On
économise ainsi tous les délais d’attente puisqu’ils sont implicites dans les délais d’interruption.

Le pseudo-code est comme suit :

code principal :
{
...
Initialiser le compteur d’étapes du pilote de clavier à 0
Initialiser l’indicateur de touche pesée à 0
Programmer un temporisateur
Autoriser les interruptions du temporisateur
Autoriser les interruptions dans le microcontrôleur
...
Si indicateur de touche pesée =1
{
Récupérer le code
Indicateur de touche pesée=0
....
}
....
Boucler ver le code de vérification de la touche pesée
}

Routine d’interruption du compteur :


{
Si compteur d’étapes = 0
{
Lire le clavier
Si touche enfoncée, incrémenter le compteur d’étapes
}
Si compteur d’étapes = 1
{
Lire le clavier
Si touche toujours enfoncée,
{
Sauver le code
incrémenter le compteur d’étapes
}
sinon compteur d’étapes = 0
}
Si compteur d’étapes = 2
{
Lire le clavier
Si touche relâchée, incrémenter le compteur d’étapes
}
Si compteur d’étapes = 3
{
Lire le clavier
Si touche toujours relâchée
Compteur d’étapes =0
Indicateur de touche pesée = 1
}

III. Partie #2 : Circuits d’affichage

Introduction

Les microcontrôleurs utilisent deux technologies de base pour afficher l’information : les diodes
émettrices de lumière (DEL) et les cristaux liquides. Dans le premier cas, les DEL sont
organisées en ensembles de segments dont les sous-ensembles, lorsqu’allumés, affichent
l’information voulue. Quant aux cristaux liquides, ils sont généralement organisés en matrices de
points à l’instar d’un écran d’ordinateur moderne. Dans tous les cas, l’information est affichée en
allumant les segments ou points concernés. Pour cela, on peut soit relier les lignes d’un port
parallèle aux différents segments dans des cas simples, ou bien utiliser une interface avec
contrôleur dédié.
Afficheurs : à segments, à matrice
de points Module d’affichage à segments

Module d’affichage à matrice de points

Concernant les afficheurs à segments, on peut les piloter en utilisant des décodeurs matériels qui
convertissent un code binaire en un code de segments à allumer (e.g. 7447, 7448), ou encore des
décodeurs logiciels qui génèrent les codes de segment par programmation. Quant aux décodeurs
à matrice de points, ils sont généralement pilotés à l’aide de contrôleurs spécialisés que l’on
commande à l’aide d’un port parallèle. Ces contrôleurs utilisent un bus de données de 4 ou 8 bits
(programmable lors de l’initialisation) et des lignes R/W, E et RS pour programmer le type
d’opération voulu.
Vcc
Vcc
1=allumé Vcc
0=allumé 0=éteint
1=éteint ou

Port // Port // Port // Décode ur Reseau de Affic heur


Vcc R requis
pour
0=allumé certains
1=éteint décode urs

I#8 mA I#20 mA
R=(Vcc-1.8)/I R=(Vcc-1.8)/I

Port // Module d’affichage à matrice de points

Différents types de circuits d’affichage Contraste Vcc Vss

Vcc

II. Procédure à effectuer :

1. Étudier le code fourni en annexe à la lumière des fichiers de spécification de l’afficheur LCD
fourni et vérifier que le code fonctionne tel que prévu en le compilant et en l’exécutant sur le kit de
développement du MSP430. Noter que le module LCD est programmé en mode 4 bits pourle
transfert des données, ce qui implique que chaque mot de 8 bit envoyé par le microcontrôleur le sera
en deux moitiés successives de 4 bits.

3. Écrire un programme qui décode un clavier téléphonique de 3x4 et qui montre sur l’afficheur LCD
les codes hexadécimal et ASCII de toute clé pesée et décodée. Afin de réduire le nombre de lignes
d’e/s du microcontrôleur à utiliser, mettre en commun les 4 lignes de données du module LCD avec
les 4 lignes du clavier (voir le schéma électrique en annexe – ce mode de connexion est possible
puisque le module LCD ignore l’état de ses lignes de données lorsque sa ligne E est inactive).

2. Écrire un programme qui réalise une horloge électronique et qui affiche le jour et l’heure (ex:
Mercredi 08:35 pm) sur le module LCD. L’entrée initiale de la date se fera par le biais du clavier
téléphonique 3x4, et le clavier et afficheur LCD seront reliés au microcontrôleur par des ports
parallèles.
Questions :

1) Que se passe-t’il si plus d'une touche est enfoncée à la fois ? Comparer les deux méthodes de
décodage de claviers matriciels présentées plus haut face à ce problème et suggérer une solution.

2) Supposer que le montage ci-contre soit relié à l'entrée IRQ d'un V cc


microcontrôleur :
IRQ/
a) Décrire les conséquences de l'effet de rebondissement sur
le microcontrôleur quand on ferme le commutateur.
:C
b) Suggérer une solution au problème.
Annexe :

Exemple de programmation d’un clavier

/**************************************************************************/
/* Lab2 - eZ430-RF2500 TEST Keypad */
/* */
/* MSP430F2274 USB */
/* Produit par: MIC4235 */
/* */
/* Exercise: Using the ez430-RF2500 Development Tool */
/* and testing a 3x4 keypad */
/* */
/**************************************************************************/

#include <msp430x22x4.h>

// On suppose que :

// La disposition des touches est comme suit :


//
// COL1 COL2 COL3
// 1 2 3 ROW 1
// 4 5 6 ROW 2
// 7 8 9 ROW 3
// * 0 # ROW 4
//
// l arrangement des broches est comme suit :
// P2.0-P2.3 = L1-L4
// P4.3-P4.5 = c1-c3

#define rowPort P2OUT


#define colPort P4IN

unsigned char keyPadMatrix[] =


{
'1','2','3',
'4','5','6',
'7','8','9',
'*','0','#', 0xFF
};

/*********************************************************
* ScanCalvierInit initialise les ports pour la lecture *
********************************************************/
void scanClavierInit()
{
P2OUT=0;
P2DIR |= 0x0f; /* P2.0-3 = output pour les lignes */
P4DIR &= 0xC7; /* P4.3-5 = input pour les colonnes */
P4REN |= 0x38; /* P4.3-5 Activer R pullup/down Col 1-3*/
P4OUT &= ~0x38; /* P4.3-5 Set pulldown */
}
/**********************************************************
* ScanClavier scan et retourne la première touche pesée *
* du clavier pendant le scan, sinon 0xff *
*********************************************************/
unsigned char scanClavier()
{
unsigned char key = 0, row;

for( row = 0x01; row < 0x10; row <<= 1 )


{
rowPort &= 0xf0; // mettre toutes les lignes à 0
rowPort |= row; // propager un 1 sur une ligne
// lire les colonnes et arrêter si un 1 détecté
if( colPort & 0x08 ) break; // colonne 1 ?
key++;
if( colPort & 0x10 ) break; // colonne 2 ?
key++;
if( colPort & 0x20 ) break; // colonne 3 ?
key++;
}
return keyPadMatrix[ key ];
}
/**********************************************************
* delaiReb : génère un délai *
*********************************************************/
void delaiReb()
{
unsigned int delai=0x1000; //ajuster à 10 ms ou utiliser l'horloge
while (--delai) ;
}

/**********************************************************
* ScanTouche attend la première touche pesée du clavier*
* et retourne sa valeur après l écoulement du délai *
* de rebondissement. *
*********************************************************/
unsigned char scanTouche()
{
unsigned char touche=0xff;

while (touche==0xff)
{
touche = scanClavier();
if (touche != 0xff) // touche pesée
{
delaiReb(); // délai de rebondissement
if (touche != scanClavier()) touche = 0xff;
}
return touche ;
}

/**********************************************************
* Programme de test *
*********************************************************/
void main()
{
unsigned char cle;
scanClavierInit();
cle = scanTouche();
}
Exemple de programmation d’un afficheur à cristaux liquides
/**************************************************************************/
/* Lab2 - eZ430-RF2500 TEST LCD */
/* */
/* MSP430F2274 USB */
/* Produit par: MIC4235 */
/* */
/* Exercise: Using the ez430-RF2500 Development Tool */
/* and test the LCD Lumex */
/* */
/**************************************************************************/
/* |
* MPS430 |
* |
* P3.0 |------------------------------------+ db4
* P3.1 |------------------------------------|-+ db7
* P3.2 |------------------------------------|-|-+ db6
* P3.3 |------------------------------------|-|-|-+ db7
* P2.0 |----------------------+RS | | | |
* P2.1 |----------------------|---+E | | | |
* | | | | | | |
* | RW=Vss | | | | | |
* | | | | | | |
* | Vdd | | | | | |
* | | | | | | | |
*______________| +-----+ | | | | | |
* | | | | | | | |
* +---+ | | | | | | |
* |10K|---|-+ | | | | | |
* +---+ | | | | | | | |
* | | | | | | | | |
* +-----+---+-|-|-|-+ | | | | |
* | 1 | | | | | | | | | | | | | | 14
* | +--------------------------------------+
* --- |               |
* - | V V V R R E D D D D D D D D LCD |
* | s d o S W b b b b b b b b (LM015) |
* | s d 0 1 2 3 4 5 6 7 |
* +--------------------------------------+
*/
/**************************************************************************/

#include <msp430x22x4.h>

#define LCD_RS (0x01) //Register select bit(P2.0)


#define LCD_E (0x02) //Clock bit(P2.1)

unsigned char index;


void initLCD(void);
void wLCDdat(unsigned char data);
void wLCDctrl (unsigned char ctl);
void wLCDctrl4(unsigned char ctl);
void putcharLCD(unsigned char car);
void cputsLCD(char *putstr);
/********************************************************
* LCD display peripheral initialization *
********************************************************/
void initLCD(void){
P3DIR |= 0x0f; /* P3.0-3 = output DATA */
P2DIR |= 0x03; /* P2.0-1 = output RS E */
wLCDctrl (0x03); /* 8 Bit mode */
wLCDctrl (0x03); /* 8 Bit mode */
wLCDctrl (0x03); /* 8 Bit mode */
wLCDctrl (0x02); /* Home */
wLCDctrl4(0x24); /* Function Set- 4-bit,1-line,5X7 */
wLCDctrl4(0x0c); /* Display on, Cursor off */
wLCDctrl4(0x06); /* entry mode- Inc addr, no shift */
wLCDctrl4(0x01); /* Clear Display */
}

/********************************************************
* wLCDdat - Write data word to LCD peripheral *
* Enter with data word in accumulator *
* Delay ÷120µS after data write *
********************************************************/
void wLCDdat(unsigned char data)
{
unsigned char LCDdata;

LCDdata = data >> 4; /* Write HI nibble word to LCD */;


P3OUT = LCDdata;
P2OUT |= LCD_RS ; /* RS->1 */
P2OUT |= LCD_E ; /* E->1 */
P2OUT &= ~LCD_E ; /* E->0 */
P2OUT &= ~LCD_RS ; /* RS->0 */
LCDdata = data & 0x0f; /* Write LO nibble word to LCD */
P3OUT = LCDdata;
P2OUT |= LCD_RS ; /* RS->1 */
P2OUT |= LCD_E ; /* E->1 */
P2OUT &= ~LCD_E ; /* E->0 */
P2OUT &= ~LCD_RS ; /* RS->0 */
index = 20;
while (--index); /* 120 µsec */
}

/*********************************************************
* wLCDctrl - Write control word to LCD peripheral *
* Enter with control word in accumulator *
* Delay ÷4.5mS if A=0x01 or 0x02 else delay ÷120æS *
*********************************************************/
void wLCDctrl (unsigned char ctl)
{

P3OUT = ctl ;
P2OUT |= LCD_E ; /* E->1 */
P2OUT &= ~LCD_E ; /* E->0 Pulse the enable line */
index = 20 ;
while (--index) ; /* ((6 * 19) + 2) 120 µsec delay loop */
if (ctl <= 2)
{
while (--index); /* 4.6 ms or so delay */
while (--index);
while (--index);
}
}
/*********************************************************
* wLCDctrl4 - Write control word to LCD peripheral *
* configured as a 4 bit interface *
* Enter with control word in accumulator *
* Delay ÷4.5mS if A=0x01 or 0x02 else delay ÷120µS *
*********************************************************/
void wLCDctrl4(unsigned char ctl)
{
unsigned char LCDPort4;
LCDPort4 = ctl >> 4; /* Write HI nibble word to LCD */;
P3OUT = LCDPort4;
P2OUT |= LCD_E ; /* E->1 */
P2OUT &= ~LCD_E ; /* E->0 */
LCDPort4 = ctl & 0x0f; /* Write LO nibble word to LCD */
P3OUT = LCDPort4;
P2OUT |= LCD_E ; /* E->1 */
P2OUT &= ~LCD_E ; /* E->0 */
index = 20;
while (--index); /* 120 µsec */
if (ctl <= 2)
{
while (--index); /* 4.6 ms or so delay */
while (--index);
while (--index);
}
}

/*********************************************************
* Send a character to the LCD display *
*********************************************************/
void putcharLCD(unsigned char car)
{
if ((car == 0x0a) || (car == 0x0d)) /* Look for a LF */
{
wLCDctrl(0x02) ; /* Home */
wLCDctrl4(0x01); /* Clear Display */
}
else
wLCDdat(car);
}

/*********************************************************
* Write a string to the LCD display *
*********************************************************/
void cputsLCD(char *putstr)
{
while(*putstr !=0)
putcharLCD(*putstr++);
}
void main (void){

initLCD();
cputsLCD ("You’ve done it!");
for (;;) ;
}
Exemple de base de temps

//***************************************************************************
// MSP430F22x4 Demo - Timer_A, Toggle P1.0, TACCR0 Cont. Mode ISR, DCO SMCLK
//
// Description: Toggle P1.0 using software and TA_0 ISR. Toggles every
// 50000 SMCLK cycles. SMCLK provides clock source for TACLK.
// During the TA_0 ISR, P1.0 is toggled and 50000 clock cycles are added to
// TACCR0. TA_0 ISR is triggered every 50000 cycles. CPU is normally off and
// used only during TA_ISR.
// ACLK = n/a, MCLK = SMCLK = TACLK = default DCO ~1.2MHz
//
// MSP430F22x4
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
// A. Dannenberg
// Texas Instruments Inc.
// April 2006
// Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
//***************************************************************************
#include "msp430x22x4.h"

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = 50000;
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode

__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt


}

// Timer A0 interrupt service routine


#pragma vector=TIMERA0_VECTOR // set vector for interrupt
__interrupt void Timer_A (void) // routine declaration
{
P1OUT ^= 0x01; // Toggle P1.0
TACCR0 += 50000; // Add Offset to TACCR0
}
Schéma électrique

Vous aimerez peut-être aussi