Vous êtes sur la page 1sur 14

Le MikroC pour les PICs

I. Introduction
▪ 1972 : naissance du C dans les laboratoires BELL par Dennis Ritchie et développement du
système d'exploitation UNIX.
▪ 1978 : vulgarisation du langage et sortie du livre de B. Kernighan et D. Ritchie "The C
programming language".
▪ 1983 : normalisation A.N.S.I du langage C. Ce travail commence en 83 et dure 5 ans.
▪ 1988 : existence d'une norme : " C-ANSI ". La 2ème édition du livre de Kernighan et Ritchie
devient la référence.
Le langage C est un langage:
▪ PORTABLE : Les modifications d'un programme pour passer d’un système à un autre sont
minimes.
▪ COMPLET : Un texte C peut contenir des séquences de bas niveau (proches du matériel) en
assembleur.
▪ SOUPLE : Tout est possible en C mais une grande rigueur s’impose.
▪ EFFICACE : On réfléchit (devant une feuille de papier) et on écrit (peu).
II. Etapes de développement d’un programme
Le processus de construction d’un programme C (builder) comporte plusieurs étapes et utilise
différents «outils» tels que: un prétraitement, un compilateur, un assembleur et un éditeur de liens. À la
fin, il devrait y avoir un seul fichier exécutable. Ci-dessous les étapes qui se déroulent dans l'ordre quel
que soit le système d'exploitation ou le compilateur.
➢ L’édition du fichier source programme.C avec un éditeur de texte (simple sans mise en forme
du texte).
➢ Le prétraitement est la première étape. Il traite les fichiers d'inclusion, les instructions de
compilation conditionnelle et les macros.
➢ La compilation est la deuxième passe. Il prend la sortie du prétraitement et le code source et
génère le code source de l'assembleur.
➢ L'assemblage est la troisième étape. Il prend le code source de l'assembleur produit par le
compilateur et produit une liste d'assembleur avec offsets. La sortie de l'assembleur est stockée
dans un fichier objet.
➢ L’édition de liens permet d’intégrer des fonctions prédéfinies. Le programme auxiliaire
Éditeur de liens (linker ou binder) génère à partir du fichier *.ASM un fichier exécutable
*.HEX compatible avec le PIC
Le programme doit également contenir la définition des différentes fonctions créées par le
programmeur. Le langage C comporte des bibliothèques de fonctions prédéfinies sous forme de fichiers
comportant l’extension *.h. Ces fonctions seront ajoutées au programme exécutable lors de l’édition de
liens. Pour incorporer dans un programme un fichier *.h, on utilise la commande #include <fichier.h>
placée habituellement en début de fichier.

III. Structure d’un programme C


La structure générale d’un programme C est:
< Zone de déclaration des variables globales et fonctions >
void main(void) {

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 1/14


Le MikroC

< Zone de déclaration des variables locales >

< Instruction 1>; //les commentaires


< Instruction 2>;
....
}
Exemple
unsigned short a;
void main(void)
{
trisb=0xff; //port B en entrée
trisc=0x00; //port C en sortie
a=portb;
portc=a;
}

IV. Les différents types de variables du langage MikroC


1- Les nombres entiers

Type entier Taille en octets Intervalle des valeurs


Bit 1–bit 0 or 1
sbit 1–bit 0 or 1
(unsigned) char 1 0 .. 255
signed char 1 - 128 .. 127
(signed) short (int) 1 - 128 .. 127
unsigned short (int) 1 0 .. 255
(signed) int 2 -32768 .. 32767
unsigned (int) 2 0 .. 65535
(signed) long (int) 4 -2147483648 .. 2147483647
unsigned long (int) 4 0 .. 4294967295

2- Les nombres à virgule flottante


Les types float et double, ainsi que long double, sont considérés comme des types à virgule
flottante. Le mikroC PRO pour l'implémentation par PIC d'une norme ANSI considère que les trois sont
similaires.
Type Taille en octets Intervalle des valeurs
float 4 -1.5 * 1045 .. +3.4 * 1038
double 4 -1.5 * 1045 .. +3.4 * 1038
long double 4 -1.5 * 1045 .. +3.4 * 1038

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 2/14


Le MikroC

3- Représentation des différentes des bases et du code ASCII


int a = 4 ; // Un nombre seul représente un nombre décimal.
int x = 0b1010 ; // Un nombre précédé de 0b ou 0B est un nombre binaire.
int p = 0x00FF ; // Un nombre précédé de 0x ou 0X est un nombre hexadécimal.
int p = 067 ; // Un nombre précédé de 0 seul est un nombre octal.
char c = ‘x’ ; // Un caractère entre ‘’ représente son code ASCII.

V. Les opérateurs
1- Opérateurs de base

Opérateur Fonction
+ Addition
- Soustraction
* Multiplication
/ Division entière
% Reste de la division entière

2- Opérateurs d’affectation

Opérateur Fonction Equivalence


= Affectation ordinaire X=Y
+= Additionner à _ X+=Y équivalent à X=X+Y
-= Soustraire de _ X-=Y équivalent à X=X-Y
*= Multiplier par _ X*=Y équivalent à X=X*Y
/= Diviser par _ X/=Y équivalent à X=X/Y
%= Modulo X%=Y équivalent à X=X%Y
-- Soustraire de 1 (Décrémentation) X-- équivalent à X=X-1
++ Ajouter 1 (Incrémentation) X++ équivalent à X=X+1
3- Opérateurs logique

Opérateur Fonction
&& ET logique
|| OU logique
! NON logique
4- Opérateurs logique sur les Bits
Opérateur Fonction Exemples
& ET x=a&b
| OU x=a|b
^ OU exclusif x=a^b
~ NON x=~a
>> Décalage à droite des bits x=a>>3
<< Décalage à gauche des bits x=a<< 2

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 3/14


Le MikroC

5- Opérateurs de comparaison
Remarque : En C, FAUX est la valeur 0, VRAI est tout ce qui est ≠ 0.
Opérateur Fonction Exemple
== Egale à x = a==3 ; x sera VRAI si a est égal à 3, FAUX sinon
!= Différent de x = a!=3 ; x sera VRAI si a est différent de 3, FAUX sinon
> Supérieur à x = a>3 ; x sera VRAI si a est supérieur à 3, FAUX sinon
< Inférieur à x = a<3 ; x sera VRAI si a est inférieur à 3, FAUX sinon
>= Supérieur ou égal à x = a>=3 ; x sera VRAI si a est supérieur ou égal à 3,.
FAUX sinon
<= Inférieur ou égal x = a<=3 ; x sera VRAI si a est inférieur ou égal à 3, FAUX
sinon

VI. Instructions de base


1- Instruction de test: Si ....alors .....si non....

if (condition) if (condition) {
Action1; Action1;
[else Actions;
Action;] ...
}
[else {
Action
Action2; ...
}]

2- Structure “switch ... case”.


switch (a)
{
case ‘1’ : b=16;
case ‘2’ : b=8;
case ‘3’ : b=4;
case ‘4’ : b=2;
}

3- Boucles: Tant que ....faire....


while (condition)
{
Action1;
Action1;

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 4/14


Le MikroC

...
}
4- Boucles: faire... Tant que .....
do {
action;
}
while (condition)

Exemple
do {
x-=y;
Portb=x;
}
while (x!=0);
5- Boucles: pour .....
for ([expression_1] ; [expression_2] ; [expression_3])
action ;
Exemple
for(x=20 ; x> 0 ; x--)
portb=x;

VII. Les tableaux.


Un tableau est un ensemble fini d’éléments de même type, stockés en mémoire à des adresses
contigües. La déclaration d’un tableau à une dimension se fait de la façon suivante :
type nom-du-tableau[nombre-éléments];
Où nombre-éléments est une expression constante entière positive. Par exemple :
int t[6]; indique que t est un tableau de 6 éléments de type int.
Pour référencier les éléments du tableau on utilise des indices. Les éléments prennent ainsi le
nom de t[indice].

Indice 0 1 2 3 4 5
valeurs 12 34 -16 77 103 -87

Dans cet exemple t[5] est égal à -87.


Déposons par exemple -24 dans t[3] : t[3]=-24 ;
➢ Il est recommandé de donner un nom à la constante nombre-éléments par une directive au
préprocesseur, par exemple : #define nombre-éléments= 6
➢ Les éléments d’un tableau sont toujours numérotés de 0 à nombre-éléments -1.
➢ On peut initialiser un tableau lors de sa déclaration par une liste de constantes de la façon suivante
:
type nom-du-tableau[N] = {constante-1,constante-2,...,constante-N};

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 5/14


Le MikroC

Par exemple :
short table[4] ={ -1,77 ,10,44};
➢ Si le nombre de données dans la liste d’initialisation est inférieur à la dimension du tableau, seuls
les premiers éléments seront initialisés. Les autres éléments seront mis à zéro.
➢ Lors d’une initialisation, il est également possible de ne pas spécifier le nombre d’éléments du
tableau. Par défaut, il correspondra au nombre de constantes de la liste d’initialisation.
Tableau multi-dimensions
type nom-du-tableau[dim1][dim2]
Exemple float m[50][20]; /* tableau à 2 dimensions 50x20 */

VIII. Les fonctions


Les fonctions permettent de subdiviser les programmes en sous-programmes plus simples et plus
compacts, pour obtenir des solutions plus élégantes et plus efficaces. Une fonction peut en appeler une
autre grâce à des instructions particulières. A la suite d'un appel, la fonction appelante s'arrête et la fonction
appelée se met en exécution jusqu'à ce qu'elle appelle une autre fonction ou se termine. Lors de la fin de
son exécution, la fonction appelante reprend son fonctionnement depuis son arrêt. Une fonction peut
envoyer les données à la fonction qu'elle appelle au moment de son appel. Une fonction peut envoyer des
données à la fonction qui l'a appelée au moment du retour. Une fonction appelée doit toujours être définie
avant la fonction qui l'appelle. Elle est soit écrite, soit déclarée avant la fonction qui l'appelle. Chaque
fonction peut être appelée plusieurs fois si nécessaire. Lors du lancement du programme, la fonction
"main" s'exécute en premier.
1- Structure de déclaration d'une fonction :
Syntaxe :
type nom_de_la_fonction(void)
{
// Corps de la fonction
return donnée ;
}
Fonction avec des paramètres
Syntaxe :
Type nom_de_la_fonction(type1 nom1; type2 nom2)
{
Corps de la fonction
Return donnée
}
Exemple :
int somme(int x, int y) {
return (x+y);
}
La donnée à renvoyer doit être compatible avec le type déclaré.
Pour renvoyer le paramètre et mettre fin à la fonction, il suffit de noter "return" suivi de la donnée
que l'on veut renvoyer. Cette ligne doit obligatoirement être la dernière de la fonction. Il est aussi possible
d'avoir plusieurs lignes "return donnée" dans une même fonction. La première ligne rencontrée met alors
fin à cette fonction. La donnée peut être un nombre, une variable, un calcul.

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 6/14


Le MikroC

2- Utilisation d’une fonction :


instruction x;
a = nom_de_fonction();
instruction y;
Instruction x se réalise en premier, puis les instructions de la fonction. A la fin de la réalisation de
la fonction, la donnée qui constitue le paramètre de sortie est déposée dans a.

IX. Les interruptions.


Une interruption provoque l’arrêt du programme principal pour aller exécuter une procédure
d'interruption. A la fin de cette procédure, le microcontrôleur reprend le programme principal à l’endroit
où il l’a laissé. A chaque interruption sont associés deux bits, un bit de validation et un drapeau. Le premier
permet d'autoriser ou non l'interruption, le second permet au programmeur de savoir de quelle interruption
il s'agit.
Sur le 16F876/877, l'es interruptions sont classées en deux catégories, les interruptions primaires
et les interruptions périphériques.
➢ Toutes les interruptions peuvent être validées/interdites par le bit INTCON.GIE
➢ Toutes les interruptions périphériques peuvent être validées/interdites par le bit INTCON.PEIE
➢ Chaque interruption peut être validée/interdite par son bit de validation individuel

3- Déroulement d’une interruption


Lorsque l'événement déclencheur d'une interruption intervient, alors son drapeau est positionné à
1 (levé). Si l'interruption a été validée (bits de validations = 1), elle est alors déclenchée : le programme
arrête ce qu'il est en train de faire et va exécuter la fonction d'interruption qui se trouve à l'adresse 4.
exemple

void interrupt() {
counter++;
TMR0 = 96;
INTCON = 0x20; //baisser le flag
}
Exemple
Dans cet exemple, la fonction principale fait clignoter les bits du port D 4 par 4 et la fonction de
l’interruption fait clignoter les bits du port C 4 par 4. La durée d’allumage et d’extinction est 500ms.

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 7/14


Le MikroC

void interrupt()
{
//faire clignoter les leds du portc 5 fois
int i;
for(i=0; i<5; i++) {
portc=0x0F;
delay_ms(500);
portc=0xF0;
delay_ms(500);
}
INTCON.intf = 0; //baisser le flag
}
//_______________________________________________
void main() {
trisc=0x00;
trisd=0x00;
intcon.gie=1; //bit de valdation de toutes les interruptions
intcon.inte= 1; //bit de valdation de l'interruption INT
while(1){
portd=0xF0;
delay_ms(500);
portd=0x0F;
delay_ms(500);
}
}

X. Exemple d’utilisation des ports parallèles.


1. Afficheur 7 segments (Rappel)

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 8/14


Le MikroC

Un segment Afficheur à Anode Commun Afficheur à Cathode Commune

2. Commande d’un afficheur 7 segments


Le schéma

Le programme correspondant

unsigned short bcdTo7seg(unsigned short y){


unsigned short v;
switch (y) {
case 0 : v=0b0111111; break;
case 1 : v=0b0000110; break;
case 2 : v=0b1011011 ; break;
case 3 : v=0b1001111; break;
case 4 : v=0b1100110; break;
case 5 : v=0b1101101; break;
case 6 : v=0b1111101; break;
case 7 : v=0b0000111; break;
case 8 : v=0b1111111; break;
case 9 : v=0b1101111;
}
return v;
}
void main() {
short unsigned a,b,x;
trisb=0x00;

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 9/14


Le MikroC

trisc=0xFF;
trisd=0xFF;
while(1){
a=portc;
b=portd;
x=a+b;
portb= bcdTo7seg(x);
RB7_bit=0;
}
}

3. Commande d’un afficheur 7 segments avec décodeur inclus

Schéma

Le programme

void main() {
short unsigned c,a,b;
trisb=0x00;
trisd=0xFF;

while(1){
c=portd;
a=c&0x0F; //extraire les 4 bist de la droite
b=c>>4; //extraire les 4 bist de la gauche
portb=a+b;
}
}
4. Afficher7segment à 4 digits
Schéma

Programme :

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 10/14


Le MikroC

Completer le programme suivant:


unsigned short bcdTo7seg(unsigned short y){
unsigned short v;
switch (y)
{
case 0 : v=0b0111111; break;
case 1 : v=0b0000110;break;
case 2 :v=0b1011011 ; break;
case 3 : v=0b1001111; break;
case 4 : v=0b1100110; break;
case 5 : v=0b1101101; break;
case 6 : v=0b1111101; break;
case 7 : v=0b0000111; break;
case 8 : v=0b1111111; break;
case 9 : v=0b1101111;
}
return v;
}
void main() {
short unsigned a,b;
unsigned int i, x,y ;
trisb=0x00;
trisc=0x00;
trisd=0xFF;
while(1){
a=portd&0x0F;
b=portd>>4;
x=a*b;
y= Dec2Bcd16(x); .// converssion d’un nombre décimal de 16 bits en BCD

.................................
.................................
.................................
.................................
delay_ms(50);

.................................
.................................
.................................
.................................
delay_ms(50);

.................................
.................................
.................................
.................................

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 11/14


Le MikroC

delay_ms(50);

.................................
.................................
.................................
.................................
delay_ms(50);
} }

5. Afficher LCD 2 lignes et 16 colonnes (2x16)

________________________________________________________
sbit LCD_RS at RB6_bit;
sbit LCD_EN at RB7_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;
sbit LCD_RS_Direction at TRISB6_bit;
sbit LCD_EN_Direction at TRISB7_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;

void main() {
short unsigned a,b;
unsigned int x ;
char ta[4],tb[4];
char tx[6];
char *tt;
trisc=0x00;
trisd=0xFF;
Lcd_Init(); //initilisation du LCD
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 12/14


Le MikroC

while(1){
a=portd&0x0F;
b=portd>>4;
x=a*b;
bytetostr(a,ta); // transformer le contenu de a en chaine de caractères
bytetostr(b,tb); // transformer le contenu de b en chaine de caractères
wordtostr(x,tx); // transformer le contenu de c en chaine de caractères
tt=Ltrim(ta);
Lcd_Out(1,6,"Calcul"); // à la ligne 1 conne 6 , on affiche "calcul"
Lcd_Out(2,1,Ltrim(ta));
Lcd_Out_Cp("x");
Lcd_Out_Cp(Ltrim(tb));
Lcd_Out_Cp("=");
Lcd_Out_Cp(Ltrim(tx));
}
}

XI. Exemple d’utilisation du port série USART

Programme réception
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;

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 13/14


Le MikroC

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;

void main() {
char a;
char ta[4];
UART1_Init(4800);
Lcd_Init(); //initilisation du LCD
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
Lcd_Out(1,2,"Donnee recue");

while(1){
UART1_Write(ta);
if (UART1_Data_Ready() == 1) {
a = UART1_Read();
bytetostr(a,ta);
Lcd_Out(2,5,ta);
}
} }
programme d’émission
sbit LCD_RS at RB6_bit;
sbit LCD_EN at RB7_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;

sbit LCD_RS_Direction at TRISB6_bit;


sbit LCD_EN_Direction at TRISB7_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;

void main() {
char a;
char ta[4];
trisd=0xFF;
UART1_Init(4800);
Lcd_Init(); //initilisation du LCD
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
Lcd_Out(1,2,"Donnee emise");

while(1){
a=portd;
bytetostr(a,ta); // transformer le contenu de a en chaine de caractères
UART1_Write(a);
Lcd_Out(2,5,ta);
}
}

Préparé par Abdelghani BOUDAOUD EST-Beni Mellal Page 14/14

Vous aimerez peut-être aussi