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

PIC Interrupts w/keypad

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PIC Interrupts w/keypad
PostPosted: Thu Mar 01, 2012 2:38 pm     Reply with quote

Hi,

I'm trying to interface a 4x4 keypad with interrupts. Here's my issue. I want to verify which key is pressed an put them into an array to later compare that array with a pre defined password.

My PIC: 18F4550
Compiler version: 4.104

Code:
///////////////////////////////////////////////////////////////////////////////
//            Applications des microcontrolleurs        243-444-RK           //
//                            Laboratoire no. 3                              //
// Programme no 3: Expérimentation avec clavier matriciel geré par           //
//                  interruptions(point boni).                               //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright: Dany Ferron 2012                                               //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
#include "Matrix Keyboard 3C.h"
#include "CLAVIER16T c-a interruption.c"

char k;

void code_gestion();



#int_EXT2    // utilisation de l'interruption EXT2 cablé sur le portB bit 2
void  EXT2_isr(void)
{
   //Si une interruption se produit les instructions seront exécutées
   
   
   
   k=kbd_getc();
   
 
}


int1 passwordValid;
int8 j;



#define PASSWORD_LENGTH 4
char password[PASSWORD_LENGTH] = {'9','8','7','6'}, userInput[PASSWORD_LENGTH] = {'0','0','0','0'};
int8 inputCount=0;


void main()//Programme principal.
{
   
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(int_EXT2);
   enable_interrupts(GLOBAL);
   ext_int_edge(2,H_TO_L);//front descendant sur RB2 Interrupt ext 2
   
   //Efface et place le curseur au bon endroit sur l'écran LCD.
   printf("%c%c",0xfe,0x1);
   printf("%c%c",0xfe,0x85);
   printf("%s","enter code");
   
   
   
     
   //Boucle faire tant que...
   do
   {
   
   set_tris_d(0x0F);//Bit0 à bit3 en sortie et bit 4 à bit7 en entrée
     
      //Mettre la sortie à 0
      output_low(pin_D4);
      output_low(pin_D5);
      output_low(pin_D6);
      output_low(pin_D7);
      //Si la variable est plus grande que 0,donc si un bouton est appuyé.
      //Éfface et place le curseur au bon endroit sur l'écran LCD et affiche
   
       if (k!='\0')
        {   
         printf("%c%c",0xfe,0xc3);
         printf("touche pesee");
         printf("%c%c",0xfe,0xd0);
         printf(":%c",k);
         delay_ms(100);
         printf("%c%c",0xfe,0x84);
         printf("%s"," enter code");
         
         userInput[inputCount] = k;
         
         
               
         if(inputCount < PASSWORD_LENGTH)
         {
         
               disable_interrupts(GLOBAL);
               
               
               inputCount++;
             
               printf("%c%c",0xfe,0xd4);
               printf("%s%u","enter code: ",inputCount);
               
               
         
         
         }
         
         k='\0';
         enable_interrupts(GLOBAL);
         
        }
       
    else
    {
        passwordValid = true;
         
       
        for(j=0; j < PASSWORD_LENGTH; j++)
        {            if(userInput[j] != password[j])
            {
                passwordValid = false;
               
            }
           
            userInput[j] = '0';
           
        }
       
        inputCount = 0;
       
       
      if(passwordValid==true)
     
      {
     
      code_gestion();//Appel de la fonction gestion code.
     
      }
         
    }
   
   } while(true);
}
     
  void code_gestion()
   {
         {
     
      printf("%c%c",0xfe,0xda);
      printf("The code is correct");
         }
   
   }


Here's my driver:
Code:


//////////////////////////////////////////////////////////////////////////////////
////                           CLAVIER16T c-a interruption.c                  ////
////     Clavier matriciel 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 really having trouble getting this to work.

Any help would be appreciated here.

Thanks


Last edited by danyboy666 on Sat Mar 10, 2012 2:13 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 2:51 pm     Reply with quote

This thread has code to poll a keypad in a timer interrupt and get a
password from it.
http://www.ccsinfo.com/forum/viewtopic.php?t=45935
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 3:03 pm     Reply with quote

Yes I saw this code before, its not really what I'm looking for though. I prefer using array, this way I can read easily read from EEPROM and reduce to a minimum the length of the code.
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 2:32 pm     Reply with quote

It seems i did not explain myself properly, so let me try this again.

The code is working fine except for one thing, if i press a key for too long, it increments my variable inputCount from 1 to 4. I'm looking for a way to fix this. The interrupt works fine as it is, and the password verification too. If you look at the driver provided, its the same as the one provided by CCS but for with minor differences, the debounce factor. Also i'm using a 4-way "and" gate to provide an interrupt on port RB2.

So again i'm asking for the professional help here as i have no where else to go for this.

Thanks again,

Dany

edit: I found the trouble. I was missing an important synchronisation circuit in between the output of the AND gate and the interrupt port. The project itself didn't demand as much as i wanted to add, but for the PIC to detect only one key pressed at a time (instead of giving pulse for as long as the key was pressed) needed extra hardware that wasn't proposed in the course.

I managed to do it without the extra hardware though, just adding extra delay was enough.

Code:
if(k!='\0') // Si une touche est appuyée, donc si interruption
        {
         printf("%c%c",0xfe,adr);
         printf("%c",k);
         delay_ms(300);
         printf("%c%c",0xfe,adr);
         printf("*");
         delay_ms(200);
         // Incrémentation de l'addresse de la position du curseur pour la
         // prochaine touche entrée par l'utilisateur.
         adr++;
         // Verification du nombre d'appuis par l'utilisateur.
         if(inputCount<PASSWORD_LENGTH)
           {
            userInput[inputCount]=k;
            inputCount++;
           }
         // On s'assure de remmetre une valeur NULL à la variable de lecture.
         k='\0';
        }


Last edited by danyboy666 on Sat Mar 10, 2012 9:15 pm; edited 1 time in total
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 1:59 pm     Reply with quote

Last question, is there a driver for serial LCD 4x20?
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 2:25 pm     Reply with quote

Whose 'serial 4x20 LCD' ??????

There isn't ONE 'standard' !!
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 2:43 pm     Reply with quote

I've checked the product number and i've came up with this:
CFAH2004A-YYH-JP#

http://www.crystalfontz.com/product/CFAH2004AYYHJPE

The serial LCD controller is from MELABS
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 6:07 pm     Reply with quote

I would start by grabbing a copy of the datasheet from Crystalfontz for that display and reviewing it (if you have not already). I use some of their other displays and while the data sheets can be a bit puzzling sometimes, usually all the information is there. If that device is a serial device as you indicate, typically, you will want to look at the data sheet to see what special characters are needed to do things you may want to do (clear display etc)

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 6:58 pm     Reply with quote

Well the display itself is Parallel but i use a serial lcd controller to interface it to the PIC. I know the basics but is can be quit time consuming to type everything, that's why i asked for a driver like flex_lcd...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 8:36 pm     Reply with quote

Quote:
Whose 'serial 4x20 LCD' ??????

He may have this lcd:
http://store.melabs.com/prod/displays/SLCD204.html

Or, he may have this adapter:
Melabs Serial LCD Controller Module -
http://store.melabs.com/prod/SLCDC.html

He needs to clarify this.


Quote:
Last question, is there a driver for serial LCD 4x20?

The command documentation for the SCLD module is here:
http://melabs.com/faq/downloads/slcddoc12.pdf
I guess you want it to be converted to CCS style routines such as
lcd_putc, and use commands similar those used by CCS lcd driver (and
also the flex driver). For example, you would send \f to clear the screen.

I don't know if such a driver exists.
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 9:00 pm     Reply with quote

PCM programmer wrote:
Quote:
Whose 'serial 4x20 LCD' ??????

He may have this lcd:
http://store.melabs.com/prod/displays/SLCD204.html

Or, he may have this adapter:
Melabs Serial LCD Controller Module -
http://store.melabs.com/prod/SLCDC.html

He needs to clarify this.


Quote:
Last question, is there a driver for serial LCD 4x20?

The command documentation for the SCLD module is here:
http://melabs.com/faq/downloads/slcddoc12.pdf
I guess you want it to be converted to CCS style routines such as
lcd_putc, and use commands similar those used by CCS lcd driver (and
also the flex driver). For example, you would send \f to clear the screen.

I don't know if such a driver exists.


That's exactly what I would need PCM_Programmer.

Edit: To clarify your point, my LCD display is a plain old parallel 20X4 LCD. The module i use from MElabs is to convert it to serial.
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sat Mar 10, 2012 11:28 pm     Reply with quote

I've posted the complete source here: http://www.ccsinfo.com/forum/viewtopic.php?p=159307#159307

It surely need improvements but it does the job nonetheless.

I Hope it will be helpful to someone else.

db666
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sun Mar 11, 2012 3:28 pm     Reply with quote

Here's a library i found and modified for an 4x20 LCD

Code:
//////////////////////////////////////////////////////////////////////////////////////////////
//
// SLCD.c
//
// Simplifies the use of a Serial LCD
//
//
//
/////////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>       // library containing serial communication functions

void LCD_ClearDisplay(void)
{
  printf("%c%c",0xFE,0x01);
}
         
void LCD_CursorOn(void)
{
  printf("%c%c",0xFE,0x0E);
}

void LCD_CursorOff(void)
{
  printf("%c%c",0xFE,0x0C);
}

void LCD_DisplayOn(void)
{
  printf("%c%c",0xFE,0x0C);
}

void LCD_DisplayOff(void)
{
  printf("%c%c",0xFE,0x08);
}

void LCD_BlinkOn(void)
{
  printf("%c%c",0xFE,0x0D);
}

void LCD_BlinkOff(void)
{
  printf("%c%c",0xFE,0x0C);
}

void LCD_UnderlineOn(void)
{
  printf("%c%c",0xFE,0x0E);
}

void LCD_UnderlineOff(void)
{
  printf("%c%c",0xFE,0x0C);
}

void LCD_MoveRight(void)
{
  printf("%c%c",0xFE,0x14);
}

void LCD_MoveLeft(void)
{
  printf("%c%c",0xFE,0x10);
}

void LCD_ScrollRight(void)
{
  printf("%c%c",0xFE,0x1C);
}

void LCD_ScrollLeft(void)
{
  printf("%c%c",0xFE,0x18);
}

/*
// This is for a 2x20 LCD
void LCD_Position(unsigned char line, unsigned char column)
{
unsigned char i;

if (line == 1)
   i = 64;
else
   i = 0;  //default is top line
 
if (column >= 0 && column <= 19)
   i += column;
else
   i = 0;  // default is column 0
 
printf("%c%c",0xFE,128 + i);

}


*/
// This is for a 4x20 LCD
void LCD_Position(unsigned char line, unsigned char column)
{
unsigned char i;

if (line == 1)
   i = 0;
else if (line == 2)
   i = 64; 
else if (line == 3)
   i = 20;
else if (line == 4)
   i = 84;
 
if (column >= 0 && column <= 19)
   i += column;
else
   i = 0;  // default is column 0
 
printf("%c%c",0xFE,128 + i);

}
danyboy666



Joined: 01 Mar 2011
Posts: 30

View user's profile Send private message

PostPosted: Sun Mar 11, 2012 10:06 pm     Reply with quote

Now i'm trying to figure out side scrolling on a single line but i haven't got any luck yet.

This is the code i'm trying:
Code:

int8 i;


LCD_Position(1,1);
LCD_ClearDisplay();
delay_ms(100);   


char ScrollTest[20]={"Hello to the world!"};

printf("%s",ScrollTest);


while(true)
  {
   for(i = 0; i < 20; i++)  // Scroll for 20 chars
      {
       lcd_scroll_left();
       delay_ms(300);   // This sets the scroll speed
      }

   
  }

I know it's working for a 2x20 lcd screen but on my 4x40 it just continues to the second line...

I have the values in decimal for the lcd columns:

The value in decimal are:
// Line 1 = 0-19
// Line 2 = 64-83
// Line 3 = 20-39
// Line 4 = 84-103


Do you guys have any ways to resolve this?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion 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