I have a problem reading input pins on the LPC2138. I used the following assignment in the Keil uVision3 and got the following error: CODE FRAGMENT unsigned int Key_0=IOPIN1& 0x00080000; // Read input pin P1.24
ERROR error: KeyPad.c(36): error: #28: expression must have a constant value.
What could be the problem? How do I read an input (IOPIN) and store the value?
You showed too little code - we can' see the scope rule for your variable. Note that for C, you can't declare new variables anywhere in the code.
C allows the variable declaration to assign a constant value, i.e. a compile-time-computable value in the variable declaration.
unsigned my_variable = 0;
Separate your code into:
unsigned Key_0; Key_0 = xxx;
Another thing: Your constant is 0x00080000. Your comment says P1.24. First off, you seem to have miss-placed a zero. But the next problem is that the pin names are zero-relative, so pin 24 would represent 0x01000000. Your constant relates to P1.19.
How about using (1u << 24) if you want to access pin 24? The advantage is of course that you might know which pin you test, without a comment.
Even better would be to create a named constant, telling what P1.24 really is.
if (IOPIN1 & IO1_KEY_0) { }
But are you sure that your variable should be named Key_0? Do you have one wire for each key, or are the keys placed in a grid?
Finally: Your header says GPIO problem. But in reality you have a compilation problem. Your problem isn't reading the GPIO, but to get the compiler to accept your source code.
@ Per Westermark Thanks very much for the corrections and suggestions. I made modifications as per your advice and the program compiled! I'm providing the code here, though i'll need to make modifications before downloading to controller.
#include <LPC213x.h> unsigned char Pos=16; // for i/o p1.16 ... // Declaration for keys unsigned int Key0; unsigned int Key1 ; unsigned int Key2; unsigned int Key3 ; unsigned int Key4; unsigned int Key5; unsigned int Key6; unsigned int Key7 ; unsigned int Key8 ; unsigned int Key9; #define GREEN 0x00FF0000 // 7Seg display p1 //************************************************ // Define 4x4 Keypad I/O mask for columns and rows #define col1 0x00000001<<Pos // p1.16 #define col2 0x00000002 <<Pos //p1.17 #define col3 0x00000004 <<Pos //etc #define col4 0x00000008 <<Pos #define Row1 0x00000010<<Pos #define Row2 0x00000020<<Pos #define Row3 0x00000040<<Pos #define Row4 0x00000080<<Pos // p1.23 //************************************************* //************************************************ unsigned int ZERO= GREEN & 0x00400000 ; // write 0 to 7seg display unsigned int ONE= GREEN & 0x00F90000 ; unsigned int TWO = GREEN & 0x00240000 ; unsigned int THREE= GREEN & 0x00300000 ; unsigned int FOUR= GREEN & 0x00190000 ; unsigned int FIVE = GREEN & 0x00120000 ; unsigned int SIX = GREEN & 0x00200000 ; unsigned int SEVEN = GREEN & 0x00780000 ; unsigned int EIGHT= GREEN & 0x00000000 ; unsigned int NINE= GREEN & 0x00100000 ; //************************************************* // variables unsigned int KeyData; // 7SEG output int KeyBounce; // key debounce time unsigned int keyPort=0x00F00000; //*************************************************** // Function prototypes void Keypad4x4(void) ; void Write_2_7Seg(void); // output to 7seg //*** MAIN *** int main(void) { IODIR1 = 0xFF0F0000; // P1.20..23 defined as Inputs IOSET1 = 0xFFFF0000; IODIR0 = 0x00FF0000; IOCLR0 = ~ GREEN ; IOSET0= GREEN ; // Define 4x4 Keypad I/O mask for keys 0-9 Key0=IOPIN1& Row2 ; Key1=IOPIN1& Row1 ; Key2=IOPIN1& Row2 ; Key3=IOPIN1& Row3 ; Key4=IOPIN1& Row1 ; Key5=IOPIN1& Row2 ; Key6=IOPIN1& Row3 ; Key7=IOPIN1& Row1 ; Key8=IOPIN1& Row2 ; Key9=IOPIN1& Row3 ; while(1) // Loop Continue { Keypad4x4() ; Write_2_7Seg(); } } // Function defs //********************************* // Keypad scan function void Keypad4x4() { IOSET1=keyPort; IOCLR1=col4 ; //clr col1 KeyBounce=60; while(KeyBounce > 0) { KeyBounce--; if(!Key0) break; else if (KeyBounce>3) continue; else KeyData=ZERO; return; } IOSET1=col4; IOCLR1=col3 ; while(KeyBounce > 0) { KeyBounce--; if(!Key1) break; else if (KeyBounce>3) continue; else KeyData=ONE; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key2) break; else if (KeyBounce>3) continue; else KeyData=TWO; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key3) break; else if (KeyBounce>3) continue; else KeyData=THREE; return; } IOSET1=col3; IOCLR1=col2; while(KeyBounce > 0) { KeyBounce--; if(!Key4) break; else if (KeyBounce>3) continue; else KeyData=FOUR; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key5) break; else if (KeyBounce>3) continue; else KeyData=FIVE; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key6) break; else if (KeyBounce>3) continue; else KeyData=SIX; return; } IOSET1=col2; IOCLR1=col1; while(KeyBounce > 0) { KeyBounce--; if(!Key7) break; else if (KeyBounce>3) continue; else KeyData=SEVEN; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key8) break; else if (KeyBounce>3) continue; else KeyData=EIGHT; return; } while(KeyBounce > 0) { KeyBounce--; if(!Key9) break; else if (KeyBounce>3) continue; else KeyData=NINE; return; } } // end of Keypad4x4 //********************************* // write to 7seg Function t void Write_2_7Seg(void) { IOCLR1 = ~ KeyData ; IOSET1=KeyData; }
Once again I say thank you!!
Sorry I failed to specify that the purpose of the program is to read a 4x4 matrix keypad and output key to 7Segment display.
Back to the drawing board again.
Still lots of magic numbers that can't be understood.
What is GREEN? I most definitely can't look at the declaration:
#define GREEN 0x00FF0000 // 7Seg display p1
and deduce any meaning. Do you have a single 7-segment digit placed on P0.16..23? Why name it GREEN?
What does Keypad4x4 mean? Shouldn't the function be called ScanKeypad, to inform that it actually does something?
Your keyboard scanner has an interesting logic. You scan one column at a time with individual timing loops for each individual button. What happens if you have multiple keys pressed?
What are your expected result if you press two keys from the same row? From the same column? Two keys from different rows and columns?
A 4x4 keypad has 16 buttons. You normally write a keyboard scanner that produces a numeric sequence. For example 0..15 for one key pressed, 16 for no key pressed, 17 for multiple keys pressed.
Then you can later convert the key-press into ASCII characters, or 7-segment patterns with a single table lookup depending on what you want to do with the key-presses.
Or if you do support multiple keys, return an unsigned int, with 16 bits for the 16 possible keys.
The normal way is to have one debounce loop and then you walk the 4 columns and pick up the row values, with acceptance only if one single column has one single row bit detected. More advanced scenarios can be implemented but then you normally have to take care of key-down and key-up so that you can implement n-key rollover and auto-repeat if a key is pressed longer than a specific time.
Do you want key repeat? It is common to implement the keyboard scanner so that it doesn't constantly repeat a pressed key (or as extension starts to repeat after a mimimum wait time). If you press a key now, and call your keyboard scanner multiple times, each call will detect the key. That is ok if your display is expected to just show the last key pressed. But if you enter a number, it will be hard to just press a one, and not instead manage to enter several ones, the repetition only controlled by how fast your main loop manages to call your keyboard scanner.
The logic may be simpler if you have one function that performs the debounce, and let this function call another function that performs the low-level scan.
How do you indent your code? A number of lines are first on the line - are you mixing tab and space? Another thing: Is there a hidden message to be extracted by looking at the number of spaces between statement and the semicolon?
Don't create variables ZERO, ONE, TWO, ... Why are they variables? They only get one single assigned constant value, which implies that they are not variables but constants.
And why are they defined as bit-and of the GREEN constant?
Instead, create a 10-entry lookup table that specifies what segments to light for the digit 0..9 (preferably without shifting for actual pins used, to allow the table to be used for multiple 7-segment digits).
Avoid extra global variables. KeyBounce is used by your keyboard scanner, never outside.
// write to 7seg Function t void Write_2_7Seg(void)
It isn't a good idea to use SMS speech in a forum. And it is just as bad to use it in source code.
Write_2_7Seg() could just as well mean the second row of digits, or that you write to two digits.