Académique Documents
Professionnel Documents
Culture Documents
Présentation
Un microcontrôleur à une forme d'un circuit intègre comme on le voit sur la photo mais il diffère des autres circuits intégrés par :
les circuits intégrés ont une fonction précise et seul un petit nombre d'entre eux en ont plusieurs
le microcontrôleur n'a pas une fonction précise mais il peut en avoir plusieurs dizaines qui peuvent être programmé par l'utilisateur
__________________________________________________________________________________________________________________
Le microcontrôleur qu'on va utiliser le pic 16f877A« Peripheral Interface Controller » est un microcontrôleur à 40 broches fabriqué par
la Société américaine
MICROCHIP Technology Inc. - Arizona – USA
Il contient :
8 ko de mémoire flash , 368 de mémoire de donnée, 256 de mémoire EEPROM de donnée 33 entrée/sortie 8 canaux CAN.
BROCHAGE
Une alimentation :
comme le pic ne peut pas supporter plus que 5 volt
un régulateur avec ses capacités ont été utilisés pour réguler cette tension et protéger le
pic
Un signal de reset:
bouton poussoir et résistance 10 k
Une horloge:
un quartz et ces capacité
Sur ISIS
En mode composant, cliquer sur P, une boite de dialogue apparaît permettant le choix du composant
dans la bibliothèque disponible
Dans Keywords saisissez pic16f877
Double cliquer sur le composant choisi pour le mettre dans la liste des composants
procéder de la même façon pour choisir le quartz( crystal) ,la résistance (res) , la
capacité (cap) , potentiomètre (POT_LIN), LED , Afficheur 7 segment (7seg) ...
Les labels du bus sont édités en pointant droit l'objet, dans le menu contextuel cliquer gauche sur ( place wire label )
une fenêtre de dialogue apparaîtra avec les onglet Label et style
Placer les différents composants ainsi que les bornes d'alimentations
Relier les pour former notre circuit de base
Remarque : on a pas besoin d’alimenter le pic Isis l'a fait à notre place .
Éditer le label de vcc en double cliquant sur
la borne d'alimentation power
( on change les valeurs d'un composant
en éditant ses propriétés par un double clic gauche )
Noter que pour limiter le courant, des résistance de 220 Ohm ont été mises en série avec les leds
Pour plus de détail télécharger le cours détaillé sur Isis
Retour
Maintenant que notre circuit de base est prêt on va commencer à écrire nos premiers programmes avec MIKROC .
On crée un nouveau projet ( Project --> New Projet ) nommé LED dans le répertoire picfiles ,on choisi le pic16f877A et un quartz de 8Mhz
pour le config on clique sur default
Expérience 1
Entrées Sorties
Notre premier programme consiste a manipuler les ports I/O .
Dans le pic les ports sont contrôlés par des registres de direction 8 bits : TRISX (X = A, B, C, ou D)
chaque bit de ces registres est associé au bit du même rang du port
Les bits à 1 indique que la broche correspondant est en entrée
Les bits à 0 indique que la broche correspondant est en sortie
donc avant l'utilisation des ports les registres TRISX doivent êtres positionnés
dans notre cas les ports b0 b1 b2 b3 doivent être en sortie pour commander les leds
void main() {
Après compilation s'il n' y a pas d'erreurs les fichier led.hex est créé
Dans isis on double clique sue le microcontrôleur et on spécifie le fichier led .hex qui se trouve dans le dossier picfiles puis OK
Par la suite lancer la simulation ( le bouton play du panneau de contrôle de l'animation) .
Si toute les étapes se sont bien passées les leds vont être allumés .
Maintenant on va transformer notre programme pour que les leds clignote .
void main() {
trisb= 0b11110000 ; // b7 b6 b5 b4 b3 b2 b1 b0
// 1 1 1 1 0 0 0 0
while(1) // boucle infini
{
portb = 0b1111111 ; // les leds éteintes
delay_ms(1000) ; // temporisation // d'une
seconde
portb = 0b11110000 ; // les leds allumées
delay_ms(1000) ; // temporisation d'une /
/ seconde
}
}
Écrire le programme suivant chaque led s’allume 200 ms puis s’éteint pour former un chenillard
void main() {
trisb= 0b11110000 ; // b7 b6 b5 b4 b3 b2 b1 b0
// 1 1 1 1 0 0 0 0
while(1) // boucle infini
{
portb = 0b11110000 ; // les leds éteintes
delay_ms(200) ; // temporisation
portb = 0b11110001 ; //led 0 allumée
delay_ms(200) ; // temporisation
portb= 0b11110010 ; //led 0 éteinte led 1 allumée
delay_ms(200) ; // temporisation
portb = 0b11110100 ; //led 1 éteinte led 2 allumée
delay_ms(200) ; // temporisation
portb = 0b11111000 ; //led 2 éteinte led 3 allumée
delay_ms(200) ; // temporisation
}
}
Dans notre exemple on a allumé les led on agissant sur le port en entier on peut accéder individuellement à chaque bit on utilisant les identifiant
F0, F1, ......, F7, F7 étant le bit du poid fort , pour allumer la led 0 on écrit Portb.F0 = 1 ;
Exercice 1 :
transformer le programme précédent on utilisant les identifiants
correction
Expérience 2
Afficheur 7 Segments
Dans cette expérience on va apprendre à contrôler un afficheur 7 segment :
Comme vous le voyez sur la figure il existe deux types d'afficheur, anode commune AC et cathode
commune CC ( noter le sens des diodes et l'alimentation des afficheurs )
Pour les AC les diodes sont allumés par la présence d'un état 1 et pour les CC par un état 0
Donc pour afficher un chiffre on doit présenter sur les broches du circuit le code 7 segment correspondant
Mikroc vous permit de former ce code en allant dans
Touls ---> seven Segment Decoder
void main() {
trisb= 0b10000000 ; // b7 b6 b5 b4 b3 b2 b1 b0
// 1 0 0 0 0 0 0 0
Jusqu’à présent on n' a pas utilisé les port en entrée, dans l'exemple suivant on va utiliser deux
boutons poussoir bp1 et bp2 .
lorsque on appuis sur bp1 ou sur bp2 on affiche successivement 3 ou 4
pour le dessin du bus et des entrée sortie voir choix des bornes
Les labels du bus sont édités en pointant droit l'objet, dans le menu contextuel cliquer gauche sur (
place wire label ) une fenêtre de dialogue apparaîtra avec les onglet Label et style
void main() {
PORTB =00 ;
TRISB = 0 ;
PORTC = 0 ;
TRISC = 0xC0; // RC7 ET RC6 EN ENTREE
Exercice 2
Exercice 3
Écrire un programme qui permet d’incrémenter le chiffre affiché en appuyant sur un bouton poussoir
correction
Expérience 3
Afficheur 7 Segments 2
Dans cette expérience on va essayer de contrôler trois afficheurs
Principe :
La technique est basée sur le phénomène de la persistance rétinienne , on dispose plusieurs afficheurs branchés sur le même bus, puis on
les sélectionne à tour de rôle à l'aide de transistors de commutation pour afficher un chiffre, si le balayage se fait assez rapidement
l’œil a l'impression que tout les afficheurs sont tous allumés simultanément et affiche le nombre voulu
void main() {
trisb= 0b10000000 ; // b7 b6 b5 b4 b3 b2 b1 b0
// 1 0 0 0 0 0 0 0
trisc = 0 ; //portc en sortie
while(1) // boucle infini
{
portb = 0xB0 ; // code 7seg du chiffre 3
portc.f0 = 1 ; //t1 passant
delay_ms(20) ; // temporisation 20 ms
portc.f0 = 0 ; // t1 bloqué
portb = 0x99; // code 7seg du chiffre 4
portc.f1 = 1 ; t2 passant
delay_ms(20) ; // temporisation 20 ms
portc.f1 = 0 ; //t2 bloqué
portb = 0xB0 ; // code 7seg du chiffre 3
portc.f2 = 1 ; t3 passant
delay_ms(20) ; // temporisation 20 ms
portc.f2 = 0 ; //t3 bloqué
Remarque : Dans la simulation avec isis contrairement à la réalité l'affichage n'est pas fixe c'est du au temps de latence du logiciel
Expérience 4
Conversion Analogique Numérique
Dans cette expérience on va apprendre a utiliser le module CAN <Conversion Analogique numérique >
le signal à convertir peut être une tension d'un capteur qu'on va simuler par un potentiomètre
le résultat de la conversion 10 bits est stocké dans les registres ADRESH et ADRESL qu'on ne va pas utiliser
car Mikroc a une fonction Adc_Read(0) qui nous retourne directement le résultat
Expérience 5
Conversion Analogique Numérique 2
Projet1
Un système sert à compter 12 boites de conserve, à mettre dans une caisse par rupture d'un fuseau infrarouge
Le convoyeur ne démarre que si une nouvelle caisse est présente
- Donne l'ordre en commandant un vérin pour déplacer la caisse pleine
- Afficher le nombre de boites restantes
Écrire un programme à embarquer dans ce système
Expérience 6
Communication Série
Notre programme consiste à envoyer au terminal les textes : bas, haut, droit, gauche. selon le bouton sélectionné
int derect ;
int i ;
char mesG[] = {'g','a','u','c','h','e'} ;
char mesD[] = {'d','r','o','i','t','e'} ;
char mesH[] = {'h','a','u','t' } ;
char mesB[] = {'b','a','s'} ;
void main() {
TRISc = 0x00;
TRISD = 0xf0; // PORTC en entrée
Usart_init(9600);
while(1) {
derect = (PORTD & 0b11110000 ) ; // masquer les bit non utilisés
switch (derect)
{ case 0b01110000 :
for (i=0 ;i<6 ;i++ )
Usart_Write(mesG[i]);
Usart_Write(13); //retour a la ligne
break ;
case 0b10110000 :
for (i=0 ;i<4 ;i++ )
Usart_Write(mesH[i]);
Usart_Write(13);
break ;
case 0b11010000:
for (i=0 ;i<3 ;i++ )
Usart_Write(mesB[i]);
Usart_Write(13);
break ;
case 0b011100000:
for (i=0 ;i<6 ;i++ )
Usart_Write(mesD[i]);
Usart_Write(13);
break ;
} delay_ms(200) ; //attente relachement bouton
}}
Exercice 4
Rajouter a l'expérience précédente quatre Leds qui indiquent le sens ( haut, bas, droite, gauche )
chaque Led s'allume en appuyant sur les bouton correspondant
Expérience 7
PWM modulation de largeur d’impulsion
PWM ou MLI (Pulse Width Modulation )est un signal dont le rapport cyclique varie.
PWM est utilisé dans:
La commande des servomoteur
La variation de vitesse des moteurs
La conversion numérique analogique
Le PIC utilise le module CCP Capture/Compare/PWM en mode PWM la broche RC1 doit être
configuré en sortie, la valeur de la période est chargé Dans le registre PR2 et la valeur du rapport
cyclique dans le registre CCPRL
Le TIMER2 compte l'horloge interne après une pré division programmable par 1.4ou 16
Quand Timer2 atteint la valeur dans PR2 : Timer2 passe a zéro, la broche PWM est mise a 1
Quant Timer2 atteint la valeur dans CCPR1L la sortie PWM est mise 0
PÉRIODE = (PR2+1) X Tosc X 4 X valeur du pré diviseur
DURÉE = CCPR1L X Tosc X valeur du pré diviseur
Notre programme consiste à générer un signal PWM de fréquence 2 Khz et dont le rapport cyclique
varie continuellement
char i ;
void main() {
TRISB = 0; // PORTB en sortie
TRISC = 0; / PORTC en sortie
Pwm_Init(2000); // Initialise PWM a 2 Khz
i =0 ;
while (1)
{
Pwm_Start(); // Demarre PWM
i= i+10 ; // incrémentation par 10 du rapport cyclique
Pwm_Change_Duty(i); // changer le rapport
cyclique
Expérience 8
Afficheur LCD
Ce composant est spécialement fabriqué pour être utilise avec des microcontroleur,ce qui signifie qu'il ne peut pas être activé par des circuits
standards.il est utilisé pour afficher différents messages .le modèle décrit ici est pour son prix bas et ses capacité, le plus fréquemment utilisé
dans la pratique. il est basé sur le microcontrôleur HD44780 de HITACHI et peut afficher des message sur deux ligne de 16 caractères
chacune.
Brochage
Fonction
N° Nom état Logique Description
masse 1 Vss - 0V
alimentation 2 Vdd - +5V
Contrast 3 Vee - 0 - Vdd
0 D0 – D7 are interprété comme commands
4 RS
1 D0 – D7 are interprété comme donnée
0 Write data (from controller to LCD)
Operation 5 R/W
1 Read data (from LCD to controller)
Control
0 Access to LCD disabled
6 E 1 Normal operating
From 1 to 0 Data/commands are transferred to LCD
Data / commands 7 D0 0/1 Bit 0 LSB
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 MSB
Commande de base
Toutes les données transférées à un écran LCD à travers les broches D0-D7 seront interprétées comme une commande ou une donnée,
qui dépend de l'état logique de la broches RS:
· RS = 1 - Bits D0 - D7 sont les codes des caractères à afficher.
· RS = 0 - Bits D0 - D7 sont des commandes pour le réglage du mode d'affichage.
Pour information Voici une liste des commandes reconnues par l'écran LCD:
Vous n'aurez pas à utiliser Ces commandes car Mikroc dispose de fonctions qui vous permettent d'utiliser Le LCD
Lcd_Config défini le port à associer au broches du LCD les paramètres RS, EN, WR, D7......D4 doivent être une combinaison de 0-
7
exemple Lcd_Config(&PORTD, 0, 1, 5, 7, 3, 2, 4, 6)
Remerque : cette fonction n'existe pas dans les version supérieures on emploi l'instruction sbit pour attribuer chaque broche du LCD un une broche du
pic, exemple :
// définition du sens
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D7_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB0_bit;
Lcd_Init associe les broches du LCD au port celon la configuration par défaut
D7 → port.7
D6 → port.6
D5 → port.5
D4 → port.4
E → port.3
RS → port.2
RW → port.0
void main() {
TRISB = 0; // PORTB en sortie
Lcd_Init(&PORTB); // Initialisation LCD
connecté au PORTB
Lcd_Config(&PORTB, 2, 3, 1, 7, 6,5, 4);
Lcd_Out(1, 2, text) ; // écrire le texte à,1°
ligne 2° colonne
}
Exercice 5
même exercice que Ex4 au lieu du terminal mettre un LCD
Expérience 8
Écriture et Lecture d'une mémoire I2C
La norme I2C( Inter component communication ) de philips permet la communication de déférents composants électroniques sur deux lignes
SDA signal Data et SCL Signal Clock , le bus I2C est géré par au moins un maitre
dans notre expérience on va écrire un programme permettant l’écriture et la lecture dans une mémoire 24C16
les fonctions C utilisées sont :
I2C_Init : initialise le bus à une fréquence désiré
I2C_start : début de communication
I2C_Repeated_Start();
I2C_WR : envoi d'une donnée
I2C_RD : lecture d'une donnée
L'image suivante explique l’opération de lecture et d’écriture dans l'eeprom
Le maitre envoi le signal Start suivi du premier octet composé de l'adresse de l'esclave et une partie
de l'adresse ou sera stocker la donnée, le huitième peut être un 0 si il s'agit d'une écriture ou un 1 dans
le cas de lecture, après acquittement par l'esclave le maitre envoi le deuxième octet qui est la deuxième
partie de l'adresse ou sera stocké ou lu, la donnée puis le troisième octet qui 'est la donnée dans le cas
d’écriture suivi du signal Stop
maintenant on va essayer de traduire tout ça en Mikroc, on va écrire la valeur 0XE5 à la
position 1000 d = 01111101000 b
0X03E8 puis on va la relire et l'afficher sur des leds
il faut noter que l'eeprom est caractérisée par l'adresse 1010 quelle que soit sa taille
pour adresser les 2Ko on a besoin de 11 bits (2048 = 2^11)
les quatre bits du premier octet sont 1010 qui caractérise les eeprom I2C, les trois suivant sont les trois
bits du poids fort de l'adresse, le dernier est un 0 pour écriture. donc le premier octet sera 10100110 =
0XA6.
le deuxième c'est c'est ce qui reste de l'adresse soit 11101000 =0XE8.
le dernier octet c'est la donnée 0XE5.
la lecture se fait en 2 étape la première est semblable à une opération d’écriture sans donnée suivi d'un
signale de start puis l'adresse 10100110 = 0XA6. +1 = 10100111 = 0XA7.la donnée est récupéré
par l'instruction I2C_Rd(0)
notre programme sera
donc
void main()
{
I2C_init (100000) ; // en général une fréquence de 100000hz
I2C_Start() ; //convient pour la plupart des aplications
I2C_Wr(0xA6) ;
I2C_Wr(0xE8) ;
I2C_Wr(0xE5) ;
I2C_Stop() ;
delay_ms(10) ;
I2C_Start() ;
I2C_Wr(0xA6) ;
I2C_Wr(0xE8) ;
I2C_Repeated_Start();
I2C_Wr(0xA7); // envoi octet par I2C (adress boitier + 1)
PORTB = I2C_Rd(0); la donnée et visualisé sur le portb
I2C_Stop() ;
}
Expérience 9
Gestion d'un clavier matricé
Dans cette expérience on va réaliser un temporisateur électronique, un clavier est utilisé pour saisir le
nombre de seconde qui seront affichées sur l'afficheur 7 segment, le décompte commence dés l'appui sur
la touche #, est une action est exécutée par exemple (rotation moteur, chauffage ...)qu'on va
matérialiser avec une led .
uine fois le temps épuisé la led s’éteint
{
refait :
portc.f2 = 1 ; // Led ON
_dix = mem/16 ;
_unit = mem%16 ;
decr :
while ( _unit > 0 )
{ _unit -- ;
portd = (_dix*16) + _unit;
delay_ms(100) ;
}
if (_dix > 0 )
{ _dix -- ;
_unit = 9 ;
portd = (_dix*16) + _unit;
delay_ms(100) ;
goto decr ;
}
portc.f2 = 0;
portd = mem ;
}
}
}
Expérience 10
Les interruptions
le pic 16f877 possède 14 sources d'interruption qui peuvent être déclenché suite à un événement
matériel ou logiciel
dés l’apparition de l’événement le programme principale est suspendu et le contexte est sauvegardé et le
pic se branche à une routine particulière à la source d'interruption,à sa sortie le pic reprend
l'exécution du programme principale en restaurant le contexte sauvegardé
dans cette experience on va utiliser une interruption matériel générer par l'entrée RB0/INT
dans l’expérience 9, si un événement indésirable ou dangereux survient qu'on va matérialiser par un
bouton poussoir le process s'arrete et ct est affiché
CORRECTION
Ex 1
void main() {
trisb= 0b11110000 ; // b7 b6 b5 b4 b3 b2 b1 b0
// 1 1 1 1 0 0 0 0
while(1) // boucle infini
{
portb = 0b11110000 ; // les leds éteintes
delay_ms(200) ; // temporisation d'une seconde
portb.f0 = 1 ; //led 0 allumée
delay_ms(200) ; // temporisation d'une seconde
portb.f0 =0 ; //led 0 éteinte
portb.f1 = 1 ; // led 1 allumée
delay_ms(200) ; // temporisation d'une seconde
portb.f1 = 0 ; //led 1 éteinte
portb.f2 = 1 ; // led 2 allumée
delay_ms(200) ; // temporisation d'une seconde
portb.f2 = 0 ; //led 2 éteinte
portb.f3 = 1 ; // led 3 allumée
delay_ms(200) ; // temporisation d'une seconde
}
}
Ex2
int i ;
char tab[9] = { 0x3f,
0x06,0x5b,0x4f,0x66,0x6d,0x07,0x7f,0x6f }
void main()
{
PORTB = 0; // Initialize PORTC
TRISB = 0 ;
while(1) {
for ( i=0; i<= 8 ; i++ )
{ portb = tab[i] ;
delay_ms(500) ;
}
}
}
Ex3
int i =0;
char tab[10] = { 0x3f, 0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f } ;
void main()
{ TRISC = 0b11111111 ;
PORTC =0 ;
PORTB = 0; // Initialize LES PORTS
TRISB = 0 ;
while(1) {
if (portc.f7 == 0 )
i++ ;
portb = tab[i] ;
if (i == 9 )
i =0 ;
delay_ms(500) ;
}
}
Ex4
int derect ;
int i ;
char mesG[] = {'g','a','u','c','h','e'} ;
char mesD[] = {'d','r','o','i','t','e'} ;
char mesH[] = {'h','a','u','t' } ;
char mesB[] = {'b','a','s'} ;
void main() {
TRISC = 0x00;
TRISD = 0xff; // PORTC en sortie et PORTD en en entrée
Usart_init(9600);
while(1) {
derect = (PORTD & 0b11110000 ) ; // masquer les bit non utilisés
switch (derect)
{ case 0b01110000 :
portc.f0 =1 ; // LED indiquant Gauche
for (i=0 ;i<6 ;i++ )
Usart_Write(mesG[i]);
Usart_Write(13); //retour a la ligne
break ;
case 0b10110000 :
portc.f1 =1 ; // LED indiquant Haut
for (i=0 ;i<4 ;i++ )
Usart_Write(mesH[i]);
Usart_Write(13);
break ;
case 0b11010000:
portc.f2 =1 ; // LED indiquant Bas
for (i=0 ;i<3 ;i++ )
Usart_Write(mesB[i]);
Usart_Write(13);
break ;
case 0b011100000:
portc.f3 =1 ; // LED indiquant Droit
for (i=0 ;i<6 ;i++ )
Usart_Write(mesD[i]);
Usart_Write(13);
break ;
} delay_ms(200) ; //attente relachement bouton
}}
Ex5
int derect ;
int i ;
char *mesG[] = "gauche";
char *mesD[] = "droite";
char *mesH[] = "haut";
char *mesB[] = "bas" ;
void main() {