Vous êtes sur la page 1sur 41

INITIATION AU PICS

Présentation Isis  MkroC Entrée Sortie Afficheur 7 segment


CAN RS 232   PWM LCD Réalisation Pratique
I2C   Clavier matricé  Interruptions

Email

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.

les outils qu’on va utilisé sont  :


  ISIS  de proteus pour la simulation
MIKROC   pour la création des programme
PICKIT2 pour la programmation 

Pourquoi le langage C  et non pas l'assembleur :


alors qu'on assembleur, pour configurer les  module du Pic on doit accéder  à différents bits des registre, le C offre plusieurs fonctions
qui dispensent  le programmeur à écrire de longs séquences de programme .

BROCHAGE 

sur l'image on voit les différents Ports du pic 


certaines pattes on des fonctions partagées 
qu'on expliquera le long de nos expériences 
Pour que le microcontrôleur fonctionne correctement il est nécessaire d’avoir:

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é 

Pour commencer on va dessiner notre circuit de base sur Isis  

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)  ...

Choix des bornes 


cliquer sur l’icône terminal, la liste des terminaux disponible apparaît 

 INPUT                         borne pour signal entrant 


OUTPUT                       borne pour signal sortant                                                                                     
BIDIR                               signal bidirectionnel                                                                    
POWER                           borne d’aimantation
GROUND                      la masse 
BUS                                 bus de plusieurs signaux 

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  

                                     


                    Saisir le programme  suivant puis compiler .

void main()  {                                                 

    trisb= 0b11110000 ;            //  b7 b6 b5 b4    b3 b2 b1 b0     


                                              //    1   1   1    1     0   0   0   0   
                                               //    entrées           sorties
    portb = 0b1111111 ;         // les leds éteintes
    portb = 0b11110000 ;     // les leds allumées
    
                                 }

     

       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

Sur isis dessiner le schéma suivant 


les résistance servent à limiter le courant
copier le code dans Mikroc compiler et simuler comme précédemment  

void main() {
    trisb= 0b10000000 ;            //  b7 b6 b5 b4 b3 b2 b1 b0
                                              //    1   0   0   0   0   0   0   0

 while(1)                    // boucle infini 


{
portb =0xB0 ;                   // code 7 seg du chiffre 3
delay_ms (1000) ;         // temporisation
// 1 sec
 portb = 0x99;              //  code 7seg du chiffre 4
delay_ms(1000) ;               // temporisation 
                                       // 1 sec
 }                             }        

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

   while(1)                               // boucle infini


{    if   ( portc.f6 == 0 )
 portb = 0x4f ;                       // code 7seg du chiffre 3
 else if  (portc.f7 == 0 )
  portb = 0x66;                       //  code 7seg du chiffre 4
 else    portb = 0x3f;                     // code zéro
                        }
 }

Exercice 2

Écrire un programme qui permet d'afficher  de 0 à 9 à une cadence de 500ms


déclarer un tableau  tab[9] contenant les 10 code  7 seg des chiffre de 0 à 9 
et avec une structure for repérer  dans la table le code à envoyer sur le portB tout les 500 ms
correction   

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

Les transistors  t1, t2, et t3  servent à la sélection des afficheur


ils deviennent passants par la présence d'un état 1 a leurs bases
et  connectent la cathode des afficheur à la masse   
  

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 

Configuration du module CAN :

1. configuration de la broche analogique en entrée exemple TRISA.F0 = 1   (RA0/AN0 )


2. configuration des registre  ADCON0  ADCON1 voir datasheet 

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

Ce programme permet unsigned long int temp ;


d'afficher le résultat de la  void main() {
conversion sur les leds   PORTB = 0;     leds eteintes        
  TRISB = 0  ;   portb en sortie
  TRISA =0X01 ;   RA0 en entrée
       ADCON0 = 0 ;
  ADCON1 = 0x8E ; 
while(1) {
      Delay_us(20);
      temp =  Adc_Read(0);
   temp =  temp/4   // 1024 / 4 =255 
portb = temp ;  //affichage de la valeur
}}
  

Expérience 5
Conversion Analogique Numérique 2

   char mil , unit,dix,cent,affc, affd,affu ; Dans cette expérience 


   unsigned long int temp ; on va afficher en claire la tension qui est sur 
  char tab[9] = { 0x3f, 0x06,0x5b,0x4f,0x66,0x6d,0x07,0x7f,0x6f } ;  //code 7seg le curseur du potentiomètre
void main() {
  PORTC = 0;               
  TRISC = 0;               Principe :
  PORTB = 0;                 à 5 volte correspond 1024 
  TRISB = 0  ; on a besoin d'afficher 5,00 v
  TRISA =0X01 ;  // entrée CAN
  ADCON0 = 0 ; relier la patte dp à zéro pour afficher la virgule
  ADCON1 = 0x8E ; une simple règle de trois nous donne
  while(1) {   res = (val *625)/128
res =résulta en décimal à afficher
      Delay_ms(10);
val = valeur de la tension en binaire 
    temp =  Adc_Read(0);
  temp = (temp *625 )/128; le résultat est en binaire pur 
  unit = temp/1000 ;      // extrait les unité  on va le coder en décimale 
  affu = tab[unit] ;      //lecture du code 7 seg dans le tableau  pour en extraire  les unités, les dizaines,
  dix = (temp/100)%10 ;  // extrait les dixième   les centaines
  affd = tab[dix]  ; qui vont être afficher  comme
  cent = (temp/10)%10 ; // extrait les centième   dans l’expérience 3
  affc = tab[cent] ;    
  mil = temp%10         // millième  non affiché
    PORTB =affu    ;    // afficher les unité 
    PORTC.F0 = 1 ;
    Delay_ms(10);
    PORTC.F0 = 0 ;

    PORTB =affd     ;    // afficher les dixième 


    PORTC.F1 = 1 ;
    Delay_ms(10);      //
    PORTC.F1 = 0    ;

    PORTB =affc  ;    // afficher les centième 


    PORTC.F3 = 1 ;
    Delay_ms(10);
    PORTC.F3 = 0   ;
 }
}

   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
   

On  va résumer  sans  entrer dans les détails du protocole RS232


Comme son nom l'indique les données sont transmises  en série bit après bit 
les octets sont entourés de bits de start et bits de stop
Sur la figure on voit l'octet 10110010 entouré d'un bit de start et un bit de stop
avec la norme rs232  on a la possibilité de rajouter un bit de parité et un deuxième bit de stop
on peut facilement envoyer ou recevoir des données avec un pic, il suffit d'utiliser les fonctions fournies
par Mikroc :

Usart _init                  : choix du débit           


Usart_Data_ready     : vérifie si la donnée est reçue
Usart_Read              :  lecture de la donnée
Usart_Write              : envoi de la donnée

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 
 

Tosc = 1/ fréquence horloge


 pour générer le signal PWM on peut utiliser ce principe qui agit directement sur les registres 
ou peut utiliser les fonctions fournis par Mikroc :
Pwm_init(freq)   :choix de la fréquence en Hz
PWM_change_duty(durée)  : choix du rapport cyclique ( valeur entre 0 pour 0% et 255 pour 100% )
PWM_start ()  :  démarrage du module  PWM 
Pmw_stop() : arrêt du module PWM 

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

               // ou   PWM1_Set_Duty  (i) ; 

          portb = i ;                   // on affiche la valeur sur le portb


        delay_ms(1000) ;                  //on attend 1 sec
    }                 }

Pour placer les instruments virtuels oscilloscope voltmètre  ...etc .


on choisi l'objet dans la bibliothèque 
plusieurs instrument sont présents  comme vous le voyez ils fonctionnent en
temps réel  est peuvent être connectés au circuit  comme les autres
composants   

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:

Command RS RW D7 D6 D5 D4 D3 D2 D1D0 Execution Time


Clear display 0 0 0 0 0 0 0 0 0 1 1.64mS
Cursor home 0 0 0 0 0 0 0 0 1 x 1.64mS
Entry mode set 0 0 0 0 0 0 0 1 I/DS 40uS
Display on/off control 0 0 0 0 0 0 1 D U B 40uS
Cursor/Display Shift 0 0 0 0 0 1 D/C R/L x x 40uS
Function set 0 0 0 0 1 DL N F x x 40uS
Set CGRAM address 0 0 0 1 CGRAM address 40uS
Set DDRAM address 0 0 1 DDRAM address 40uS
Read "BUSY" flag (BF) 0 1 BF DDRAM address -
Write to CGRAM or DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
Read from CGRAM or DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS

I/D 1 = Increment (by 1)         R/L 1 = Shift right


    0 = Decrement (by 1)             0 = Shift left
   
S 1 = Display shift on           DL 1 = 8-bit interface
  0 = Display shift off             0 = 4-bit interface
 
D 1 = Display on                 N 1 = Display in two lines
  0 = Display off                  0 = Display in one line
 
U 1 = Cursor on       F 1 = Character format 5x10 dots
  0 = Cursor off                   0 = Character format 5x7 dots
 
B 1 = Cursor blink on            D/C 1 = Display shift
  0 = Cursor blink off               0 = Cursor shift

Vous n'aurez pas à utiliser Ces commandes car Mikroc dispose de fonctions qui vous permettent d'utiliser Le LCD

voici les fonctions utilisées par Mikroc

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 :

// Association des broche du LCD à celle du pic


sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D4 at RB0_bit;

// 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

Lcd_Out                        affiche un texte à la position spécifiée   exemple Lcd_Out (1, 3, ''bonjour") 


Lcd_Out_Cp                affiche un  texte à la position courante   exemple Lcd_Out (1, 3, ''ici")   
Lcd_Chr                          affiche un caractère à la position sepecifiée   exemple Lcd_Chr (1, 3, ''b")                       
Lcd_Cmd                     envoi une commande a LCD 

                 Réaliser le schéma ci_contre  avec le programme ci_dessous 

  char *text = "Premier  Test  Lcd  ";

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 

Principe de gestion clavier 

Un clavier matricé est composé de lignes ( L1 L2 L3 L4) et de colonnes 


( C1 C2 C3), à l'appui sur une touche une connexion entre une
ligne et une colonne est établi 

exemple  si on appui sur 2,  L1 et C2 seront interconnectées 


Le role du pic est de balayer les lignes et les colonnes en envoyant des codes appropriés contenus dans un
tableau,  pour déterminer la touche appuyée puis le code du chiffre à afficher est prélevé sur une
deuxième table   

Sur Isis  dessiner le schéma ci-dessous 


dans ce schéma on a utilisé des 74ls47 pour le décodage 7 segment 
le principe est différent  de l’expérience 3
Dans Mikroc saisir le code suivant 

l'entree RB3 non utilisé est relier à la masse

     char kp , kp2  ,_dix ,_unit ;


    int i ;
    char  mem = 0 ;
// code à envoyer vers clavier pour balayer les touches et trouver celle  enfoncée   
 char clav[] ={ 0x12,0x81,0x82,0x84,0x41,0x42,0x44,0x21,0x22,0x24,0x11,0x14};
    char clav1[] ={ 0,1,2,3,4,5,6,7,8,9,'*',22 };  // si trouvé prendre valeur du même rang dans cette table

     /*------------------- fonction lecture clavier ----------------------*/


     /*--------------------------------------------------------------------*/
 char getclav(void)
 {
    portb= 0xf0   ;   /* preparation du port */
    scan  :
    if (portb!= 0xf0   )      /* si une touche a ete enfoncé*/
    {for (i=0 ;i<=11 ; i++)    /*blayage  clavier */
      { portb = clav[i] ;
        if (portb== clav[i] )  /* touche trouvé */
         {
           while((portb&0x07) != 0x00)   /* attente relachement touche */
           asm { NOP ;  }

           return clav1[i] ;                   /* envoi du code correspondant */


          }
       }

     } else goto scan ;         /* sinon refaire l'op */


   }
    /* ------------------------routine affichage  ------------------------*/
    void afficher ( char temp)     /* temp parametre d 'entree */
      {     char dix ,unit ;          /* variables  locales*/
           unit = (portd&0x0f ) ;          /*recup l'unite */
              dix =unit ;            /* decalage afficheur  unit ----> dix*/
               unit = temp ;         /*unite*/
                 mem = (dix *16 )+unit ;
                  portd = mem  ;     /* affichage */
       }
void main()
{    trisb = 0x0f  ;
     trisd =0 ;
     trisc = 0 ;
     portc = 0 ;
      portd =0x33 ;
    while(1)
    {
      kp = getclav() ;

      if (kp!=22)       /* si pas code '#'    (22) */


      afficher (kp) ;   /* appel fonction affichage  */
      else  if (kp =22 )    /*si #  est enfoncée lancer la decrimentation */

       {
       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é

Pour gérer ce processus , il faut : activer dans le programme la ou les sources 


d’interruption, et écrire une routine d’interruption appropriée. 
Le contrôle des interruptions se fait grâce aux registres INTCON, PIE1, PIR1, PIE2, 
PIR2. Le registre INTCON regroupe les bits de validation (= enable bit) et de 
signalisation (= flag ou drapeau) des interruptions« de base ». Les interruptions des 
modules périphériques sont gérées par les registres PIE et PIR. Sur le PIC 16F877 
on a deux PIE et deux PIR, étant donné le nombre important de sources 
d’interruptions possibles. 

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é

routine d'interruption à mettre avant main 


void Interrupt() {
 
  if (INTCON.INTF) {     //   SI INTF =1 
     portc.f2 = 0; // Led off 
portd = 0xAE ; //  affiche  ct 
           while (1)
{  asm { NOP ;  } // boucle infini 
                   }

initialisation à mettre dans main


// setup interrupts
 
  INTCON.INTE = 1;          //  interruption sur INT0  active
  INTCON.INTF = 0;  // drapeau à 0
  INTCON.GIE  = 1;  //  interrupptin general GIE   active

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() {

TRISB = 0;                         // PORTB en sortie


  Lcd_Init(&PORTB);         // Initialisation LCD connecté au PORTB
  Lcd_Config(&PORTB, 2, 3, 1, 7, 6,5, 4);
  TRISC  = 0x00;
  TRISD = 0xff;               // PORTC en sortie et  PORTD en en entrée
  while(1) {
   derect = (PORTD & 0b11110000 ) ;  // masquer les bit non utilisés
   switch (derect)
   { case  0b01110000 :
   Lcd_Out(1, 5, mesG )  ;
    break ;
     case  0b10110000 :
    Lcd_Out(1, 5, mesH)  ;
    break ;
     case  0b11010000:
    Lcd_Out(1, 5, mesB )  ;
    break ;
     case  0b011100000:
   Lcd_Out(1, 5, mesD )  ;
     break ;
  }    delay_ms(200) ;   //attente relachement bouton
}}

Vous aimerez peut-être aussi