Vous êtes sur la page 1sur 18

Pinel Olivier CUST Génie

électrique
Vivion Nicolas 1ère année

Compte rendu de TP
microcontrôleur
Session 2005

Sommaire :

1 : Introduction…………………………………………………………………

2 : Schéma fonctionnel…………………………………………………………

3 : Architecture du système…………………………………………………….

4 : Organigramme du programme………………………………………………

1 : Programme principal…………………………………………………

2 : Affichage LCD………………………………………………………

3 : Saisie valeur…………………………………………………………

4 : Attendre touche……………………………………………………..

5 : Com_LCD / Affich_LCD…………………………………………..

6: Phrase LCD………………………………………………………….

7: Lecture touché……………………………………………………….

5 : Code commenté……………………………………………………………..

6 : Performances et fonctionnalités effective…………………………………..

7 : Ressources mémoires utilisées et durée d’exécution des fonctions……..….

8 : Conclusion…………………………………………………………………..
1 : Introduction

Le but de ce TP est la réalisation d’un système de génération de signaux modulés


en largeur d’impulsion géré par un microcontrôleur de type Mitsubishi M16C6NA.
Les signaux pourront être de trois types : mode normal, mode variation
sinusoïdale du rapport cyclique et mode étalement de spectre. Le choix du mode ainsi que
les paramètres de configuration des signaux sera effectué grâce à un menu mis en place
sur un afficheur LCD. On entrera ces données à l’aide d’un clavier.

Dans le détail, les MLI seront configurés grâce aux paramètres suivants :

Pour la MLI de type normal :


- fréquence ( de 1kHz à 50kHz)
- rapport cyclique ( de 10% à 90%)

Pour la MLI à variation sinusoïdale du rapport cyclique :


- fréquence (de 1kHz à 50kHz)
- rapport cyclique moyen (de 10% à 90%)
- fréquence de modulation du rapport cyclique (de 5Hz à 50Hz)

Pour la MLI à étalement de spectre :


- fréquence moyenne (de 1kHz à 50kHz)
- dérive de la fréquence (de 5% à 25%)
- rapport cyclique moyen (de 10% à 90%)
- dérive du rapport cyclique (de 5% à 25%)

Pour réaliser ce TP, nous avons à notre disposition :


- une platine microcontrôleur entièrement câblée
- un afficheur LCD à 4 lignes et 16 caractères
- un clavier 12 touches
- une alimentation
- un ordinateur de type PC
- la chaîne de développement TM
- des plaques de test à diodes

2 : Schéma fonctionnel

On a partagé le problème en 4 grandes fonctions :


- une fonction de saisie de données qui englobe la gestion du clavier
- une fonction de traitement des données pour qu’elles soient utiisables
- une fonction d’affichage qui correspond à la gestion de l’afficheur
LCD
- une fonction de génération des MLI

3 : Architecture du système
Pour ce système, on utilise plusieurs périphériques du microcontrôleur .

Tout d’abord, on a besoin d’un port pour connecter le clavier. A cette fin, on
utilisera le port 10 qui permet de configurer des interruptions sur réception de touche s’il
arrivait qu’on en ait besoin.

Il nous faut aussi 2 ports pour l’afficheur LCD. Un pour les données et un pour les
signaux d commande si on effectue des transferts de données de 8 bits. On utilisera donc
le port 2 pour transmettre les données à l’afficheur et les bits 0,1 et 2 du port 1 pour les
signaux de commande ( RS, R/W et E).

Pour générer la MLI, il nous faut une broche de sortie. On a choisi de prendre la
broche 0 du port 3.

Enfin pour générer une MLI, on utilise 2 timers, l’un configuré en astable et
l’autre en monostable. Ce dernier ce déclenchera sur débordement du premier. On
prendra dans notre système les timers A0 et A1.
4 : Organigramme du programme

1 : Programme principal
2 : Affichage LCD
3 : Saisie valeur

4 : Attendre touche
5 : Com_LCD / affich_LCD

6: Phrase_LCD

7 : Lecture touche
5 : Code commenté

/********************************************************/
/* TEST PROGRAM FOR M16C6N0 board */
/* FILENAME: ports.c */
/* WRITTEN BY: PINEL/VIVION */
/* DESCRIPTION: */
/* Génération de MLI */
/* avec gestion par clavier et écran LCD */
/* simulateur et cible ( non compatible debbugger ) */
/********************************************************/

#include "sfr62.h"
#include <math.h>

void initport(void); //Initialisation des ports

void delay ( int x); //Fonction de temporisation


void com_lcd( char x); //Envoie d'une commande au LCD
void affich_lcd( char x); //Affichage d'un caractère sur le LCD
void phrase_lcd (char *x); //Affichage d'une phrase sur le LCD
void init_lcd(); //Initialisation du LCD

char touche(void); //Scrutation du clavier


void attendretouche( void); //Attente d'une nouvelle touche

//Saisie d'une valeur de n caractères au clavier comprise entre min et


max
long int saisievaleur(long int n,long int min,long int max);

void MLI1 (void); //Paramétrage de la MLI simple


void MLI2 (void); //Paramètrage de la MLI sinusoïdale
void MLI3 (void); //Paramétrage de la MLI à étalement de spectre

void init_TA(void); //Initialisation des timers


void TA0int (void); //Interruption due au timer A0
void TA1int (void); //Interruption due au timer A1

//Déclaration des phrases utilisées dans le programme


char ph1[]="F: ";
char ph2[]="RC: ";
char ph3[]="RC moy: ";
char ph4[]="F RC: ";
char ph5[]="F moy: ";
char ph6[]="Dériv F: ";
char ph7[]="Dériv RC: ";
char ph8[]="1:MLI 1";
char ph9[]="2:MLI 2";
char ph10[]="3:MLI 3";
char ph11[]="Votre choix : ";

void main(void)
{
int x;

initport(); //Initialisation des ports


init_lcd(); //Initialisation du LCD
init_TA(); //Initialisation des timers

while (1) //Boucle principale


{
com_lcd(0x01); //Effaçage de l'écran
com_lcd(0x80); //Positionnement du curseur sur la
première ligne
phrase_lcd(ph8); //Affichage de ph8
com_lcd(0xC0); //Positionnement du curseur sur la 2éme
ligne
phrase_lcd(ph9); //Affichage de ph9
com_lcd(0x90); //Positionnement du curseur sur la 3ème
ligne
phrase_lcd(ph10); //Affichage de ph10
com_lcd(0xD0); //Positionnement du curseur sur la 4ème
ligne
phrase_lcd(ph11); //Affichage de ph11

x=saisievaleur(1,0,9); //Lecture et affichage d'une touche


comprise entre // 0 et 9
switch (x) //Selon la touche
{
case 1 :MLI1(); //Effectuer MLI1
break;
case 2 :MLI2(); //Effectuer MLI2
break;
case 3 :MLI3(); //Effectuer MLI3
break;
}
}
}

void initport(void) //Paramétrage des ports


{
pd1=0xFF; //P1 en sortie | port de données du LCD
pd2=0xFF; //P2 en sortie
// port de commande du LCD (bits 0,1
et 2)
pd3=0xFF; //P3 en sortie | port de sortie de la
MLI
pd10 = 0x0F; //P10:bits 0 à 3 en sortie, bits 4 à 7 en
entrée // port pour le clavier
pu25=1; //Pull-up sur les bits 4 à 7 de P10
}

void delay ( int x) //Fonction de temporisation d'environ x µs


{
x=(x*4)/3;
while (x!=0)
x--;
}
void com_lcd( char x) //Envoie d'une commande au LCD
{
p1_1=0; //R/W=0, On écrit
p1_0=0; //RS=0, Mode commande
p2=x; //On écrit le code de la commande sur le
port
p1_2=1; //On mets l'enable à 1 (Données stables)
delay(0); //On attends un peu
p1_2=0; //On remets l'enable à 0
delay(4100); //On attends que la commande soit prise en
compte
//4,1 ms est le temps maximal de prise en
compte // d'une commande
}

void affich_lcd( char x) //Affichage d'un caractère sur le LCD


{
p1_1=0; //R/W=0, On écrit
p1_0=1; //RS=1, Mode affichage
p2=x; //On écrit la valeur du caractère sur le
port
p1_2=1; //On mets l'enable à 1 (Données stables)
delay(0); //On attends un peu
p1_2=0; //On remets l'enable à 0
delay(100); //On attends que l'affichage soit pris en
compte // (100 µs maximum)
}

void phrase_lcd (char x[]) //Affichage d'une phrase sur le LCD


{
int i=0;
while (x[i]!=0) //Tant que le caractère de la chaine est
non nul
{
affich_lcd(x[i]); //On affiche le caractère
i++; //On passe au caractère suivant
}
}

void init_lcd() //Initialisation du LCD


{
com_lcd(0x38); //Séquence de reset
com_lcd(0x38);
com_lcd(0x38);
com_lcd(0x38); //Définition de la taille des données, du
nombre // de lignes et de la taille de la
police
com_lcd(0x06); //Mode d'entrée ( On incrémente sans
bouger // l'écran)
com_lcd(0x0E); //On allume l'écran, le curseur sans carré
noir
com_lcd(0x01); //On efface l'écran
com_lcd(0x80); //Positionnement du curseur en début de
première ligne
}

char touche(void) //Scrutation clavier


{
char retour; //Variable temporaire
retour=0; //Si aucune touche n'est enfoncé on
renvoie 0
delay(20); //Temporisation pour éviter les rebonds
p10=0x0E; //Sélection de la première ligne
switch (p10) //Selon le code lu sur le port on
détermine la // touche enfoncée
{
case 0xBE:
retour ='1';
break;
case 0xDE:
retour ='2';
break;
case 0x7E:
retour ='3';
break;

}
p10=0x0D; //Sélection de la 2ème ligne
switch (p10) //Selon le code lu sur le port on
détermine la // touche enfoncée
{
case 0xBD:
retour ='4';
break;
case 0xDD:
retour ='5';
break;
case 0x7D:
retour ='6';
break;
}

p10=0x0B; //Sélection de la 3ème ligne


switch (p10) //Selon le code lu sur le port on
détermine la // touche enfoncée
{
case 0xBB:
retour ='7';

break;
case 0xDB:
retour ='8';
break;
case 0x7B:
retour ='9';
break;

}
p10=0x07; //Sélection de la 4ème ligne
switch (p10) //Selon le code lu sur le port on
détermine la // touche enfoncée
{
case 0xB7:
retour ='*';
break;
case 0xD7:
retour ='0';
break;
case 0x77:
retour ='#';
break;

}
return retour; //On renvoie la valeur de la touche ou 0
si // aucune n'est enfoncée
}

void attendretouche() //Attente d'une nouvelle touche ( touche


//relevée puis appuyée)
{
char touch;
touch=touche(); //Lecture de la touche enfoncée
while(touch!=0) //Tant qu'elle n'est pas égale à 0 on la
relit
{touch=touche();}
while(touch==0) //Tant qu'elle est égale à 0 on la relit
{touch=touche();}

long int saisievaleur(long int n,long int min,long int max)


//Saisie d'une valeur de n caractères au clavier comprise entre min et
max
{
char touch;
long int i;
long int valeur;

valeur=0;
i=0;

attendretouche(); //Attente d'une nouvelle touche


touch=touche(); //Lecture de la touche
while (touch!='#'&&i!=n) //Tant que la touche n'est pas # et
que //la longueur saisie ne dépasse pas
n
{
valeur=valeur*10+(touch-'0'); //valeur = valeur *10 +
binaire(touch)
i++; //On incrémente la longueur de la saisie
affich_lcd(touch); //On affiche la touche sur le LCD
attendretouche(); //Attente d'une nouvelle touche
touch=touche(); //Lecture de la touche
}
if (valeur<=min) //Si la valeur saisie est plus petite que
min
valeur=min; //valeur = min
if (valeur>=max) //Si la valeur est plus grande que max
valeur=max; //valeur = max

return(valeur); //On renvoie valeur

void MLI1 (void) //MLI simple


{
long int f;
long int temp;
long int RC;
long int temp1;

com_lcd(0x01); //On efface l'écran


com_lcd(0x80); //Positionnement du curseur sur la 1ère
ligne
phrase_lcd(ph1); //Affichage de ph1
com_lcd(0xC0); //Positionnement sur la 2ème ligne
phrase_lcd(ph2); //Affichage de ph2
com_lcd(0x90); //Positionnement du curseur sur la 3ème
ligne
phrase_lcd(ph11); //Affichage de ph11
com_lcd(0x84); //Positionnement du curseur après ph1
f=saisievaleur(5,10000,50000); //Saisie d'une fréquence entre
1K //et 50KHz
com_lcd(0xC5); //Positionnement du curseur apès ph2
RC=saisievaleur(2,10,90); //Saisie du rapport cyclique entre
10 et 90%
temp =(8000000/f); //Réglage du temps de comptage du
timer A0
ta0=temp;
temp1=(RC*temp)/100; //Réglage du temps de comptage du
timer A1
ta1=temp1;
}

void MLI2 (void) //MLI sinusoïdale


{ //Idem précédemment: Affichage menu et saisie
des // valeurs
long int f;
long int frc;
long int moyRC;
long int temp;

com_lcd(0x01);
phrase_lcd(ph1);
com_lcd(0xC0);
phrase_lcd(ph3);
com_lcd(0x90);
phrase_lcd(ph4);
com_lcd(0xD0);
phrase_lcd(ph11);
com_lcd(0x84);
f=saisievaleur(5,1000,50000);
com_lcd(0xC9);
moyRC=saisievaleur(2,10,90);
com_lcd(0x97);
frc=saisievaleur(2,5,50);
temp =(8000000/f);
ta0=temp;
temp=(moyRC*temp)/100;
ta1=temp;
//Calculs...
}

void MLI3 (void) //MLI à étalement de spectre


{ //Idem
int fmoy;
int derivF;
int RCmoy;
int derivRC;

com_lcd(0x01);
phrase_lcd(ph5);
com_lcd(0xC0);
phrase_lcd(ph6);
com_lcd(0x90);
phrase_lcd(ph3);
com_lcd(0xD0);
phrase_lcd(ph11);
com_lcd(0x88);
fmoy=saisievaleur(5,1000,50000);
com_lcd(0xCA);
derivF=saisievaleur(2,5,25);
com_lcd(0x99);
RCmoy=saisievaleur(2,10,90);
com_lcd(0xDB);
derivRC=saisievaleur(2,5,25);
//Calculs...
}

void init_TA(void) //Initialisation des timers


{
ta0mr=0x00; //Timer A0 en mode compteur
ta1mr=0x12; //Timer A1 en monostable
ta0=160; //Initialisation du timer A0 à 160 (MLI de
//fréquence 50KHz)
ta1=80; //Initialisation du timer A1 à 80 (MLI de
rapport //cyclique 1/2)
ta0ic=0x07; //Interruption de TA0 de degré 7
ta1ic=0x07; //Interruption de TA1 de degré 7
udf=0x0F; //Compteurs en mode count up
trgsr=0x02; //Déclenchement du timer A1 sur débordement du
//timer A0
tabsr=0x03; //Démarrage des timers A0 et A1
}

#pragma INTERRUPT TA0int


void TA0int(void) //Interruption du timer A0
{
asm("fset I");
p3_0=1; //Mettre la broche 0 du port 3 à 1
}

#pragma INTERRUPT TA1int


void TA1int(void) //Interruption du timer A1
{
asm("fset I");
p3_0=0; //Mettre la broche 0 du port 3 à 0
}

6 : Performances et fonctionnalités effectives

A l’issue de ce TP, notre programme permet d’afficher un menu sur l’afficheur


LCD grâce à des fonctions qui permettent d’afficher des phrases et de déplacer le curseur.
La saisie de données grâce au clavier se fait sans problème, on peut saisir une valeur et
limiter le nombre de caractère de cette saisie ainsi que ses valeurs minimale et maximale.
Enfin, le programme permet de générer une MLI simple sur la broche 0 du port 3 qui
respecte la gamme de fréquence et de rapport cyclique du cahier des charges.

7 : Ressources mémoires utilisées et durée d’exécution


des fonctions
Les phrases utilisées pour les différents menus sont des variables globales qui
utilisent environ 100 adresses mémoires.
Le programme lui, est stocké à partir de l’adresse 0x0F006D est utilise 0xC61
adresses mémoire.
En ce qui concerne la durée d’exécution des fonctions, la mesure de ces durées
est assez dure à mettre en place car seul le logiciel de simulation PDSIM permet de le
faire. On ne peut donc mesurer que les temps des fonctions qui ne font pas appel aux
matériel (en fait on doit pouvoir en simulant des évènements mais la prise en main du
logiciel aurait pris beaucoup trop de temps).
Voilà tout de même les temps relevés :

- init_port : 26 cycles, 1µs


- init_lcd : 526196 cycles, 32,887 ms
- init_TA : 34 cycles, 2µs
- com_lcd : 65772 cycles, 4,11ms
- affich_lcd : 1802 cycles, 112µs
- delay (x) : ( x + 2) µs

8: Conclusion

Ce TP nous a permis de mieux comprendre le fonctionnement d’un processeur et


de ces périphériques à travers des manipulations concrètes. Il nous a également permis
d’appréhender une méthode de travail pour réaliser un projet et de maîtriser les outils de
développement associés.
Le programme rendu ne réponds pas complètement au cahier des charges
puisque seule la MLI normale fonctionne. En effet nous n’avons pas eu le temps de
coder les deux autres. De plus, si nous avions eu le temps de terminer, il aurait été
possible d’optimiser les temps d’affichage et de commande de l’afficheur LCD en
scrutant le busy flag plutôt que de faire une attente maximale.

Vous aimerez peut-être aussi