help needed with PIC programming

Discussion in 'Embedded Systems and Microcontrollers' started by Eyeru, Sep 4, 2013.

  1. Eyeru

    Thread Starter New Member

    Mar 5, 2013
    4
    0
    Hi all,

    I am currently working on a PIC programming project. I am new to embedded programming, so please bear with me if I come across as an idiot. My project is to program a user interface for a power supply unit, this includes a 3x4 matrix keypad and multiplexed 7segment LEDs. My code includes a function that scans the keypad and verifies the key pressed using polling, and an array with the decoded values to drive the 7 segment displays. My code works fine and displays the correct key pressed on one digit but I can't seem to get how to store the keypresses and display them on the multiplexed displays and shift the displayed numbers to the left as the user enters the 2nd and 3rd...digit numbers

    Below is the function that finds the key pressed and sends value to PORTC where the 7segment displays are connected

    Code ( (Unknown Language)):
    1.  
    2. unsigned char find_key(void)
    3. {
    4.     while (1)
    5.     {
    6.         PORTB &= 0x00;
    7.         PORTBbits.RB5 = 1; //set row 1 high
    8.         wait_1ms ();
    9.        
    10.         if (PORTBbits.RB1)
    11.         {
    12.             wait_5ms();
    13.           if (PORTBbits.RB1)
    14.             key = pat7seg[7]; //send '7' to portc to drive sevenseg display
    15.         }
    16.         if (PORTBbits.RB2)
    17.         {
    18.             wait_5ms();
    19.           if (PORTBbits.RB2)
    20.             key = pat7seg[8]; //send '8'
    21.         }
    22.         if (PORTBbits.RB3)
    23.         {
    24.              wait_5ms();
    25.            if (PORTBbits.RB3)
    26.             key = pat7seg[9]; //send '9'
    27.         }
    28.         PORTB &= 0x00;
    29.         PORTBbits.RB4 = 1;  //set row 2 high
    30.         wait_1ms ();
    31.        
    32.         if (PORTBbits.RB1)
    33.         {
    34.            wait_5ms();
    35.           if (PORTBbits.RB1)
    36.             key = pat7seg[4]; //send '4'
    37.         }
    38.         if (PORTBbits.RB2)
    39.         {
    40.             wait_5ms();
    41.           if (PORTBbits.RB2)
    42.             key = pat7seg[5]; //send '5'
    43.         }
    44.         if (PORTBbits.RB3)
    45.         {
    46.             wait_5ms();
    47.            if (PORTBbits.RB3)
    48.             key = pat7seg[6]; //send '6'
    49.         }
    50.         PORTB &= 0x00;
    51.         PORTBbits.RB6 = 1;   //set row3 high
    52.         wait_1ms ();
    53.        
    54.         if (PORTBbits.RB1)  //check column 1
    55.         {
    56.            wait_5ms();
    57.           if (PORTBbits.RB1)
    58.             key = pat7seg[1]; //send '1'
    59.         }
    60.         if (PORTBbits.RB2)
    61.         {
    62.             wait_5ms();
    63.           if (PORTBbits.RB2)
    64.             key = pat7seg[2]; //send '2'
    65.         }
    66.         if (PORTBbits.RB3)
    67.         {
    68.             wait_5ms();
    69.            if (PORTBbits.RB3)
    70.             key = pat7seg[3]; //send '3'
    71.         }
    72.         PORTB &= 0x00;
    73.         PORTBbits.RB7 = 1;  //set row4 high
    74.         wait_1ms ();
    75.        
    76.         if (PORTBbits.RB1)  //is column 1 pressed?
    77.         {
    78.            wait_5ms();
    79.           if (PORTBbits.RB1)
    80.            key = pat7seg[10]; //send dp
    81.         }
    82.         if (PORTBbits.RB2)
    83.         {
    84.              wait_5ms();
    85.           if (PORTBbits.RB2)
    86.             key = pat7seg[0]; //send '0'
    87.         }
    88.         if (PORTBbits.RB3)
    89.         {
    90.             wait_5ms();
    91.            if (PORTBbits.RB3)
    92.             key = ENTER; //send 'H'
    93.         }
    94.      }
    95.     return key;
    96. }
    97.  
    below is the part of the code I thought would display numbers on the 2 multiplexed 7segment displays but it doesn't work

    Code ( (Unknown Language)):
    1.  
    2. do
    3.     {
    4.         clearDisplay ();
    5.        
    6.        
    7.         Keypressed = find_key();
    8.         while (Keypressed != 0)
    9.         if (Keypressed == ENTER)
    10.                 break;
    11.             Keypressed++;
    12.         Dig1 = Keypressed % 10;  //ones digit
    13.         Dig1 = pat7seg[Dig1];
    14.         Dig2 = Keypressed / 10;
    15.         Dig2 = pat7seg[Dig2];
    16.         for (i = 0; i <= 1; i++)
    17.         {
    18.             PORTC = Dig1;
    19.             PORTDbits.RD6 = 0;
    20.             PORTDbits.RD7 = 1;
    21.             wait_5ms ();
    22.             PORTC = Dig2;
    23.             PORTDbits.RD6 = 1;
    24.             PORTDbits.RD7 = 0;
    25.             wait_5ms ();
    26.         }
    27.  
    28.  }
    29.    
    30.     while (1);
    31.  
    Can you please give me some suggestions as to how I can improve this, thanks a lot in advance.
     
    Last edited by a moderator: Sep 4, 2013
  2. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    First of all, congratulations on your excellent clear formatting. When we see someone who wants help with their code here, and it's a mess to wade through, it's so tempting to say, "Oh, this guy isn't doing anything to make it easy to help him. What else is there to look at?"

    What your clear formatting makes it easy to see is that the button sensing is done in a while(1) loop which seems to have no exit. How's anything meant to happen? My suggestion is that in main() you should call the find_key() routine, which will return a code for any key pressed, or some null value (0 or 0xFF?) if nothing is pressed. Then if there's a keypress, act on it and if not, do other things and loop.
     
    Eyeru likes this.
  3. MrChips

    Moderator

    Oct 2, 2009
    12,437
    3,360
    As far as I can tell I believe your code is stuck here:

    Code ( (Unknown Language)):
    1.  
    2.         while (Keypressed != 0)
    3.         if (Keypressed == ENTER)
    4.                 break;
    5.  
    This is the same as:
    Code ( (Unknown Language)):
    1.  
    2.         while (Keypressed != 0) if (Keypressed == ENTER);
    3.  
    Use this instead:
    Code ( (Unknown Language)):
    1.  
    2.         while (1)
    3.           {
    4.             Keypressed = find_key();
    5.             if (Keypressed)
    6.             {
    7.  
    8.             }
    9.            
    10.           }
    11.  
     
    Last edited: Sep 4, 2013
    Eyeru likes this.
  4. Eyeru

    Thread Starter New Member

    Mar 5, 2013
    4
    0
    First of all, thanks for your encouraging words, JohnP. Secondly, that while(1) loop is in main (), it was meant to be a do...while() loop and does have a curly bracket after it if that's what you mean by an exit. And I do call find_key () in main() as follows:

    Keypressed = find_key();

    But how do I go about storing the next number enterred?

    can while (Keypressed != 0) work as a condition to verify if a key has been pressed? as in the following code

    Keypressed = find_key();
    while (Keypressed != 0)
    if (Keypressed == ENTER)
    break;
    Keypressed++;

    and would the line Keypressed++; ensure that the system keeps on obtaining pressed keys till ENTER key is pressed?
     
  5. MrChips

    Moderator

    Oct 2, 2009
    12,437
    3,360
    No.

    Keypressed++ means add 1 to Keypressed.
     
  6. Eyeru

    Thread Starter New Member

    Mar 5, 2013
    4
    0
    Thanks @ Mr Chips, I see what you mean by my code being stuck at break;

    Keypressed = find_key();

    works for one digit, but as I said above, can you please help me with how to go on with the 2nd digit entered?
     
  7. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    I meant that the find_key() routine has its own while(1) loop; that's the first line in the function, and I don't see any break or return statement to get you out of it. Also the variable "key" is presumably a global, since it isn't defined in the function, so there's no need to return it; all you need is to set it. But make sure you can tell the difference between a key-pressed situation and no key pressed.
     
    Eyeru likes this.
  8. MrChips

    Moderator

    Oct 2, 2009
    12,437
    3,360
    Your problem is not just simply how to code a problem but it is also about creating an algorithm.

    Before you start writing code I suggest you map out on a piece of paper the program algorithm using either pseudo-code or flowchart, or both.

    What you need to do is:

    1) establish the difference between key pressed and no key pressed,

    2) convert from a key-code to a key digit and key function and detecting the differences,

    3) establish a digit pointer indicating which digit (unit) is being addressed,

    4) establish what to do when the ENTER key is pressed repeatedly.
     
    Eyeru likes this.
  9. Eyeru

    Thread Starter New Member

    Mar 5, 2013
    4
    0
    Thanks a lot again, guys. I had a flow chart mapped out when I first started, but I am looking at expanding on it now, good tip there, thanks. @JohnP, if I try to build the code without the return key; statement, I get a warning of an implicit return to a function. What do you mean by I only need to set the global variable 'key'? set it like key = 1;?
    And how can I differentiate between a key press and no key press state....I though the conditional statement;

    if (Keypressed)
    {

    }

    meant 'is there a key pressed? If so do something...' otherwise it's a no-key-pressed state by default

    Another question can I use the following structure to store the values of the four digits to be displayed?

    struct Digit_sel
    {
    unsigned Digit1 : 4;
    unsigned Digit2 : 4;
    unsigned Digit3 : 4;
    unsigned Digit4 : 4;
    }
    Digit_selbits;
     
  10. MrChips

    Moderator

    Oct 2, 2009
    12,437
    3,360
    If you don't return key then find_key(void) should be declared as:

    void find_key(void)

    What you have written is ok except good programming practice would dictate that key should be declared as local:

    Code ( (Unknown Language)):
    1.  
    2. unsigned char find_key(void)
    3. {
    4.   unsigned char key;
    5.  
    6.  return key;
    7. }
    8.  
    You need to remove the while(1) from inside find_key( ).
     
    Eyeru likes this.
Loading...