|
|
View previous topic :: View next topic |
Author |
Message |
danyboy666
Joined: 01 Mar 2011 Posts: 30
|
PIC Interrupts w/keypad |
Posted: Thu Mar 01, 2012 2:38 pm |
|
|
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
|
|
|
danyboy666
Joined: 01 Mar 2011 Posts: 30
|
|
Posted: Thu Mar 01, 2012 3:03 pm |
|
|
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
|
|
Posted: Tue Mar 06, 2012 2:32 pm |
|
|
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
|
|
Posted: Sat Mar 10, 2012 1:59 pm |
|
|
Last question, is there a driver for serial LCD 4x20? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sat Mar 10, 2012 2:25 pm |
|
|
Whose 'serial 4x20 LCD' ??????
There isn't ONE 'standard' !! |
|
|
danyboy666
Joined: 01 Mar 2011 Posts: 30
|
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Sat Mar 10, 2012 6:07 pm |
|
|
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
|
|
Posted: Sat Mar 10, 2012 6:58 pm |
|
|
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
|
|
Posted: Sat Mar 10, 2012 8:36 pm |
|
|
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
|
|
Posted: Sat Mar 10, 2012 9:00 pm |
|
|
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
|
|
|
danyboy666
Joined: 01 Mar 2011 Posts: 30
|
|
Posted: Sun Mar 11, 2012 3:28 pm |
|
|
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
|
|
Posted: Sun Mar 11, 2012 10:06 pm |
|
|
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? |
|
|
|
|
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
|