This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ARM LPC2000 GPIO problem

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?

Parents
  • 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.

Reply
  • 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.

Children
  • @ 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.