Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
Michael Karas
11/06/03 00:56
Read: 1623 times


 
#57921 - 8052 Puzzler #2
Sometimes an 8051/8051 microcontroller may need to monitor and debounce filter a multiple of inputs. These inputs may arrive at the microcontroller from switches, relay contacts, proximity detectors or opto couplers. I have a module of C code that I have used many times to perform this type of function and recently ported it to an C8051F226 project. On this project there were a total of eight inputs to monitor and they were conveniently all connected to Port 1.

The C code implements the filter and debounce logic by filtering the port 1 values in an array of filter samples. A single subroutine is called on a periodic basis to perform the filtering function (100 Hz rate recommended) and also manages a set of status variables that hold the current filtered status for the eight inputs, one that queues a bit for each input that is seen to transition from a filtered false to a true level and another that queues a bit for each input that is seen to transition from a filtered true level to a false level. The queued transition bits are maintained until they are either polled by the application program or until the input signal has transitioned back to the opposite level.

The routine that is called on a periodic basis is typically called from inside a timer interrupt service routine and thus it is highly desireable to make this routine as efficient as possible. The challenge of this Puzzler is to take advantage of the rich logic instruction opcodes supported by the 8051 and re-code the C routine in assembler language to see how compact it can get while still maintaining the functionality of the C routine. Note that the full source code has ancillary subroutines that are used by the application to fetch the status of the various inputs from the variables that are maintained by the poll/filter routine.

Here is the C code for the subroutine of interest:
#define INPUT_POLL_COUNT  4

/* array of bit flags for input filter */
unsigned char input_filter[INPUT_POLL_COUNT];
unsigned char input_status;              /* current filtered input state */
unsigned char input_previous;            /* previous filtered input state */
unsigned char input_true;                /* saved input true transition */
unsigned char input_false;               /* saved input false transition */

unsigned char code input_xlat[8] = {0x01,0x02,0x04,0x08, /* xlat bit number to mask */
                                    0x10,0x20,0x40,0x80};
unsigned char code input_nxlt[8] = {0xFE,0xFD,0xFB,0xF7, /* xlat bit number to ~mask */
                                    0xEF,0xDF,0xBF,0x7F};

void p1_input_poll(void)
{
    unsigned char input_tmp;
    unsigned char input_or;
    unsigned char input_cur;
    unsigned char i;

    input_cur = P1;                            /* read current input state */

    /* loop to shift filter up by one position and perform */
    /* bit wise equal comparison */
    input_or = 0;                              /* this holds 1 for bits that are */  
    for(i=0; i<INPUT_POLL_COUNT; i++)          /* changing in span of filter table */
    {
        input_or |= input_cur ^ input_filter[i];  /* adjacent pair != so set or */
        input_tmp = input_filter[i];              /* swap so to slide table up */
        input_filter[i] = input_cur;
        input_cur = input_tmp;
    }

    /* produce bit pattern for current stable input data */
    /* if a input goes true its previous false state data is */
    /* automatically cleared and as well if a input goes false */
    /* its previous true going status is cleared */
                 /* no chg where toggles  */   /* mask present status where stable */
    input_status = (input_status & input_or) | (input_filter[0] & ~input_or);

    input_tmp = input_status & (input_status ^ input_previous);
    input_true |= input_tmp;
    input_false &= ~input_tmp;

    input_tmp = input_previous & (input_status ^ input_previous);
    input_false |= input_tmp;
    input_true &= ~input_tmp;

    input_previous = input_status;
}


The full source C source code for the input filter program is available from here: C Source Code.

The corresponding assembly language produced by the Keil C51 compiler is available from here: SRC Translated Assembler Code.

Have Fun
Michael Karas



List of 14 messages in thread
TopicAuthorDate
8052 Puzzler #2      Michael Karas      11/06/03 00:56      
   RE: 8052 Puzzler #2      Jez Smith      11/06/03 02:30      
      RE: 8052 Puzzler #2      Michael Karas      11/06/03 07:42      
   RE: 8052 Puzzler #2      Jez Smith      11/06/03 03:20      
   smaller is beatiful      Peter Dannegger      11/06/03 08:19      
      RE: smaller is beatiful      Michael Karas      11/06/03 08:42      
      RE: smaller is beatiful      Michael Karas      11/06/03 17:08      
         RE: smaller is beatiful      Peter Dannegger      11/07/03 06:39      
   RE: 8052 Puzzler #2      Mahmood Elnasser      11/07/03 04:17      
      Answer      Andy Neil      11/07/03 05:34      
         RE: Answer      Michael Karas      11/07/03 06:05      
            RE: Answer      Mahmood Elnasser      11/07/03 08:08      
               RE: Answer      Erik Malund      11/07/03 08:23      
               RE: Answer      Michael Karas      11/07/03 08:32      

Back to Subject List