|
|
View previous topic :: View next topic |
Author |
Message |
asadi.siyavash@gmail.com
Joined: 22 Aug 2013 Posts: 22
|
4x4 Keypad Problem Pic18fxxkxx |
Posted: Thu Aug 22, 2013 3:59 pm |
|
|
Hi, all I am new programmer in CCS,
I read CCS manual and also many topic about keypad,
I used PCM Programmer's code :
Code: |
#include <18F452.h>
#fuses EC_IO,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//=============================
//Keypad connection:
#define row0 PIN_B4
#define row1 PIN_B5
#define row2 PIN_B6
#define row3 PIN_B7
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define col3 PIN_B3
// Keypad layout:
char const KEYS[4][4] =
{{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}};
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init()
{
//set_tris_b(0xF0);
//output_b(0xF0);
port_b_pullups(true);
}
short int ALL_ROWS (void)
{
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
char kbd_getc()
{
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
{
switch (col)
{
case 0:
output_low(col0);
output_high(col1);
output_high(col2);
output_high(col3);
break;
case 1:
output_high(col0);
output_low(col1);
output_high(col2);
output_high(col3);
break;
case 2:
output_high(col0);
output_high(col1);
output_low(col2);
output_high(col3);
break;
case 3:
output_high(col0);
output_high(col1);
output_high(col2);
output_low(col3);
break;
}
if(kbd_down)
{
if(!ALL_ROWS())
{
kbd_down=false;
kchar=last_key;
last_key='\0';
}
}
else
{
if(ALL_ROWS())
{
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
//===========================
void main()
{
char k;
kbd_init();
printf("\r\Starting ...");
while(TRUE)
{
k=kbd_getc();
if(k!=0)
{
if(k=='*')
printf("%c", '*');
else
printf("%c", k);
}
}
} |
it is work very well I changed 18f452 with 16f877A it work good too, but when I changed header with 18f26k20 OR 18f46k20 it doesn't work. Then after search in the forum I understood that I should use pull up resistor for row, after this it work and but after 3 or 4 press it doesn't work.
My simulator program is Proteus and my compiler is CCS4.13
and it is my header code with 18f26k20:
Code: |
#include <18F26K20.h>
#device adc=10
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES LP //Low power osc < 200 khz
#FUSES NOBROWNOUT //No brownout reset
//#FUSES WDT_NOSLEEP //Watch Dog Timer, disabled during SLEEP
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC // setup internal oscillator
|
Sincerely yours |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 22, 2013 9:48 pm |
|
|
That's not my keypad code. That's Ahmed's code, from the Code Library.
Quote: |
#include <18F26K20.h>
#device adc=10
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES LP //Low power osc < 200 khz
#FUSES NOBROWNOUT //No brownout reset
//#FUSES WDT_NOSLEEP //Watch Dog Timer, disabled during SLEEP
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC
|
Also in the code above, you have three different oscillator fuses. You
should only have one.
Quote: | but when I changed header with 18f26k20 OR 18f46k20 it doesn't work |
When you change to a new PIC and it doesn't work, read the Migration
document for the new PIC. It's named:
PIC18F4520 → PIC18F45K20 Migration
http://ww1.microchip.com/downloads/en/DeviceDoc/41310A.pdf
Read about the pull-up differences at the top of page 3:
Quote: |
The RBPU bit is still the global weak pull-up enable and the WPUB register
powers-up with all pull-ups enabled to preserve the functionality of the
WPUA bit for legacy code. Where as the internal weak pull-up resistors on
inputs were globally enabled or disabled on the PIC18F4520, the
PIC18F45K20 has independent control of the weak pull-ups, where
each pull-up has a control bit in the WPUB register. |
Then read the 18F26K20 data sheet:
Quote: |
10.3.1 WEAK PULL-UPS
Each of the PORTB pins has an individually controlled weak internal
pull-up. When set, each bit of the WPUB register enables the corresponding
pin pull-up. |
Next, look up this function in the CCS manual:
Code: | port_b_pullups(true); |
It says:
Quote: |
Parameters: value is TRUE or FALSE on most parts, some parts that allow pullups to be specified on individual pins permit an 8 bit int here, one bit for each port pin. upmask for ports that permit pullups to be specified on a pin basis. This mask indicates what pins should have pullups activated. A 1 indicates the pullup is on |
In other words, to turn on all pull-ups, you do this:
Code: | port_b_pullups(0xFF); |
or
Code: | port_b_pullups(0b11111111); |
|
|
|
asadi.siyavash@gmail.com
Joined: 22 Aug 2013 Posts: 22
|
|
Posted: Fri Aug 23, 2013 2:35 am |
|
|
thank you PCM programmer for your good suggestion I read data and links that you sent, but with when I changed the code, it doesn't work again. I can't understand why I need internal pull up when I used external pull up?
this is my last Code:
Code: | #include <18F26K20.h>
#device adc=10
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
//#FUSES LP //Low power osc < 200 khz
#FUSES NOBROWNOUT //No brownout reset
//#FUSES WDT_NOSLEEP //Watch Dog Timer, disabled during SLEEP
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#FUSES INTRC
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//=============================
//Keypad connection:
#define row0 PIN_B4
#define row1 PIN_B5
#define row2 PIN_B6
#define row3 PIN_B7
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define col3 PIN_B3
// Keypad layout:
char const KEYS[4][4] =
{{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}};
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init()
{
//set_tris_b(0xF0);
//output_b(0xF0);
port_b_pullups(true);
}
short int ALL_ROWS (void)
{
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
char kbd_getc()
{
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
{
switch (col)
{
case 0:
output_low(col0);
output_high(col1);
output_high(col2);
output_high(col3);
break;
case 1:
output_high(col0);
output_low(col1);
output_high(col2);
output_high(col3);
break;
case 2:
output_high(col0);
output_high(col1);
output_low(col2);
output_high(col3);
break;
case 3:
output_high(col0);
output_high(col1);
output_high(col2);
output_low(col3);
break;
}
if(kbd_down)
{
if(!ALL_ROWS())
{
kbd_down=false;
kchar=last_key;
last_key='\0';
}
}
else
{
if(ALL_ROWS())
{
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
//===========================
void main()
{
char k;
port_b_pullups(true);
kbd_init();
port_B_pullups(0xFF);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
printf("\r\Starting ...");
while(TRUE)
{
k=kbd_getc();
if(k!=0)
{
if(k=='*')
printf("%c", '*');
else
printf("%c", k);
}
}
} |
really thanks for spending your time for solving newer Programmer like me |
|
|
asadi.siyavash@gmail.com
Joined: 22 Aug 2013 Posts: 22
|
|
Posted: Sat Aug 24, 2013 9:45 pm |
|
|
any idea?
please help me after 2 days yet I can't solve my problem
I need your guides,
best regards. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 24, 2013 10:43 pm |
|
|
Quote: | my compiler is CCS4.13 |
What's your real compiler version ? And why does nearly every newbie
leave off the last one or two digits of their version number ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Sun Aug 25, 2013 12:28 am |
|
|
On the pull-ups, nowhere did you tell us that you had got external pull-ups....
You know your hardware, we don't.
Critical thing is the compiler version.
Without this though add one fuse:
NOPBADEN
The chip defaults to setting portB, as _analog_, unless this fuse is selected.
Some compiler versions will default to selecting this fuse.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Aug 25, 2013 12:42 am |
|
|
That's why I wanted to know his version. I had checked, and in vs. 4.141
if you don't specify the fuse, it defaults to PBADEN (analog for PortB).
But, the startup code sets PortB to digital i/o, overriding the fuse.
Code: |
00028: MOVF ANSELH,W
0002A: ANDLW E0
0002C: MOVWF ANSELH
|
His version may not do that. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Sun Aug 25, 2013 12:57 am |
|
|
Exactly.
I tested a low 4.13x version, and it doesn't.
This is why version numbers x.xxx, are so critical.
Best Wishes |
|
|
asadi.siyavash@gmail.com
Joined: 22 Aug 2013 Posts: 22
|
|
Posted: Tue Aug 27, 2013 1:01 pm |
|
|
Hi, thank you for replying & really very good support, your good support that was one of my reason for selecting CCS.
My compiler in PC is 4.13 and in my laptop PCWHD 4.140 but in both of them I have this problem.
I solved my keypad problem by changing the keypad function in the row for, I add delay_ms(10); my problem solved till I used uart channel two, when I used uart2 my keypad doesn't work, refer 18f46k22 datasheet I should set register of each port for using digital I/O & each port has ANSEL register, for example ANSELA, ANSELB , ANSELC &... but refer your guide and.... you said I should use just set ANSELH, & can you describe your code:
Code: |
00028: MOVF ANSELH,W
0002A: ANDLW E0
0002C: MOVWF ANSELH |
& if I want to change other port like PORTA to digital I/O what I should do?
Also I don't understand how I can set ANSEL A,B & ...
and in the end please suggest an ebook to learn something like these,
it is my simple keypad code:
Code: |
#include <18F46K22.h>
#device adc=16
#fuses HSH,PUT,NOPROTECT,NOLVP,NOWDT,NOBROWNOUT,NOPLLEN,NOPBADEN,NOXINST
#use delay(clock=20000000) //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,stream=S1, ERRORS)
#use rs232(baud=9600, xmit=PIN_D6, rcv=PIN_D7,stream=XBEE, ERRORS)
//------------------
//keypad start
//------------------
//Keypad connection:
#define row0 PIN_B4
#define row1 PIN_B5
#define row2 PIN_B6
#define row3 PIN_B7
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define col3 PIN_B3
// Keypad layout:
char const KEYS[4][4] =
{{'7','4','1','P'},
{'8','5','2','0'},
{'9','6','3','E'},
{'A','B','C','M'}};
#define KBD_DEBOUNCE_FACTOR 100 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init()
{
port_b_pullups(true);
}
short int ALL_ROWS (void)
{
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
int8 keypad()
{
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
{
switch (col)
{
case 0:
output_low(col0);
output_high(col1);
output_high(col2);
output_high(col3);
break;
case 1:
output_high(col0);
output_low(col1);
output_high(col2);
output_high(col3);
break;
case 2:
output_high(col0);
output_high(col1);
output_low(col2);
output_high(col3);
break;
case 3:
output_high(col0);
output_high(col1);
output_high(col2);
output_low(col3);
break;
}
if(kbd_down)
{
if(!ALL_ROWS())
{
kbd_down=false;
kchar=last_key;
last_key='\0';
}
}
else
{
if(ALL_ROWS())
{
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
delay_ms(10);//I insert this line and it correct my problem a bit
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
//-------------------
//end of keypad
//-------------------
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //13.1 ms overflow
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_timer_5(T5_DISABLED | T5_DIV_BY_1);
setup_timer_6(T6_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
enable_interrupts(INT_RTCC);
enable_interrupts(int_rda);// rs232 hardware 1 interrupt
enable_interrupts(GLOBAL);
char k;
kbd_init();//intial keypad
printf(S1,"hi GOD");
while(TRUE)
{
k=keypad();
if(k!=0)
{
if(k=='*')
fprintf(S1,"%c", '*');
else
fprintf(S1,"%c", k);
}
}
}
|
really thanks,
Sincerely yours. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Aug 28, 2013 4:59 am |
|
|
setup_adc(NO_ANALOGS);
There is no such compiler version as 4.13. 4.013?. If so, forget it and put 4.140 on the system. Version numbers are always x.xxx. The earliest V4 compiler that worked reasonably, was about 4.070. |
|
|
|
|
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
|