PIC program - Newby question

Discussion in 'Embedded Systems and Microcontrollers' started by Man_in_UK, Sep 11, 2012.

  1. Man_in_UK

    Thread Starter Active Member

    May 13, 2008
    Many years ago I learned how to program a PIC to be a multifunction timer but the program was very basic. It would monitor a bank of switches and run a set time sequence depending on what switch was active.
    It could only ever run one timer sequence at a time.

    I would like to start another project but this one would involve running two routines independently of each other and I do not have a clue where to start.
    (example: if button A is pressed, output a time sequence on pin 1, at the same time still monitor button B. If button B is pressed output a separate time sequence on pin 2)

    Can anyone suggest any sample code I could study to learn such things?

    Sorry for asking such a basic question but I have not kept up with my programming ...... I can't use the word "skills".
  2. Markd77

    Senior Member

    Sep 7, 2009
    C or assembler? <ed> Which PIC? </ed>
    It's fairly simple, instead of checking for the buttons, then going into a sequence of delays, have a short fixed time delay, maybe a millisecond.
    Every time the delay is over;
    check the buttons,
    if a sequence has been started increase a counter for that sequence and change pin state when required.
    Last edited: Sep 11, 2012
  3. Man_in_UK

    Thread Starter Active Member

    May 13, 2008
    Cheers Mark.
    I was using MPLab to write the code, I think that would be assembler.
    I have not yet decided what PIC to use yet as I have not got far enough to work out pin counts. I have to get my head round the code as that is the hard bit for me.

    I understand what your saying about checking the switches. Trouble is, my limited skills only know how to run one timer at a time.
  4. t06afre

    AAC Fanatic!

    May 11, 2009
    I guess your problem will call for using Interrupts. With the most critical part of the program placed in an Interrupt Service Routine(ISR). This is not as hard as many people think. Using assembler is OK. But you might also consider using C. It is no problem to get free versions. That will do more than good in any hobbyist project.
  5. Markd77

    Senior Member

    Sep 7, 2009
    If you have the old code, that would give a better idea of what you are trying to do, if not the sequences would be good.
    In the cold light of day I realise I was underestimating it slightly in my last post.
    A way which would cover most cases is to have a variable for counting the 1ms intervals, a variable for counting which part of the sequence it is in, and a table containing times (number of intervals) for the sequence. Also a flag to indicate if the sequence is running.
    If times were only needed to 1 second resolution, or the sequence was very simple it could be easier.
    There would be one of these for each sequence, and these are 16 bit values which are slightly easier to use in C (it's easy enough in assembler). I've used 65535 (the maximum value for a 16 bit variable) as an end point, but it could be done other ways, like storing how long the table is and having a counter variable for it.
    It could just as easily use 24 or 32 bit variables which would give much longer possible times at the expense of a larger table.

    1 second on, 3 seconds off, 1 minute on, then off and sequence end.
    Table: 1000, 3000, 60000, 65535

    When a button is pressed the first value from the table is fetched into the time counter variable, Time_count.
    Every time the 1ms is up Time_count is decreased by one and tested if it has reached zero. If it has then the Sequence_count is increased by 1, a new value for Time_count is fetched from the table and checked to see if it is the end of sequence marker, and the pin is toggled.
    If Time_count isn't zero then it just checks if the other sequence is running, checks the buttons, waits 1ms, then repeats.
  6. MMcLaren

    Well-Known Member

    Feb 14, 2010
    Something simple like this BoostC example excerpt could easily be converted to assembly language. The two independent timers are based on a 25 msec loop time which is used to sample and debounce the switches.

    Regards, Mike

    Code ( (Unknown Language)):
    1.    while(1)                     // loop forever
    2.    { delay_ms(25);              // 25 msec debounce interval
    3.   /*                                                            *
    4.    *  K8LH parallel switch state logic ("new press" filter)     *
    5.    *                                                            *
    6.    *  swnew  ___---___---_____     sample active lo switches    *
    7.    *  swold  ____---___---____     switch state latch           *
    8.    *  swnew  ___-__-__-__-____     changes, press or release    *
    9.    *  swnew  ___-_____-_______     filter out 'release' bits    *
    10.    *                                                            */
    11.      swnew = ~porta;            // sample active lo switches
    12.      swnew &= 0b00000011;       // on the RA0 and RA1 pins
    13.      swnew ^= swold;            // changes, press or release
    14.      swold ^= swnew;            // update switch state latch
    15.      swnew &= swold;            // filter out 'release' bits
    16.   /*                                                            *
    17.    *  decrement any running timers                              *
    18.    *                                                            */
    19.      if(timer0)                 // if timer 0 "running"
    20.      { timer0--;                // decrement the timer
    21.        if(timer0 == 0)          // if timed out
    22.          porta.2 = 0;           // turn LED0 (RA2) "off"
    23.      }                          //
    25.      if(timer1)                 // if timer 1 "running"
    26.      { timer1--;                // decrment the timer
    27.        if(timer1 == 0)          // if timed out
    28.          porta.3 = 0;           // turn LED1 (RA3) "off"
    29.      }                          //
    30.   /*                                                            *
    31.    *  check switch inputs                                       *
    32.    *                                                            */
    33.      if(swnew.0)                // if sw0 (RA0) "new press"
    34.      { if(timer0 == 0)          // if sw0 timer not running
    35.        { timer0 = 1000/25;      // set timer to 1 second
    36.          porta.2 = 1;           // turn LED0 (RA2) "on"
    37.        }                        //
    38.      }                          //
    40.      if(swnew.1)                // if sw1 (RA1) "new press"
    41.      { if(timer1 == 0)          // if sw1 timer not running
    42.        { timer1 = 5000/25;      // set timer to 5 seconds
    43.          porta.3 = 1;           // turn LED1 (RA3) "on"
    44.        }                        //
    45.      }                          //
    46.    }                            //
    Last edited: Sep 12, 2012
  7. Man_in_UK

    Thread Starter Active Member

    May 13, 2008
    I like the sound of some of that. I think I can use it as my maximum delay will only be 1 second. I will go away and make a start at getting some specifics, a flow diagram is an obvious start.
    I should have really done a bit more homework before I came here asking questions. I will return shortly.

    I like the idea of learning from others code but I can't understand that routine. When I played about in MPLab it all looked so different. I wish I could say that I knew what some of those commands are, but I'm afraid not.
  8. Man_in_UK

    Thread Starter Active Member

    May 13, 2008
    I have never used these before. If you know of any simple code examples for me to look at It would be handy. In assembly would be even better :)
  9. W4GNS


    Dec 1, 2008

    Why not download a demo(free) of SourceBoost and compile/build K8LH's code, then have a look in the Lst file, which is assembler that SourceBoost generates.