Having trouble with this code. Please help.

Discussion in 'Programmer's Corner' started by ke5nnt, Dec 23, 2011.

  1. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Hey guys,

    I wanted to build a circuit and a program to test switch debouncing routines to see how well each one works. The general idea was that I would build a small circuit with a 7-segment display that starts at the number 0. Each time the button is pressed it generates an interrupt that increments the number, and after a delay of 6 seconds, writes the number to eeprom so that after a reset, the 7-segment would return to that number. This would indicate whether the button press was incrementing the desired loop by more than 1 in order to see how stable the debounce routine is.

    The problem in my code is, that after a button press, the number doesn't increment on the display until after the 6 seconds has expired and the eeprom write completes. Before that, it continues to display the previous number. For instance, if the 7-segment is showing a 0 and I press a button, the display continues to show 0 for 6 seconds and then increments to 1, rather than going to 1 immediately after the button press like I want.

    You can find the program and a schematic of the circuit below. One other thing I would like to know is whether the way I've programmed the display is the best way (flashing 1 segment at a time rapidly in order to keep current from exceeding device limits). Thanks for the help.

    Code ( (Unknown Language)):
    1.  
    2. //        CONFIGURATION
    3.  
    4. #include <htc.h>
    5. #define _XTAL_FREQ 4000000
    6. __CONFIG(BOREN_OFF & MCLRE_OFF & PWRTE_ON & WDTE_OFF & FOSC_INTOSCIO & LVP_OFF);
    7.  
    8. /*****************************************************/
    9.  
    10. //        GLOBAL VARIABLS
    11.  
    12. unsigned char fpnum;        //FLASH PATTERN NUMBER
    13. unsigned char dlycnt;        //COUNTER FOR DELAY
    14. unsigned char count;        //GENERAL COUNTER VARIABLE
    15. unsigned char dbnce;        //SWITCH DEBOUNCE COUNTER
    16. unsigned char tcnt;            //COUNTER FOR TIMER 0
    17. bit ewrit;                    //SETS READY TO WRITE EEPROM
    18. /*****************************************************/
    19.  
    20. //        MAIN PROGRAM
    21.  
    22. void main()
    23. {
    24. unsigned char address = 0;    //ADDRESS FOR EEPROM DEFINED
    25. //        OPTIONS
    26. T0CS = 0;                    //TMR0 SOURCE IS INTERNAL CLOCK
    27. PSA = 0;                    //PRESCALER IS ASSIGNED TO TMR0
    28. PS2 = 1;
    29. PS1 = 1;
    30. PS0 = 1;                    //PRESCALER IS 1:256
    31. //        INTCON
    32. INTE = 1;                    //ENABLE EXTERNAL INTERRUPT ON RB0/INT
    33. GIE = 1;                    //ENABLE GLOBAL INTERRUPTS
    34.  
    35. //        GPIO PORT
    36. TRISA=0X3C;                    //TRISA <7:6>OUT <5:2>IN <1:0>OUT
    37. TRISB=0XF;                    //TRISB <7:4>OUT <3:0>IN
    38.  
    39. fpnum = eeprom_read(address);   //COPY EEPROM TO FPNUM
    40.  
    41. PORTA=0;
    42. PORTB=0;                    //CLEAR PORTS
    43.  
    44. for (count=0; count<4; count++)
    45.     {
    46.     RB5=1;
    47.     __delay_ms(250);
    48.     RB5=0;
    49.     __delay_ms(250);        //FLASH THE DECIMAL POINT 4 TIMES
    50.     }
    51.  
    52. while(1)                    //BEGIN MAIN LOOP
    53.  {
    54. /******************DISPLAY A "1"**********************/
    55.  
    56.     if (fpnum==1)
    57.     {
    58.     while (ewrit!=0)        //IF EEPROM FLAG IS SET
    59.       {
    60.       eeprom_write(address, fpnum);        //WRITE FPNUM TO THE EEPROM
    61.       ewrit=0;                //AND CLEAR THE EEPROM FLAG
    62.       }
    63.     while (ewrit==0)        //IF EEPROM FLAG IS CLEAR
    64.       {
    65.       RB6=1;
    66.       __delay_us(100);
    67.       RB6=0;
    68.       RB4=1;
    69.       __delay_us(100);
    70.       RB4=0;
    71.       }
    72.     }
    73. /*****************DISPLAY A "2"***********************/
    74.  
    75.     else if (fpnum==2)
    76.     {
    77.     while (ewrit!=0)
    78.       {
    79.       eeprom_write(address, fpnum);
    80.       ewrit=0;
    81.       }
    82.     while (ewrit==0)
    83.       {
    84.       RB7=1;
    85.       __delay_us(100);
    86.       RB7=0;
    87.       RB6=1;
    88.       __delay_us(100);
    89.       RB6=0;
    90.       RA0=1;
    91.       __delay_us(100);
    92.       RA0=0;
    93.       RA7=1;
    94.       __delay_us(100);
    95.       RA7=0;
    96.       RA6=1;
    97.       __delay_us(100);
    98.       RA6=0;
    99.       }
    100.     }
    101. /****************DISPLAY A "3"************************/
    102.  
    103.     else if (fpnum==3)
    104.     {
    105.     while (ewrit!=0)
    106.       {
    107.       eeprom_write(address, fpnum);
    108.       ewrit=0;
    109.       }
    110.     while (ewrit==0)
    111.       {
    112.       RB7=1;
    113.       __delay_us(100);
    114.       RB7=0;
    115.       RB6=1;
    116.       __delay_us(100);
    117.       RB6=0;
    118.       RA0=1;
    119.       __delay_us(100);
    120.       RA0=0;
    121.       RB4=1;
    122.       __delay_us(100);
    123.       RB4=0;
    124.       RA6=1;
    125.       __delay_us(100);
    126.       RA6=0;
    127.       }
    128.     }
    129. /***************DISPLAY A "4"*************************/
    130.  
    131.     else if (fpnum==4)
    132.     {
    133.     while (ewrit!=0)
    134.       {
    135.       eeprom_write(address, fpnum);
    136.       ewrit=0;
    137.       }
    138.     while (ewrit==0)
    139.       {
    140.       RA1=1;
    141.       __delay_us(100);
    142.       RA1=0;
    143.       RB6=1;
    144.       __delay_us(100);
    145.       RB6=0;
    146.       RA0=1;
    147.       __delay_us(100);
    148.       RA0=0;
    149.       RB4=1;
    150.       __delay_us(100);
    151.       RB4=0;
    152.       }
    153.     }
    154. /***************DISPLAY A "5"*************************/
    155.  
    156.     else if (fpnum==5)
    157.     {
    158.     while (ewrit!=0)
    159.       {
    160.       eeprom_write(address, fpnum);
    161.       ewrit=0;
    162.       }
    163.     while (ewrit==0)
    164.       {
    165.       RB7=1;
    166.       __delay_us(100);
    167.       RB7=0;
    168.       RA1=1;
    169.       __delay_us(100);
    170.       RA1=0;
    171.       RA0=1;
    172.       __delay_us(100);
    173.       RA0=0;
    174.       RB4=1;
    175.       __delay_us(100);
    176.       RB4=0;
    177.       RA6=1;
    178.       __delay_us(100);
    179.       RA6=0;
    180.       }
    181.     }
    182. /***************DISPLAY A "6"*************************/
    183.  
    184.     else if (fpnum==6)
    185.     {
    186.     while (ewrit!=0)
    187.       {
    188.       eeprom_write(address, fpnum);
    189.       ewrit=0;
    190.       }
    191.     while (ewrit==0)
    192.       {
    193.       RB7=1;
    194.       __delay_us(100);
    195.       RB7=0;
    196.       RA1=1;
    197.       __delay_us(100);
    198.       RA1=0;
    199.       RA0=1;
    200.       __delay_us(100);
    201.       RA0=0;
    202.       RA7=1;
    203.       __delay_us(100);
    204.       RA7=0;
    205.       RB4=1;
    206.       __delay_us(100);
    207.       RB4=0;
    208.       RA6=1;
    209.       __delay_us(100);
    210.       RA6=0;
    211.       }
    212.     }
    213. /*****************DISPLAY A "7"***********************/
    214.  
    215.     else if (fpnum==7)
    216.     {
    217.     while (ewrit!=0)
    218.       {
    219.       eeprom_write(address, fpnum);
    220.       ewrit=0;
    221.       }
    222.     while (ewrit==0)
    223.       {
    224.       RB7=1;
    225.       __delay_us(100);
    226.       RB7=0;
    227.       RB6=1;
    228.       __delay_us(100);
    229.       RB6=0;
    230.       RB4=1;
    231.       __delay_us(100);
    232.       RB4=0;
    233.       }
    234.     }
    235. /*****************DISPLAY A "8"***********************/
    236.  
    237.     else if (fpnum==8)
    238.     {
    239.     while (ewrit!=0)
    240.       {
    241.       eeprom_write(address, fpnum);
    242.       ewrit=0;
    243.       }
    244.     while (ewrit==0)
    245.       {
    246.       RB7=1;
    247.       __delay_us(100);
    248.       RB7=0;
    249.       RA1=1;
    250.       __delay_us(100);
    251.       RA1=0;
    252.       RB6=1;
    253.       __delay_us(100);
    254.       RB6=0;
    255.       RA0=1;
    256.       __delay_us(100);
    257.       RA0=0;
    258.       RA7=1;
    259.       __delay_us(100);
    260.       RA7=0;
    261.       RB4=1;
    262.       __delay_us(100);
    263.       RB4=0;
    264.       RA6=1;
    265.       __delay_us(100);
    266.       RA6=0;
    267.       }
    268.     }
    269. /******************DISPLAY A "9"**********************/
    270.  
    271.     else if (fpnum==9)
    272.     {
    273.     while (ewrit!=0)
    274.       {
    275.       eeprom_write(address, fpnum);
    276.       ewrit=0;
    277.       }
    278.     while (ewrit==0)
    279.       {
    280.       RB7=1;
    281.       __delay_us(100);
    282.       RB7=0;
    283.       RA1=1;
    284.       __delay_us(100);
    285.       RA1=0;
    286.       RB6=1;
    287.       __delay_us(100);
    288.       RB6=0;
    289.       RA0=1;
    290.       __delay_us(100);
    291.       RA0=0;
    292.       RB4=1;
    293.       __delay_us(100);
    294.       RB4=0;
    295.       }
    296.     }
    297. /******************DISPLAY A "0"**********************/
    298.  
    299.     else
    300.     {
    301.     fpnum=0;
    302.     while (ewrit!=0)
    303.       {
    304.       eeprom_write(address, fpnum);
    305.       ewrit=0;
    306.       }
    307.     while (ewrit==0)
    308.       {
    309.       RB7=1;
    310.       __delay_us(100);
    311.       RB7=0;
    312.       RA1=1;
    313.       __delay_us(100);
    314.       RA1=0;
    315.       RB6=1;
    316.       __delay_us(100);
    317.       RB6=0;
    318.       RA7=1;
    319.       __delay_us(100);
    320.       RA7=0;
    321.       RB4=1;
    322.       __delay_us(100);
    323.       RB4=0;
    324.       RA6=1;
    325.       __delay_us(100);
    326.       RA6=0;
    327.       }
    328.     }
    329.  }//main program loop
    330. }//main program end
    331. /*************INTERRUPT SERVICE ROUTINE***************/
    332. void interrupt isr(void)
    333.     {
    334. /*************BUTTON PRESS INTERRUPT******************/
    335.     if(INTF==1)                //IF INTF FLAG SET
    336.      {
    337.      for(dbnce=0; dbnce<20; dbnce++)     //DEBOUNCE SWITCH
    338.      {
    339.         __delay_ms(5);
    340.      }
    341.      TMR0=0;                //CLEAR TIMER 0
    342.      T0IE=1;                //ENABLE TMR0 INTERRUPTS
    343.      fpnum++;                //INCREMENT LOOP NUMBER
    344.      tcnt=0;                //CLEAR THE TIMER COUNTER VARIABLE
    345.      INTF=0;                //CLEAR THE INTERRUPT FLAG
    346.      PORTA=0;                //CLEAR PORT A
    347.      PORTB=0;                //CLEAR PORT B
    348.      }
    349. /************TIMER 0 OVERFLOW INTERRUPT***************/
    350.     if(T0IF==1)                //IF TIMER 0 OVERFLOWED
    351.      {
    352.       if(tcnt<92)            //TIMER COUNTER HAS NOT REACHED 6 SECONDS
    353.        {
    354.        tcnt++;                //INCREMENT THE TIMER COUNTER VARIABLE
    355.        T0IF=0;                //CLEAR THE TIMER 0 OVERFLOW INTERRUPT FLAG
    356.        }
    357.       if(tcnt>=92)            //TIMER COUNTER HAS REACHED 6 SECONDS
    358.        {
    359.        T0IF=0;                //CLEAR TIMER 0 INTERRUPT FLAG
    360.        T0IE=0;                //DISABLE TIMER 0 INTERRUPTS
    361.        ewrit=1;                //SET THE EEPROM WRITE NOTIFIER
    362.        }
    363.      }
    364.     }
     
    Last edited: Dec 23, 2011
  2. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    #1: NEVER Put a delay loop in an interrupt. (unless you know exactly what you are doing)

    #2: For interrupt on change, when interrupt is entered, one way to debounce is test the state of the button in a for loop 10 times, if there is a majority of 1's, it bounced, but now time has passed, set a flag variable to indicate input received and exit interrupt.

    in main loop, Keep looking at flag for key pressed (which is set in interrupt), if one is positive, then do the EEEPROM write, by the time you are done writing to EEPROM, the bouncing should be over. The worse switches will bounce for maybe 10mS (most are done in 1 or 2mS), so the only times debouncing is critical is when entering numbers or similar, so as not to double up on numbers or actions. In many cases, debouncing isn't needed.


    http://www.best-microcontroller-projects.com/switch-debounce.html
    http://www.rentron.com/Myke6.htm
    http://www.dattalo.com/technical/software/pic/debounce.html

    The rest of your code is a bit hard to read. Try aliasing some ports using #define

    Such as
    #define portb.4 LED1
    #define portb.5 button1
    etc..

    Makes code FAR easier to read and understand what you are trying to do. A global search and replace with the editor can do this for you pretty quickly.
     
  3. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
  4. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Ryan (ke5nnt),

    What's the purpose of your 6 second timer, please? I'm not trying to criticize. I'm just trying to figure out your logic...

    Also, are RB5 and RB4 connected to the "common anode" of a common-anode 7-segment display?
     
    Last edited: Dec 25, 2011
  5. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Okay, my apologies for leaving this thread hanging, been busy on account of it being Christmas and all, and I've been working on this code.

    Basically, the whole point of this little project was simply to test various debounce routines just to see how well each one worked. The 7-segment display was connected to the pins of the MCU (common cathode was connected to ground).

    The code contains 10 separate loops that display the numbers 0 through 9 on the display. Each time the button is pressed, the interrupt increments the variable "fpnum" by 1. If I press the button, and the display increments by more than 1, I can tell that my debounce routine isn't working. I found the problem with my code today, and everything works quite well.

    The 6 second timer was mostly a learning experiment on my part. I've never used timer 0 before, and since this "project" doesn't serve any real purpose other than testing debounce software, I figured it was a good time to check out timer 0 as well.

    Always appreciate the help and feedback guys, thank you.
     
  6. MrChips

    Moderator

    Oct 2, 2009
    12,449
    3,365
    Please use a title that explains a bit more of your problem.
    "Having trouble with this code. Please help." is of no help to us if you wish us to help you.
     
  7. AlexR

    Well-Known Member

    Jan 16, 2008
    735
    54
    As it stands your code is unreadable and I have no idea of what you are doing or why you are doing it.

    Try breaking up your code into separate logical functions with clear comments telling us what each function is supposed to do and why.
    Also unless you have a VERY GOOD reason to do otherwise keep the interrupt function free from delay loops. Interrupts should be serviced and exited as quickly as possible. Any delays should be done in the main loop.

    If you are testing debounce routines I would have thought that a program to measure how long the switch contacts bounce would be much more useful than one that simply tells you that your debounce has failed (if that is what it does). Once you know how long you must wait for the bouncing to stop then writing the actual debounce routine is a pretty trivial exercise.
     
Loading...