CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Matrix 4x4 Keypad w/ interrupt and EEPROM password

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

Matrix 4x4 Keypad w/ interrupt and EEPROM password
PostPosted: Sat Mar 10, 2012 11:25 pm     Reply with quote

This is a little code i've did at the college. The function is simple; read a 4x4 keypad which is polled by an interrupt on RB2. The code can read a password from EEPROM and compare it to a user input.


Code:
/////////////////////////////////////////////////////////////////////////////////
//                 Applications des microcontrolleurs               243-444-RK //
//                         Laboratoire no. 3                                   //
// Programme no 3: Expérimentation avec clavier matriciel style matrice        //
// carrée geré par interruptions(point boni).                                  //
//                                                                             //
// Ce programme vérifie et compare avec les données mis en mémoires morte.     //
// Ces mot de passes sont stocker dans un tableau(array) et en appelant        //
// la fonction read_from_EEPROM() ce mot de passe stocké en EEPROM et mis      //
// dans une variable pour ensuite la comparer avec la combinaison entré par    //
// l'utilisateur.                                                              //
//                                                                             //
// Une porte ET à quatre entrés est relié entre les broches RD4 et RD7. Dès    //
// qu'une touche est appuyé, un niveau bas se produit à la sortie de la        //
// porte ET ce qui à pour effet de causer une interruption EXTERNE             //
// sur l'entré RB2 qui est reliée à celle-ci.                                  //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
// Copyright@Dany Ferron 2012                                                  //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////
//                                                                             //
//                                                                             //
//              _________________                                              //
//            -|1              40|-                                            //
//            -|                 |-                                            //
//            -| PIC18F4550      |-                                            //
//            -|      @20MHz     |-                                            //
//            -|                 |-                                            //
//            -|                 |-                                            //
//            -|                 |-RB2 This is the port I use for the int_EXT2 //
//            -|                 |-                                            //
//            -|                 |-                                            //
//            -|                 |-                                            //
//            -|                 |-RD7                                         //
//            -|                 |-RD6                                         //
//            -|                 |-RD5                                         //
//            -|                 |-RD4                                         //
//            -|                 |-RC7/RX <-This is the connection to the      //
//            -|                 |-RC6/TX ->MELabs serial LCD controller       //
//            -|                 |-                                            //
//            -|                 |-                                            //
//         RD0-|                 |-RD3                                         //
//         RD1-|20             21|-RD2                                         //
//              -----------------                                              //
//   => RD0 to RD7 Connex to the Matrix keypad                                 //
//   => I'm using a 4-way AND gate to provide an interrupt on port RB2.        //
//                                                                             //
//                                                                             //
//                                                                             //
//                                                                             //
//                                                                             //
/////////////////////////////////////////////////////////////////////////////////
#include "Matrix Keyboard 3C.h"
#include "CLAVIER16T c-a interruption.c"
/////////////////////////////////////////////////////////////////////////////////
// Le début de l'addresse mémoire commence à 0xF00000: Il est à noté qu'il faut//
// spécifier au compilateur qu'elle est le type de variable, par défault il    //
// stock en mémoire un integer d'une longueur de 16. Donc pas pratique si l'on // 
// veux lire et stocker un octet à la fois.                                    //
/////////////////////////////////////////////////////////////////////////////////
#rom int8 0xF00000={'9','8','7','6'}
// Definition et initialisation des variables servant au stockage de mot de passe
// en EEPROM
#define PASSWORD_LENGTH 4
char password[PASSWORD_LENGTH] = {};

// Variable de mémorisation des touche de clavier retournés par la fonction
// kbd_getc();
char k;
////////////////////////////////////////////////////////////////////////////////
// L'appui d'une touche provoque un interruption du programme principal.      //
// En mettant au niveau bas les rangées et les colonnes, on identifie quelle  //
// touche est pesée en effectuant un OU logique et la fonction appelée par    //
// l'interruption retourne la valeur de la touche appuyée.                    //
////////////////////////////////////////////////////////////////////////////////
#int_EXT2 // utilisation de l'interruption EXT2 cablé sur le portB bit 2   

void EXT2_isr(void)
   { 
    k=kbd_getc();
   }
// Déclaration de la fonction de lecture du mot de passe stocké en mémoire morte. 
char read_from_EEPROM(int8 adr);

void main()
   {
    // Variables servant à la lecture du code entré par l'utilisateur.
    int1 passwordValid=false;
    int8 inputCount=0;
    char userInput[PASSWORD_LENGTH] = {};
    int8 j=0;
   
    // Variables servant à définir la position du curseur de l'afficheur.
    int8 adr;
   
    // Initialisation des interruptions.
    enable_interrupts(int_EXT2);
    enable_interrupts(GLOBAL);
    ext_int_edge(2,H_TO_L);// Front descendant sur RB2 Interrupt ext 2
   
    //Initialisation de l'affichage.
    printf("%c%c",0xfe,0x1);
    printf("%c%c",0xfe,0x81);
    printf("Entrez votre code");
   
    adr=0xc7;// Adresse de retour pour le curseur.
   
    do
     {
      // Initialisation du port pour la lecture du clavier
      set_tris_d(0x0f);//Bit0 à bit3 en entrée et bit 4 à bit7 en sortie
      output_low(pin_D4);
      output_low(pin_D5);
      output_low(pin_D6);
      output_low(pin_D7);
      // L'appel de cette fonction lit le code qui est en EEPROM à la premiere
      // case d'adresse mémoire disponible dans le Micro controlleur.
      read_from_EEPROM(0x00);
             
      if(k!='\0') // Si une touche est appuyée, donc si interruption
        {
         printf("%c%c",0xfe,adr);
         printf("%c",k);
         delay_ms(300); // Delai servant de fonction anti-rebond(DEBOUNCE)
         printf("%c%c",0xfe,adr);
         printf("*");
         delay_ms(200); // Cache le caractère entré par l'utilisateur.
         // Incrémentation de l'addresse de la position du curseur pour la
         // prochaine touche entrée par l'utilisateur.
         adr++;
         // Vérification du nombre d'appuis par l'utilisateur.
         if(inputCount<PASSWORD_LENGTH)
           {
            userInput[inputCount]=k;
            inputCount++;
           }
         // On s'assure de remettre une valeur NULL à la variable de lecture.
         k='\0';
        }
      // La validation du nombre de touche appuyées se fait ici. 
      else if(inputCount==PASSWORD_LENGTH)
         {
          passwordValid=true;
         
         for(j=0;j<PASSWORD_LENGTH;j++)
           {
            // On compare le code entré par l'utilisateur avec le mot de passe
            // qui à été lut auparavant par la fonction read_from_EEPROM().
            if(userInput[j]!=password[j])
             {
              passwordValid=false;
              printf("%c%c",0xfe,0x1);
              printf("%c%c",0xfe,0x97);
              printf("Votre code est");
              printf("%c%c",0xfe,0xd9);
              printf("incorrect!");
              delay_ms(500);
              printf("%c%c",0xfe,0x1);
              printf("%c%c",0xfe,0xd5);
              printf("Veuillez reessayer");
              printf("%c%c",0xfe,0x1);
              printf("%c%c",0xfe,0x81);
              printf("Entrez votre code");
              adr=0xc7;
             }
            // On remet la chaine entrée par l'utilisateur a NULL pour
            // un autre essai.
            userInput[j]='0';
           }
         // On remet la variable de touche appuyée par l'utilisateur à 0 une
         // fois que les 4 touches on été validées.
         inputCount=0;
         
         if(passwordValid==true)
          {
           printf("%c%c",0xfe,0x1);
           printf("%c%c",0xfe,0x97);
           printf("Votre code est");
           printf("%c%c",0xfe,0xdb);
           printf("correct!");
           delay_ms(1000);
           printf("%c%c",0xfe,0x1);
           printf("%c%c",0xfe,0x81);
           printf("Entrez votre code");
           adr=0xc7;
          }
         }
      }
    while(true);
   }
   // Cette fonction lit et retourne le code qui est en EEPROM.
   char read_from_EEPROM(int8 adr)
      {
       int8 i;
       for(i=0;i<PASSWORD_LENGTH;i++)
         {
          password[i]=read_eeprom(i+adr);
         } 
   return password[i]; 
      }

     

This is its Header file:
Code:
#include <18F4550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL12                    //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV4                  //System Clock by 4
#FUSES USBDIV                   //USB clock source comes from PLL divide by 2
#FUSES VREGEN                   //USB voltage regulator enabled
#FUSES ICPRT                    //ICPRT enabled

#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

The driver i used is a modified CCS driver:

Code:


//////////////////////////////////////////////////////////////////////////////////
////                           CLAVIER16T c-a interruption.c                  ////
////     Clavier matriciel 4x4 gérer par une interruption matérielle          ////
////                           Utilise le port D  du 16F4550                  ////
////           kbd_getc();         // appelle la fonction                     ////
////          char kbd_getc();     // retourne le caractère entrée            ////
////                                                                          ////
////        Auteur : Paul Bernard                                             ////
////                                                                          ////
//////////////////////////////////////////////////////////////////////////////////

#byte kbd = 0xF83                  // adresse du porB= F81h, du porD = F83h

// #define constante équivalence elles sont remplacées par leur valeur lors de la compilation
#define set_tris_kbd(x) set_tris_d(x)      // configuration du port 0=ouput, 1=input

#define COL0 (1 << 4)           // COL0=décalage à gauche de 4 bit : 0001 0000
#define COL1 (1 << 5)           // COL1=décalage à gauche de 5 bit : 0010 0000
#define COL2 (1 << 6)           // COL2=décalage à gauche de 6 bit : 0100 0000
#define COL3 (1 << 7)           // COL3=décalage à gauche de 7 bit : 1000 0000

#define ROW0 (1 << 0)           // ROW0=décalage à gauche de 0 bit : 0000 0001
#define ROW1 (1 << 1)           // ROW1=décalage à gauche de 1 bit : 0000 0010   
#define ROW2 (1 << 2)           // ROW2=décalage à gauche de 2 bit : 0000 0100
#define ROW3 (1 << 3)           // ROW3=décalage à gauche de 3 bit : 0000 1000


#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)           // All_ROWS=0000 1111 le résultat du OU entre Bits des vars ROWx
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3)  //ALL_PINS=1111 1111 le résultat du OU entre Bits des vars ROWx et colx

// Keypad layout:
char const KEYS[4][4] ={{'1','4','7','a'},    //  déclaration d'un tableau de
                        {'2','5','8','0'},    //  caractères de votre clavier
                        {'3','6','9','b'},    //  ( 4 lignes 4 rangées)
                        {'*','/','-','+'}};
char kbd_getc() // retourne le caractère entrée
{     
 
   static BYTE col;
   BYTE kchar;
   BYTE row;

   kchar='\0';     // la variable=une chaine nulle
   for (col=0;col<5;++col)
   {
      switch (col) // exécute l'instruction selon la valeur de col
      {                               
         case 0   : set_tris_kbd(ALL_PINS&~COL0);   // &~ : ET logique avec le complément 1 de COL0
                    kbd=~COL0&ALL_PINS;   // Le portB =~ le comp 1 de COL1 ET ALL_PIN
                    break;   // On sort de sa structure switch
         case 1   : set_tris_kbd(ALL_PINS&~COL1);
                    kbd=~COL1&ALL_PINS;
                    break;
         case 2   : set_tris_kbd(ALL_PINS&~COL2);
                    kbd=~COL2&ALL_PINS;
                    break;
         case 3   : set_tris_kbd(ALL_PINS&~COL3);
                    kbd=~COL3&ALL_PINS;
                    break;
      } 
      if((kbd & (ALL_ROWS))!=(ALL_ROWS))  // si (le portb ET logique 0000 1111) n'égale pas  0000 1111
      { 
         if((kbd & ROW0)==0)  row=0;   // choix de la rangée
         else if((kbd & ROW1)==0) row=1;
         else if((kbd & ROW2)==0) row=2;
         else if((kbd & ROW3)==0) row=3;
         kchar=KEYS[row][col-1];
                 
      }
   }
   set_tris_kbd(ALL_PINS);   // configuration du portB en I/O selon la variable ALL_PINS 
   
   return(kchar);
}


I'm sorry for the comments in french but i think the code itself isn't too complicated to read and understand.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group