function to read buttons doesn't work as expected

Discussion in 'Programmer's Corner' started by bug13, Jun 14, 2016.

  1. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Hi guys

    I think it may be a long short to get an answer without the hardware for this, but I am stuck and want to try my luck here. So I basically want to write a function to drive and read a digital IO (the IO need to switch between input and output). And I need to do that to a lot of IOs. So I wrote an function to do that so I don't need to copy and paste the code many many times.

    The thing is it works if I duplicate the code manually, but it doesn't work with my function.

    So here is the codes:
    Code (Text):
    1.     typedef struct
    2.     {
    3.         // b type input 1 - 6
    4.         uint8_t set1 : 1;
    5.         uint8_t reset1 : 1;
    6.         uint8_t set2 : 1;
    7.         uint8_t reset2 : 1;
    8.         uint8_t set3 : 1;
    9.         uint8_t reset3 : 1;
    10.         uint8_t set4 : 1;
    11.         uint8_t reset4 : 1;
    12.         uint8_t set5 : 1;
    13.         uint8_t reset5 : 1;
    14.         uint8_t set6 : 1;
    15.         uint8_t reset6 : 1;
    16.         // VoIP calling status
    17.         uint8_t connecting : 1;
    18.         uint8_t connected : 1;
    19.         // intercom control
    20.         uint8_t intercomEnable : 1;
    21.     }INPUTS;
    codes that works:
    Code (Text):
    1.    
    2. run_every_1ms()
    3. {
    4.         static uint8_t states = 0;
    5.         static uint8_t db1 = 0;
    6.         static uint8_t db2 = 0;
    7.         states++;
    8.  
    9.         // driving and reading first IO
    10.         if (states == 1)
    11.         {
    12.             /* start reading button state*/
    13.             TRISCbits.TRISC5 = 1;         // input
    14.             __delay_us(1);
    15.             if (!PORTCbits.RC5)
    16.             {
    17.                 if (db1 < INPUT_BTN_DEBOUNCE_DELAY)
    18.                     db1++;
    19.                 else
    20.                     inputs.set6 = 1;
    21.             }
    22.             else
    23.             {
    24.                 if (db1 != 0)
    25.                     db1--;
    26.                 else
    27.                     inputs.set6 = 0;
    28.             }
    29.  
    30.             /* drive buttons LEDs */
    31.             TRISCbits.TRISC5 = 0;         // output
    32.             LATCbits.LATC5 = 1;          // high, LED off
    33.         }
    34.         else if (states == STATE_NUM)
    35.         {
    36.             /* drive buttons LEDs */
    37.             LATCbits.LATC5 = 0;          // low, LED on
    38.         }
    39.  
    40.         // driving and reading 2nd IO
    41.         if (states == 1)
    42.         {
    43.             /* start reading button state*/
    44.             TRISCbits.TRISC4 = 1;         // input
    45.             __delay_us(1);
    46.             if (!PORTCbits.RC4)
    47.             {
    48.                 if (db2 < INPUT_BTN_DEBOUNCE_DELAY)
    49.                     db2++;
    50.                 else
    51.                     inputs.reset6 = 1;
    52.             }
    53.             else
    54.             {
    55.                 if (db2 != 0)
    56.                     db2--;
    57.                 else
    58.                     inputs.reset6 = 0;
    59.             }
    60.  
    61.             /* drive buttons LEDs */
    62.             TRISCbits.TRISC4 = 0;         // output
    63.             LATCbits.LATC4 = 1;          // high, LED off
    64.         }
    65.         else if (states == STATE_NUM)
    66.         {
    67.             /* drive buttons LEDs */
    68.             LATCbits.LATC4 = 0;          // low, LED on
    69.         }
    70.        
    71.         // drive and read another io....
    72.         // drive and read another io....
    73.         // drive and read another io....
    74.  
    75.         if (states == STATE_NUM) states = 0;    // reset states
    76. }
    77.  
    my function that doesn't work:
    Code (Text):
    1.  
    2. run_every_1ms()
    3. {
    4.         static uint8_t states = 0;
    5.         static uint8_t db1 = 0;
    6.         static uint8_t db2 = 0;
    7.         states++;
    8.         inputs.set6 = buttonScan(&SET6_TRIS, &SET6_PORT, &SET6_LAT, SET6_PIN, &db1, states);
    9.         inputs.reset6 = buttonScan(&RESET6_TRIS, &RESET6_PORT, &RESET6_LAT, RESET6_PIN, &db2, states);
    10.         // drive and read another io....
    11.         // drive and read another io....
    12.         if (states == STATE_NUM) states = 0;
    13. }

    Code (Text):
    1. uint8_t buttonScan(volatile unsigned char *TRIS,
    2.         volatile unsigned char *PORT,
    3.         volatile unsigned char *LAT,
    4.         uint8_t pinNum,
    5.         uint8_t *db,
    6.         uint8_t states)
    7. {
    8.     uint8_t result;
    9.     if (states == 1)
    10.     {
    11.         /* start reading button state*/
    12.         SET_BIT(*TRIS, pinNum);         // input
    13.         _delay(10);
    14.         if (!CHECK_BIT(*PORT, pinNum))
    15.         {
    16.             if ((*db) < INPUT_BTN_DEBOUNCE_DELAY)
    17.                 (*db)++;
    18.             else
    19.                 result = 1;
    20.         }
    21.         else
    22.         {
    23.             if ((*db) != 0)
    24.                 (*db)--;
    25.             else
    26.                 result = 0;
    27.         }
    28.  
    29.         /* drive buttons LEDs */
    30.         CLR_BIT(*TRIS, pinNum);         // output
    31.         SET_BIT(*LAT, pinNum);          // high, LED off
    32.     }
    33.     else if (states == STATE_NUM)
    34.     {
    35.         /* drive buttons LEDs */
    36.         CLR_BIT(*LAT, pinNum);          // low, LED on
    37.     }
    38.     return result;
    39. }
     
  2. jpanhalt

    AAC Fanatic!

    Jan 18, 2008
    5,699
    907
    Can you elaborate on what that means? What is it not doing, or alternatively, what is it doing that is wrong?

    John
     
  3. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    So a pin is connected to a LED and a button, my code need to drive the led at ~10% duty cycle at ~100Hz. Both method of my code can drive a LED properly. But only the code I manually duplicated can read the button, but my function doesn't read the button properly.

    To be exact, when a button is pressed, the return a my function is undetermined (sometime is true, sometime is false).

    When no buttons are pressed, both code working correctly (which only drive LEDs on 10% duty cycle)
     
  4. dannyf

    Well-Known Member

    Sep 13, 2015
    1,835
    367
    I recently posted a hardware independent readaptation of the Kuhn debouncer - I will post a link later.

    It can be modified to suit your denouncing logic and dual use fairly easily.
     
  5. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    I don't think it's the debounce that cause the problem. If it is, both of my code should not work correctly, as they debounce the same way. However, I am interested in having a look of your hardware independent readaptation of the Kuhn debouncer.
     
  6. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    Addition info:
    For some reason, in my function, pressing button reset6, will trigger button set6 to return true too. It looks like the datas is corrupted inside my function somewhere, but I don't know why and how.
    Code (Text):
    1.         inputs.set6 = buttonScan(&SET6_TRIS, &SET6_PORT, &SET6_LAT, SET6_PIN, &db1, states);
    2.         inputs.reset6 = buttonScan(&RESET6_TRIS, &RESET6_PORT, &RESET6_LAT, RESET6_PIN, &db2, states);
     
  7. hellifino

    New Member

    Jul 2, 2015
    19
    1
    1. CLR_BIT(*TRIS, pinNum); // output
    2. SET_BIT(*LAT, pinNum); // high, LED off
    Are these macros?
     
  8. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    yes, they are:

    Code (Text):
    1. #define SET_BIT(p,n) ((p) |= (1 << (n)))
    2. #define CLR_BIT(p,n) ((p) &= ~((1) << (n)))
    3. #define CHECK_BIT(p,n) ((p) & (1 << (n)))
     
  9. bug13

    Thread Starter Well-Known Member

    Feb 13, 2012
    1,208
    38
    extra info:
    if only reading and driving one pin with my function, it works as expected.
     
  10. dannyf

    Well-Known Member

    Sep 13, 2015
    1,835
    367
    So here is the link: https://dannyelectronics.wordpress.com/2016/06/05/a-generic-software-debouncer/

    In your application, it goes like this:

    Code (Text):
    1.  
    2. #include "keyint.h"  //include kuhn debouncer
    3.  
    4. //user handler for key1, active low
    5. KEY_STATE key1read(void) {
    6.   KEY_STATE tmp;
    7.   IO_IN(KEY1_DDR, KEY1); //key1 as input
    8.   if (IO_GET(KEY1_PORT, KEY1)==0) tmp = KEY_PRESSED; //if key1 low, returned pressed
    9.   else tmp = KEY_NOTPRESSED;
    10.   IO_OUT(KEY1_DDR, KEY1); //key1 return as output
    11.   return tmp;
    12. }
    13.  
    14. //key2 user handler, active high
    15. KEY_STATE key2read(void) {
    16.   KEY_STATE tmp;
    17.   IO_IN(KEY2_DDR, KEY2); //key2 as input
    18.   if (IO_GET(KEY2_PORT, KEY2)==0) tmp = KEY_NOTPRESSED; //low = key not pressed
    19.   else tmp = KEY_PRESSED;
    20.   IO_OUT(KEY2_DDR, KEY2); //key2 return as output
    21.   return tmp;
    22. }
    23.  
    24.  
    25. int main(void) {
    26.  
    27.   KEY_TypeDef key1, key2, key3, ....; //define your keys here
    28.  
    29.   key_init(&key1, key1read); //install user handler for key1
    30.   key_init(&key2, key2read); //install user handler for key2
    31.  
    32.   while (1) {
    33.     key_read(&key1); //read key1
    34.     key_read(&key2); //read key2
    35.  
    36.   if (key_get(&key1) == KEY_PRESSED) do_something();
    37.   if (key_get(&key2) == KEY_PRESSED) do_somethingelse();
    38.  
    39.  
    The number of keys it can access is only limited by the chip.

    Hope it helps.
     
Loading...