Document Formation Mikroc Finale
Document Formation Mikroc Finale
Document Formation Mikroc Finale
MINISTÈRE DE L’ÉDUCATION
D.R.E. SFAX1
de la famille PIC
de présent manuscrit.
Le langage mikroC pour PIC a trouvé une large application pour le développement de systèmes embarqués
sur la base de microcontrôleur. Il assure une combinaison de l'environnement de programmation avancée
IDE (Integrated Development Environment) et d’un vaste ensemble de bibliothèques pour le matériel, de la
documentation complète et d’un grand nombre d’exemples. Le compilateur mikroC pour PIC bénéficie
d'une prise en main très intuitive et d'une ergonomie sans faille. Ses très nombreux outils intégrés
(mode simulateur, terminal de communication Ethernet, terminal de communication USB, gestionnaire
pour afficheurs 7 segments, analyseur statistique, correcteur d'erreur, explorateur de code, mode Débug
ICD...) associé à sa capacité à pouvoir gérer la plupart des périphériques rencontrés dans l'industrie
(Bus I2C™, 1Wire™, SPI™, RS485, Bus CAN™, USB, gestion de cartes compact Flash et SD™/MMC™,
génération de signaux PWM, afficheurs LCD alphanumériques et graphiques, afficheurs LEDs à 7
segments, etc...) en font un outil de développement incontournable pour les systèmes embarqués,
sans aucun compromis entre la performance et la facilité de débogage.
La nouvelle version appelée mikroC PRO dispose de très nombreuses améliorations du compilateur
mikroC : nouvelles variables utilisables, nouvelle interface IDE, amélioration des performances du
linker et de l'optimisateur, cycle de compilation plus rapide, code machine généré plus compact
(jusqu'à 40 % suivant les cas), nouveaux PIC supportés, environnement de développement encore plus
ergonomique, nouveaux exemples d'applications, etc...
Pas 3 : Cocher la case : I accept the terms in the License Agreement et cliquer sur Next
Pas 9 : Aller dans le répertoire KeyGen et copier le fichier qui s’y trouve.
Pas 10 : Coller ce fichier au directory
"C:\Users\Public\Documents\Mikroelektronika\mikroC PRO for PIC\" ou
"C:\Program Files\Mikroelektronika\mikroC PRO for PIC\"
Pas 11: Cliquer deux fois sur le fichier KeyGen.exe pour enregistrer ses informations sur le registre de
votre ordinateur.
Pas 12 : Après exécution KeyGen ,un fichier est produit (mikroC_PRO_PIC.key).
Pas 13 : Supprimer le fichier keygen
Pas 14:Lancer le compilateur mickroC en cliquant sur l’icône
3. Construction d’un exécutable :
C, est un langage compilé, cela signifie qu’un programme C est décrit par un fichier texte appelé fichier
source. Ce fichier n’est pas exécutable par le microprocesseur. Il faut le traduire en langage machine. Cette
opération est effectuée par un programme appelé compilateur (compilateur mikroC par exemple)
Comment passer du code source au code exécutable ?
Tout à bord, pour écrire un programme, on doit faire appel à des bibliothèques (ce sont des morceaux de
codes déjà empaquetés prés à l’emploi), définir des variables et des constantes pour stoker des résultats
sous forme de chiffres, de lettres ou de chaines de caractères puis écrire le programme dans la fonction
main .Si votre projet commence à prendre un peu de volume, vous allez le scinder en fonctions qui
remplacent des tâches simples et élémentaires. Si votre projet commence à prendre plus d’ampleur, dans
ce cas, vous devrez effectuer un découpage sous forme de fichiers. Cela rend votre projet plus lisible et
flexible c'est-à-dire si vous voulez à faire une amélioration (extension) de votre projet, ça sera toujours plus
simple si vous avez des briques élémentaires.
Le compilateur passe par deux phases pour transformer le code source en code machine : phase
d’analyse et phase de production.
Phase d’analyse : Dans la phase d’analyse, le compilateur s’assure que le code source respecte la
syntaxe de grammaire du langage haut niveau (langage C).
La phase d’analyse est réalisée en trois étapes :
• Analyse lexicale : pour s’assurer que tous les mots du code source appartiennent au vocabulaire
du langage haut niveau.
Exemple pour une variable on écrit int 1a=5 ; erreur la variable ne doit pas débuter par un chiffre
Si la compilation est réussie, le compilateur mikroC PRO pour PIC génère des fichiers de sortie dans le
dossier du projet (dossier qui contient le fichier projet. mcppi). Les fichiers de sortie sont résumés dans le
tableau ci-dessous:
Format Description Type de fichier
Code hexadécimal .Ce fichier est utilisé pour
Intel HEX .hex
programmer le PIC
Binary Fichier compilé pour la bibliothèque mikroC. .mcl
L’image globale de l’allocation de mémoire du PIC
List File pour les adresses d’instruction, les registres et les .lst
étiquettes du programme
Assembler File Le fichier en assembleur .asm
Certains noms sont réservés pour le compilateur lui-même et ne peut pas être utilisés comme
noms de variables dans un programme.
On donne une liste alphabétique de ces noms réservés.
Noms réservés en mikroC ( Vous êtes appelés à respecter la casse)
asm enum signed auto extern sizeof break float static case for struct char goto switch const if
typedef continue int union default long unsigned do register void double return volatile else short while
Les letters c,f,w et z ne sont pas acceptés par le compilateur mikroC .On peut utiliser c1 par exemple
****************************************************************************/
void main() En langage C, un programme
{ commence avec les mots
clés : Void main ()
TRISB = 0; // Configuration du PORTB en sortie
PORTB=0 ; // Initialisation du PORTB
for(;;) // Boucle sans fin
{ Après cela, une accolade
ouvrante est utilisée pour
PORTB.B0 = 0; // RB0 = 0 indiquer le début du corps de
Delay_ms(1000); // Pause d’une seconde programme au lieu de begin
PORTB.B0 = 1; // RB0 = 1
Delay_ms(1000); // Pause d’une seconde
Le programme se termine par
} // Fin de la boucle une accolade fermante
} Au lieu de end.
Autres méthodes :
• Utilisation du caractère
Négation logique !
Directive # define
Dans la phase de précompilation le préprocesseur
remplace LED_1 par PORTB.B0
N.B Respecter la casse on écrit #define minuscule. Exemple : si on écrit # Define on aura ce message d’erreur
Activité1 : Ecrire un programme en MikroC permettant de clignoter tout le PORTB avec une période 2s
On constate que seule la broche RB0 clignote puisque l’opérateur ! (not) utilisé réalise la fonction non juste
pour un seul bit elle nous renvoie une valeur booléenne. Pour que tout le PORTB clignote on utilise
l’opérateur tilde « ~ » ( Alt Gr 2 puis espace pour un clavier azerty) l’opérateur ~ complémente tout le mot
binaire bit à bit
Activité2 : On désire commander la LED D1 en utilisant le bouton poussoir BP : une impulsion sur le
bouton poussoir BP allume la LED D1 durant 3s puis elle s’éteint.
Ecrire un programme mikroC qui répond au cahier de charges.
Utilisation de la structure conditionnelle
Si ( condition ) alors action 1 sinon action 2
Condition du test :
== « Test d’égalité » non
>,<,>=,<=, condition
oui
!= « test de différence»
&& ET logique Action1 Action2
|| Ou logique etc …
NB : le test d’égalité se fait avec == et non pas avec un seule = comme en mikropascal
Ne pas confondre == (test d'égalité) et = (affectation)
non
Si BP==1
oui
Led=1 Led=0
pause 3s
If BP==1 n’est pas accepté par le compilateur ce qu’on doit écrire c’est if (BP==1)
Même remarque pour la boucle : while 1 sans parenthèse n’est pas acceptée par le compilateur ce qu’on
doit écrire c’est while (1)
P++;
else
P--;
Nous pouvons avoir plus d'une instruction en joignant les instructions entres accolades.
Par exemple:
if (x> MAX)
P++;
Cnt = P;
else
P--;
Dans cet exemple, si x est supérieur à MAX, alors les trois instructions qui sont entres accolades sont
exécutées, sinon l’instruction P-- est exécutée.
Un autre exemple en utilisant l'instruction if :
if (x> 0 && x <10)
{Total + = Sum; Sum++;}
else
{Total = 0;Sum = 0;}
Théoriquement, le résultat d'une comparaison est une valeur booléenne (vraie ou fausse).
En C, le résultat d'une comparaison est 1 ( != 0) ou 0 selon que cette comparaison est vraie ou fausse.
Les opérateurs logiques
Une variable booléenne est une variable pouvant prendre la valeur vrai ou faux.
La valeur d'une expression booléenne est, comme le résultat des comparaisons, une valeur entière.
Activité3 : Même cahier de charges que l’activité 2, on change seulement la condition sur le bouton
poussoir BP
3000
#define A RA0_bit
#define B RA1_bit
#define C1 RA2_bit
#define D RA3_bit
#define S1 RB0_bit
#define S2 RB1_bit
#define S3 RB2_bit
# define S4 RB3_bit
#define S5 RB4_bit
#define S6 RB5_bit
#define S7 RB6_bit
void main()
PORTB=0;
S2= B&&D;
S3= A^B;
S4= D||B&&!A;
S5 =!S3;
S6= !(A&&B);
S7= !(A||B);
Instruction switch ….case : (Au cas ou) « (en pascal case expression of) »
Pour éviter les tractions de l’imbrication des if, on fait appel à une instruction plus élégante appelée switch
et dont la syntaxe est la suivante :
break
switch (condition) Case1 instruction1 Case1 instruction1
{
Case condition1 : instruction1 ;break ;
break
Case condition2 : instruction1 ;break ; Case2 Instruction2 Case2 Instruction2
…………………………………………..
N.B La condition doit être de type char ou int et non pas de type float par exemple
Activité8 : Même cahier de charges que l’activité 7 mais on utilise l’instruction switch au lieu des tests
imbriqués
Dans le schéma relatif à l’instruction switch, les liaisons effectuées sur les broches RA3 et RA4 à travers
deux résistors sont nécessaires pour éviter de laisser des broches à l’air libre ce qui peut influer les valeurs
prises par ces broches à un moment donné puisqu’ on va tester sur tout le PORTA
Donc si PORTA=1 D01 sauter
si PORTA=2 D11 sauter
si PORTA=4 D21 sauter
Autrement D71
{
Instructions ;
Ce type de boucle nécessite l’utilisation d’une variable qui doit être
}
déclaré auparavant dans la zone de déclaration des variables.
Exemple 1 :
for (i=0 ;i<10 ;i++) Trois paramètres :
1°) Initialisation : une instruction qui s’exécute une seule fois au début de la boucle
{ 2°) La condition : la condition pour que la boucle continu
Instructions; 3°) l’incrémentation : une instruction qui s’exécut e à chaque itération, i++ →i=i+1
}
Condition de départ
Condition de fin
Quizz :
Combien de fois la LED va s’allumer dans ce programme ?
• 4 fois
• 5 fois
• 6 fois La réponse est évidemment 5 fois
Quizz :
Combien de fois la LED va s’allumer par ce programme ?
• 6 fois
• 5 fois
• 4 fois La réponse est évidemment 5 fois
Instruction while
La syntaxe d’une instruction while est la suivante
Exemple2 :
while (1) // boucle sans fin puisque la condition est toujours vraie
{
Instructions;
}
N.B : Il est possible d’avoir une déclaration while sans corps. Une telle déclaration est utile.
Voici un exemple où le programme va attendre aussi longtemps que le bit 0 de PORTA est au niveau
logique 0. Le programme se poursuivra jusqu'au changement à la valeur 1 sur la broche RA0
Activité 13 :
On se propose de clignoter un nombre de fois une LED en fonction de la durée de pression sur un bouton
poussoir : si on presse rapidement la LED clignote une fois, si on presse très longuement la LED clignote
plusieurs fois. Tant qu’on presse sur le bouton poussoir on va incrémenter un compteur qui augmente
toutes les 20ms , une fois on a relâché le bouton poussoir on va décompter.
Ecrire un programme en mikroC qui traduit ce cahier de charges.
Nombre de clignotements
selon durée poussoir
Bouton
Compteur
LED
La boucle finie do while (condition) est identique à while(), à la seule différence que la condition est
évaluée à la fin de la boucle. Donc dans ce cas les instructions entre accolades sont au moins
exécutées une seule fois.
La syntaxe d’une instruction do while est la suivante :
do
{
instruction_1 ;
instruction_2 ;
etc….
instrcuction_n ;
}
while (condition) ;
KM1 KM2 AV AR
?
? ? ?
U1
+5V
9 21
OSC1/CLKIN RB0/INT
10 22
OSC2/CLKOUT RB1
23
RB2
2 24
RA0/AN0 RB3/PGM
3 25
RA1/AN1 RB4
4 26
m 5
RA2/AN2/VREF-/CVREF
RA3/AN3/VREF+
RB5
RB6/PGC
27
6 28
RA4/T0CKI/C1OUT RB7/PGD
7
RA5/AN4/SS/C2OUT
11
a 1
MCLR/Vpp/THV
RC0/T1OSO/T1CKI
RC1/T1OSI/CCP2
12
13
RC2/CCP1
14
RC3/SCK/SCL
15
b 10k 10k 10k
RC4/SDI/SDA
RC5/SDO
16
17
RC6/TX/CK
18
RC7/RX/DT
PIC16F876A
0 CT=0
10k +5V
m
m
1 KM1 KM2 AV
a1 a1
2 KM1 AR a0
U2
a0 16
15
OSC1/CLKIN RA0
17
18
OSC2/CLKOUT RA1
1
3 CT= CT + 1 4
MCLR
RA2
RA3
2
3
RA4/T0CKI ? KM1
6
RB0/INT
7
RB1
8
CT=4 CT<4 RB2
RB3
9 ? KM2
10
RB4
11
RB5
12
RB6
RB7
13 ? AV
PIC16F84A
? AR
GIE EEIE T0IE INTE RBIE T0IF INTF RBIF Valeur INTCON
INTCON
… … … … … ... ... ... ..............
GIE EEIE T0IE INTE RBIE T0IF INTF RBIF Valeur INTCON
INTCON
… … … … … ... ... ...
CONCLUSION :
Déroulement normal du programme principal Au cours d’une interruption A la fin de l’interruption
INTCON=0x……. INTCON=0x…. INTCON=0x………..
Il faut toujours remettre le registre INTCON à 0x….. à la fin de la routine d'interruption pour autoriser une
autre interruption ou bien mettre les bits :
INTCON.INTF=0 et INTCON.GIE =1 ou INTCON.b1=0 et INTCON.b7 =1 (en respectant l’ordre)
N.B si on veut produire l’interruption sur le front descendant d’une impulsion appliquée sur RB0 on doit
mettre un 0 au bit INTEDG du registre POTION_REG
Si INTEDG = 1, l’interruption s’effectuera si le niveau sur RB0 passe de 0 vers1 (front montant de RB0).
Si INTEDG = 0, l’interruption s’effectuera si RB0 passe de 1 vers 0 (front descendant de RB0).
À l'issue d’un Reset, tous les bits du registre OPTION_REG sont à 1.
Activité 18 : Interruption externe avec RB0↑ ↑
Ecrire un programme en mikroC qui déclenche une interruption sur RB0 (front montant) et à chaque
impulsion sur le bouton poussoir BP relié à la broche RB0 inverse l’état de la diode LED D reliée à la
broche RA0.
Reprenons donc l’activité 18 et ajoutons cette commande tout en modifiant l’interruption pour la rendre
active sur front descendant
Analyse : Pour chaque interruption on va incrémenter une variable nommé i de type char et on test la
variable si elle est égale à 3 on change l’état de la diode et on initialise la variable i , sinon on sort de
l’interruption.
Quatre LED dont chacune signale l’entrée en mode interruption par inversion de leur état .Ces diodes sont
associées aux boutons de la façon suivante :
D1 pour le bouton BP1 branché sur RB4,
D2 pour le bouton BP2 branché sur RB5,
D3 pour le bouton BP3 branché sur RB6,
D4 pour le bouton BP4 branché sur RB7.
GIE EEIE T0IE INTE RBIE T0IF INTF RBIF Valeur INTCON
INTCON
… 0 0 … … 0 0 0 0x...
U1
16 17
RA7/OSC1/CLKIN RA0/AN0
15 18
RA6/OSC2/CLKOUT RA1/AN1
1
RA2/AN2/VREF
4 2
RA5/MCLR RA3/AN3/CMP1
3
RA4/T0CKI/CMP2 D1
R1
6
RB0/INT
7
RB1/RX/DT
8
RB2/TX/CK D2
RB3/CCP1
9 R2
10
RB4
11
RB5
12
RB6/T1OSO/T1CKI D3
RB7/T1OSI
13 R3
PIC16F628A D4
R4
D5
R5
D6
R6
D7
R7
D8
R8
U1
16 17
OSC1/CLKIN RA0
15 18
OSC2/CLKOUT RA1
RA2
1 0
4 2
MCLR RA3
3
RA4/T0CKI
6
RB0/INT
7
RB1
8
RB2
9
RB3
10
RB4
11
RB5
12
RB6
13
RB7
PIC16F84A
Pour lire et afficher la température de la lampe « ultraviolet » d’un robot aspirateur on utilise un
microcontrôleur PIC 16F876A, un afficheur LCD 16x2 et un capteur de température LM35. Ce dernier
fournit à sa sortie une tension proportionnelle à la température (10mV /10°C) .
V
En appliquant la règle de trois T = avec T en °C et V en mV
10
Le convertisseur CAN du microcontrôleur convertit toute tension comprise entre 0 et 5V (0 à 5000mV) en
un nombre sur 10 bits (de 0 à 1023) . En appliquant encore la règle de trois on obtient :
V Canal 0 A.D.C N
N × 5000 N × 500
V = avec V en (mV) → T = avec T en °C
1023 1023
V N
5000 mV 1023
Une conversion de type intervient lorsqu’ un opérateur doit agir sur des opérandes de types différents. En
L’opérande la plus petite est convertit dans le type de l’opérande la plus grande.
Char → int → long → float → double (conversion implicite çad faite automatiquement par le compilateur).
Exemple :
char nombre_1=45 ;
Int nombre_2 ;
Exemple :
int nombre_2 ;
Le mikroC PRO pour PIC fournit une bibliothèque pour travailler avec des claviers « en bloc de touches
4x4 ». Les routines de bibliothèque peuvent également être employées avec le bloc de touches 4x1, 4x2,
ou 4x3.
L’utilisation de ce clavier nécessite un port obligatoirement bidirectionnel 8 bits.
Instructions spécifique au compilateur « MikroC pro » pour le Clavier
char keypadPort at PORTD; // Pour la connexion du clavier au PORTD considéré (8 bits)
char kp; //on définit une variable de type octet
Keypad_Init();// Initialisation du clavier
kp = Keypad_Key_Press();// lecture de code de la touche « touche enfoncée » de 1 à 16.
kp = Keypad_Key_Click();// lecture de code de la touche « touche enfoncée puis libérée »de 1 à 16.
Activité N°33 (Clavier_1)
Saisir le programme suivant puis simuler le fonctionnement de chaque circuit et remplir les tableaux
correspondants :
Code en
Touche
décimal
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
?
?
?
?
?
R9
Circuit 2
16
U1
OSC1/CLKIN RA0
10k
17
2 5
15 18
4
OSC2/CLKOUT
MCLR
RA1
RA2
RA3
RA4/T0CKI
1
2
3
1 2 3 4
3 9
L1
RB0/INT
RB1
RB2
6
7
8
L1 R1
10k
4 13
9
7 8
RB3
RB4
RB5
RB6
10
11
12
5 6
5 2
13 L2 R2
PIC16F84A
RB7
10k 6 6
lecture 10 11 12
L3
9
R3
7 10
15 16
10k
8 14
13 14
L4 R4
9 3
Colonne1
10k
10 7
Colonne2 11 11
Colonne3 12 15
Colonne4
13 4
On fait une balayage sur les colonnes et on lit sur les lignes
R8
10k
R7
10k
R6
10k
R5
10k 14 8
15 12
Le balayage se fait avec RB4 RB5 RB6 RB7
16 16
Lecture sur RB0 RB1 RB2 RB3 RB4
RB3/CCP1
SOUNDER
• Déduire à chaque fois la valeur de la variable code_serrure lorsque l’utilisateur appuie sur les
touches données dans le tableau suivant :
Valeur en décimal de la variable Porte Témoin Témoin
Touche appuyé
code_serrure= code_serrure *10 + a ouverte rouge verte
# 0 non non non
4 0+4=4 non non non
7 4*10 + 7 = 47 non non non
8 47*10+8 = 478 non non non
1 478*10 +1= 4781 non non non
* Validation 4781 ≠ 1978 après 1seconde 0 Non Oui (1s) non
1 1 non non non
9 19 non non non
7 197 non non non
8 1978 non non non
* Validation 1978 =1978 après 2seconde 0 oui (2s) non oui (2s)
# 0 non non non
5 5 non non non
4 54 non non non
* Validation 54 ≠ 1978 après 1seconde 0 non Oui (1s) non
Ecrire un programme en MikroC PRO qui permet la génération d’un signal PWM de fréquence 5 KHz, dont
le rapport cyclique est modifié a l’aide de 2 boutons (augmentation + et diminution -). , on dispose aussi
d’un bouton arrêt qui arrête le moteur : la valeur X à placer sur le module set Duty est affichée sur le portB
et portA Vérifier le fonctionnement avec Proteus ISIS ?
RB1 0 0
0 0
EA
EP 0
On relâche sur le bouton
Mise à jour de l’état précédent Mise à jour de l’état précédent
Résultat du test 0 On appui sur le bouton EA=0 // EA= PORTB.RB1
Pas d’incrémentation EP=EA =1 EP=EA =0
EA=1 // EA= PORTB.RB1 Résultat du test faux EA=0 et EP=1
du PORTA Résultat du test faux Résultat du test faux
Résultat du test vraie EA=1 et EP=0 Pas d’ incrémentation du PORTA
Pas d’incrémentation Pas d’incrémentation
On aura incrémentation du PORTA du PORTA du PORTA
Etat.f1 Etat.f0
Programme : État précédente État actuel
unsigned char etat=0; // variable nommé etat de 8 bits
void main()
{
TRISA=0;
TRISB.RB1=1;
PORTA=0;
etat=0;
while (1)
{
while (PORTA<10)
{
etat.f0=PORTB.RB1;
if (ETAT.F0&&!ETAT.F1) PORTA++;
ETAT.F1=ETAT.F0;
}
PORTA=0;
}
}
Projet composé d’un seul fichier source .c (main) Projet composé de 2 fichiers sources .c et un
fichier Header (entête) .H
Comme vous le voyez, il ya deux types de fichiers :
Les fichiers .h appelés headers. Ces fichiers contiennent les prototypes des fonctions : déclaration
des fonctions indiquant au processeur qu’il existe une fonction appelé ... et qui prend tels paramètres
en entrées etc. Cela permet au processeur de s’organiser.
Les fichiers .c : ce sont des fichiers sources qui contiennent les fonctions elles – mêmes.
Pour chaque fichier .c, il ya son équivalent .h sauf la fonction main n’a pas de prototype parce que le
processeur la connait, c’est toujours la même pour tous les programmes.
Il faut inclure le fichier .h grâce à une directive de préprocesseur qui s’appelle # include avec des
guillemets sans espaces (exemple : # include ‘’fichier_1.h‘’) .
La commande # include demande d’insérer le contenu du fichier _1.h dans le fichier .c, et dans le fichier .h
on trouve seulement les prototypes des fonctions du fichier fichier_1.c
Exemple d’application :
Activité N°41
Prenons un exemple simple : Soit à clignoter deux PORTs (PORTA et PORTB d’un microcontrôleur
PIC 16F84A) en même temps à période de 1s. On va diviser le programme en deux fichiers source .c et un
fichier .h. Le clignotement du PORTA est fait avec la fonction main, (premier fichier source nommé
fichier_0), et le clignotement du PORTB est fait avec une autre fonction Clignote_PORTB (2ème fichier
source nommé fichier_1). Le prototype de cette fonction se trouve sur un fichier header nommé fichier_1.h
Comment ajouter des fichiers .c et .h à un projet ?
Commencer par créer un nouveau projet nommé par exemple Projet_1 modulaire, attribuer à ce projet un
Donner le même nom à ce fichier (fichier _1) et préciser le type ici .h (fichier header)
2 fichiers sources
Contient la fonction principale main
1 fichier d’entête
2. On veut enlever (en le mettant en commentaire) un gros bloc d'instructions sans prendre garde au fait
qu'il comporte des commentaires.
• Erreurs avec les priorités des opérateurs
Les priorités des opérateurs sont parfois surprenantes. Les cas les plus gênants sont les suivants :
La priorité des opérateurs bit à bit est inférieure à celle des opérateurs de comparaison.
La priorité des opérateurs de décalage est inférieure à celle des opérateurs arithmétiques.
Dans la séquence ci-dessous, très souvent utilisée, toutes les parenthèses sont nécessaires :
...
}
• Erreurs avec l'instruction switch
Oubli du break
L'alternative à exécuter par défaut est introduite par l'étiquette default. Si une faute de frappe est commise
sur cette étiquette, l'alternative par défaut ne sera plus reconnue : l'étiquette sera prise pour une étiquette
switch(a){
case 1 : a = b;
TH TB t(ms)
.............................................................
……………………………………….
Exercice N°2 :
On désire automatiser la gestion des LEDs tricolores à l’aide d’un microcontrôleur 16F84A comme le
montre la figure ci-contre.
1) Ecrire un programme MikroC qui permet de faire clignoter les 3 LEDs tricolores simultanément. Le
fonctionnement normal est décrit par le chronogramme suivant :
TB=1000ms
LED :D1,D2,D3 Période TH=1000ms
TH TB t(ms)
.............................................................
……………………………………….
Exercice N°3 :
On propose de faire clignoter des LEDS branchées au PORTB du microcontrôleur de deux façons
différentes :
• 1ère façon :
- Si RA0=0, toutes les LEDS clignotent avec une période d’une seconde (0,5s allumées, 0,5s éteintes)
- Si RA0=1, les LEDS doivent clignoter chaque 500ms comme indiqué dans la figure ci-dessous.
RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
.............................................................
……………………………………….
• 2éme façon :
- Si RA0=0, toutes les LEDS clignotent avec une période de deux secondes
- Si RA0=1 on obtient le cycle répétitif suivant :
Diodes LED allumées Durées (en seconde)
D0D1 1
D2D3 2
D4D5 3
D6D7 4
Aucune diode 1
.............................................................
……………………………………….
Exercice N°4 :
On veut maintenant réaliser plusieurs animation sur les LEDS commandées par les boutons poussoirs B1
et B2 selon le tableau suivant :
N°
B2 B1 Séquence Durée de défilement
séquence
0 0 0 D0etD1 -D2etD3 –D4etD5 -D6etD7 200ms
Chenillard à droite
1 0 1 100ms
D7-D6-D5-D4–D3-D2-D1-D0
2 1 0 D0etD7 –D1etD6 –D2etD5 –D3etD4 200ms
Chenillard à gauche
3 1 1 100ms
D0-D1-D2-D3–D4-D5-D6-D7
…………….
Exercice N°5 :
On désire commander deux LEDs à l’aide d’un interrupteur via un microcontrôleur
PIC 16F84A comme donnée par la figure ci-contre.
1°) Ecrire un programme en MikroC qui permet de fai re
allumer et éteindre les deux LEDS par l’interrupteur BP
……..
……..
Exercice N°6 :
On désire commander deux LEDs à l’aide de deux boutons poussoirs via un microcontrôleur
16 F84A comme donnée par la figure ci-contre.
Ecrire un programme en MikroC qui permet de faire
allumer la LED bleu pour une durée de 3s et la LED
verte pour une durée de 5s suite à l’action de l’un de
deux boutons poussoirs.
……..
Exercice N°7:
On désire automatiser la gestion de feux tricolores, réglant la circulation d’un carrefour à deux voies.
L’étude se limitera à un seul feu et le fonctionnement normal est décrit par le chronogramme donné par la
figure ci-dessous.
……..
Exercice N°8:
Gestion de deux feux tricolores de circulation (carrefour)
Ecrire un programme en MikroC qui permet de piloter deux feux tricolores de carrefour. Vérifier le bon
fonctionnement du programme réalisé en utilisant Proteus ISIS.
Le chronogramme de fonctionnement est le suivant :
……..
Pour faciliter la tache, on programme par PORT entier, les feux tricolores sont connectés au PORTB et les
feux des piétons sont connectés au PORTA
Feux route secondaire Feux route principale
Vert2 Orangé2 Rouge2 Vert1 Orangé1 Rouge1
RB5 RB4 RB3 RB2 RB1 RB0
Feux piéton route secondaire Feux piéton route principale
Vert Rouge Vert Rouge
RA3 RA2 RA1 RA0
Exercice N°10:
On désire commander une LED par plusieurs endroits à l’aide d’un microcontrôleur
16F84A via des boutons poussoir BPi (BP1, BP2 et BP3).
Le principe de fonctionnement est le suivant : une impulsion sur l’un des boutons poussoir BPi, la LED D
s’allume, une deuxième impulsion la LED s’éteint.
……..
……..
……..
……..
……..
Bits de sélection
Opérations
RE2 RE1 RE0
001 AND
010 OR
011 XOR
100 +
101 -
110 *
111 /
……..
……..
63 6 91 79 102
Segment G F E D C B A
PORTB=
Chiffre RB6 RB5 RB4 RB3 RB2 RB1 RB0
0 0 1 1 1 1 1 1 63
1
2
3
4
5
6
7
8
9
2°) Écrire un programme en MikroC qui permet de rép ondre au cahier des charges.
……..
Programme :
……..
Exercice N°17:
……..
Exercice N°18:
……..
……..
Exercice N°19:
Écrire un programme en mikroC qui permet de contrôler l’affichage de deux chiffres (2 digits)
7 segments de 0 à 99 avec une cadence de 500ms. (déclarer un tableau tab[10] contenant les 10 codes 7
segments des chiffres de 0 à 9 et avec des boucles for repérer le code à envoyer)
Programme :
……..
Exercice N°20:
On désire réaliser un compteur modulo 100 par deux afficheurs 7 segments sans décodeur. On utilise le
principe de l’affichage multiplexé à l’aide d’un microcontrôleur 16F84A.
Ecrire un programme en mikroC qui permet de réaliser le compteur modulo100, les deux broches RA0 et
RA1 permettent de sélectionner l’un des deux afficheurs 7 segment à cathodes communes.
Programme :
……..
AV
A D
AV
B C
ROTOR Phase A
BC D
S
C
STATOR
1 2 3 4 5 1 2 3 4 5
Cycle
1seconde Arrêt
Figure 1
1°) Selon le schéma du circuit logique, déterminer la valeur du registre TRISA et TRISB sachant que les
broches non utilisées sont configurées comme entrées :
TRISA=0X ………. TRISB=0B ………………..
2°) A partir du chronogramme du moteur pas à pas, r emplir sa table de vérité suivante :
Exercice N°23
On ajoute à l’exercice précédente un bouton relié à la broche RA3 qui sélectionne le mode de fonctionnent
de telle sorte que :
Si RA3=1 : mode de fonctionnement asymétrique et vitesse double
Si RA3=0 : mode de fonctionnement symétrique et vitesse normale
AV
ROTOR Phase A
N
BC D
S
STATOR
……..
……..
Programme :
……..
……..
……..
……..
……..
Écrire un programme qui lit une valeur numérique sur le PORTB sous forme d’un nombre codé sur 8 bits, ce
nombre constituera le rapport cyclique d’un signal MLI de fréquence 1KHz qui va être généré par la sortie
RC1 pour commander un moteur à courant continu.
Programme :
……..
Soit le schéma de la figure ci –après, ou quatre boutons BP1, BP2, BP3 et BP4 sont reliés aux quatre bits
de poids faible du PORTB du microcontrôleur avec les résistances de tirage vers le haut, ces boutons sont
utilisés pour commander le rapport cyclique du PWM de fréquence 5KHz qui est généré par les modules
CCP le fonctionnement est :
• Une impulsion sur le bouton BP1 augmente le rapport cyclique du PWM1
• Une impulsion sur le bouton BP2 diminue le rapport cyclique du PWM1
• Une impulsion sur le bouton BP3 augmente le rapport cyclique du PWM2
• Une impulsion sur le bouton BP4 diminue le rapport cyclique du PWM2
Programme :
……..
Programme :
……..
Programme :
……..
Programme :
…….
Programme :
…….
Programme :
…….
Programme :
……………….
On attribue à KM1 une variable de type bit (booléen) X et à KM2 une variable de type bit Y
……………….
char i,j,k,l,m,n,o,p;
void main()
{
trisb=0;
portb=0;
for (;;)
{
for (i=0;i<5;i++)
{PORTB=255; delay_ms(100);PORTB=0;delay_ms(100);}
for (j=0;j<5;j++)
{
PORTB=128;
for (K=0;k<8;k++)
{delay_ms(50);PORTB=PORTB>>1;}
}
for (l=0;l<8;l++)
{
PORTB=1;
for (m=0;m<8;m++)
{delay_ms(50);PORTB=PORTB<<1;}
}
for (n=0;n<10;n++)
{
PORTB=24;delay_ms(50);PORTB=36;delay_ms(50);
PORTB=66;delay_ms(50);PORTB=129;delay_ms(50);
PORTB=66;delay_ms(50);PORTB=36;delay_ms(50);
}
}
}
Programme :
……………….
……………….
while(1) {
if (B1==0)
{
{
if (B1==0) // (!B1) PORTB=0XFF;delay_ms(1000);
{ PORTB=0X00;delay_ms(1000);
}
PORTB=0XFF;delay_ms(500);
if (B1==1)
PORTB=0X00;delay_ms(500); {
} PORTB=0X3; delay_ms(1000);
PORTB=0XC; delay_ms(2000);
if (B1==1) //(B1)
PORTB=0x30; delay_ms(3000);
{ PORTB=0xC0; delay_ms(4000);
Exercice N°6
Exercice N°7
# define BP1 RA0_bit
# define BP2 RA1_bit # define R RA0_bit
# define LED_BLEU RB0_bit
# define O RA1_bit
# define LED_VERTE RB1_bit
# define V RA2_bit
void main()
{ void main()
TRISA=31;TRISB=0;PORTB=0;
{
while(1)
TRISA=0;PORTA=0;
{
for(;;) // boucle infinie
if( BP1||BP2) // B1 ou B2
{
{
O=0;R=1;delay_ms(1000);
LED_BLEU=1; LED_VERTE=1; delay_ms(3000);
R=0;O=1;delay_ms(600);
LED_BLEU=0; LED_VERTE=1; delay_ms(2000);
O=0;V=1;delay_ms(1000);
}
O=1;V=0;delay_ms(600);
else
}
{
}
LED_BLEU=0; LED_VERTE=0;
}
}
}
2°) Programme
void main()
TRISB=0;PORTB=0;
while(1)
PORTB=12;
delay_ms(32000);
PORTB=26;
delay_ms(4000);
PORTB=33;
delay_ms(32000);
PORTB=19;
delay_ms(4000);
2°) Programme :
void main()
{
TRISB=0;PORTB=0;
TRISA=0;PORTA=0;
while(1)
{
PORTB=12;
PORTA=9;
delay_ms(32000);
PORTB=26;
PORTA=9;
delay_ms(4000);
PORTB=33;
PORTA=6;
delay_ms(32000);
PORTB=19;
PORTA=6;
delay_ms(4000);
}
{ }
TrisA=0x1F; // configuration du portA en entrée
}
TrisB=0b11100000; // configuration du portB
char A,B,E,S1;
void ET_logique () // fonction Et void main()
{ {
{ TRISD=255;TRISE=7;
S1= (A | B) ; PORTB=0;
}
while (1)
void OU_exclusive () // fonction OU exclusive
{
{
A= (PORTC & 0X0F);
S1= (A ^ B) ;
B=(PORTD & 0X0F);
}
{ PORTB=S1;
S1= (A + B) ;
if (E==1) ET_logique(); // appel de la fonction
}
if (E==2) OU_logique(); // appel de la fonction
void soustraction () // fonction soustraction
}
if (E==5) soustraction ();// appel de la fonction
void multiplication () // fonction multiplication
if (E==6) multiplication ();// appel de la fonction
{
} }
char i; {
{ PORTB=tab[i];
TRISB=0; }
PORTB=63; }
}
3°) Programme :
while(PORTA==4)
#define tempo delay_ms(1000)
void main() {
{
PORTB=3;tempo;
TRISA=0X1F;
PORTB=6;tempo;
TRISB=0B11110000;
PORTB=12;tempo;
PORTB=0;
{
}
while(PORTA==1)
while(PORTA==2)
{
{
PORTB=9;tempo;
PORTB=0;
PORTB=12;tempo;
}
PORTB=6;tempo;
}
PORTB=3;tempo;
}
}
Exercice N°24
Exercice N°25
# define B1 RB0_bit
# define B2 RB1_bit
# define B3 RB2_bit
# define D1 RC0_bit
# define D2 RC1_bit
# define D3 RC2_bit
// LCD module connexion
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// Fin module connexion
void main()
{
TRISC=0b11111000;
TRISB=0b11111111;
PORTC=0;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // effacer l'LCD
Lcd_Cmd(_LCD_CURSOR_OFF); // désactiver le curseur
while(1)
{
while (B1&!B2&!B3)
{
Lcd_Out(1,1,"BONJOUR");D1=!D1;delay_ms(500);
}
while (!B1& B2&!B3)
{
Lcd_Out(1,1,"BONSOIR");D2=!D2;delay_ms(500);
}
while (!B1&!B2&B3)
{
Lcd_Out(1,1,"SALAM");D3=!D3;delay_ms(500);
}
while ((!B1&!B2&!B3)|(B1&B2&B3)|(B1&B2&!B3)|(B1&B3&!B2)|(B2&B3&!B1))
{
Lcd_Cmd(_LCD_CLEAR); D1=0;D2=0;D3=0;
PORTA=0; ADCON1=0X80;
Keypad_Init();
ADC_Init();
while (1)
{ while(1)
kp=0; {
do
valeur_V0= ADC_Read(0);
{
kp=keypad_key_click(); valeur_V1= ADC_Read(1);
{ }
case 1: kp=1; break;
}
case 2: kp=4; break;
case 3: kp=7; break;
case 4: kp=10;break;
case 5: kp=2; break;
case 6: kp=5; break;
case 7: kp=8; break;
case 8: kp=0; break;
case 9: kp=3; break;
case 10: kp=6; break;
case 11: kp=9; break;
case 12: kp=11; break;
}
PORTA=Kp;
}
}
char x,y;
void main()
X=0;Y=0;
PORTC = 0;
while (1)
PWM1_Set_Duty(X);PWM2_Set_Duty(Y);
}
}
void main() {
{
a=48;b=48;
TRISA=0B11100;PORTA=0;
TRISB.B6=1;TRISB.B7=1; }
Lcd_Init(); Lcd_Chr(1,15,a);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Chr(1,14,b);
Lcd_Cmd(_LCD_CURSOR_OFF);
while (1) }
{ PORTA=0;
while ((PORTB.RB6 ==0)&&!((b==57)&&(a==57)))
Lcd_Out(1,1,"STOP ");
{
PORTA.RA0=1;PORTA.RA1=0;
Lcd_Out(1,1,"sens droite"); }
a++ ; delay_ms(200);
}
if (a==58)
{
a=48;b++ ;
}
if ((a== 57) && (b==57))
{
a=57;b=57;
}
Lcd_Chr(1,15,a);
Lcd_Chr(1,14,b);
}