1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

C18 Questions

Discussion in 'Microcontrollers' started by 3v0, Jun 25, 2009.

  1. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    I know so little about PIC timers. (or arm ) but i have a question since on the subject here. And not sure if you know but may benefit from a answer.

    If i have 2 times on a pic can i have both on at the same time?
    Also if so ... if both are on and 1 triggers. will the other continue counting?
    if so.... if the other triggers then which function will i be in?
     
  2. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I learned C++ programming mostly online, though I did take one class on it. And I've taken one other computer science class that went through all sorts of math and structure concepts, but that was focused on PC programming. So I am learning MCU programming from the internet. Trying to anyway, I'm just reading whatever microchip document seems related to what I'm doing and tutorials I find online, probably similar to what you're doing. I just get stuck a lot because there's so much out there, and cause I keep having long breaks in working on this where I'm too busy for my hobby.

    Anyway, once I develop a general structure for timed multitasking in C18 I'll be sure to post it, but its been slow going.

    right now I'm working off of this document
    http://www.electro-tech-online.com/custompdfs/2009/09/TIMER_FUNCTIONS_18F4550.pdf

    and in general, the manuals for C18 released by microchip, data sheets, errata and that whole mess.
     
  3. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    Have you read my tutorial on cooperative multitasking ? It uses a timer to block and enable tasks. Even if it is not what you want to do it should get you started.

    3v0's Tutorials

    Bottom entry in the table

    3v0-
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area

    I have, that's actually what I was using, I just lost track of it, like I said I was away from this hobby for a few months, so I forgot where some of the resources I was using were. Thanks.

    Its kind of hard to keep up a hobby when your life goes between super busy and a lot of free time, when you get a break you spend most of it just picking up where you left off. Oh well.
     
  6. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    It you document is fits I would be glad to add it to my list.
     
  7. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    3v0 i think i finally understand that Multitasking stuff a bit thanks to your PDF. But i noticed some error or something you forgot to edit..

    For instance check out page 8 on the left side the line of code:

    Code (text):

    #define DUR 500
     
    Where since KMAX is thought of as (per your example) to be 3. should that have not been a "2" like in the appendix code?
     
  8. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    I will try to create my own code following yours but with 3 task!

    1. Blink LED 1/4 Second. (not half)
    2. Sound speaker (just for fun)
    3. Something complicated like write to a char LCD

    What should happen if one TASK last to long? Would it be ok to mix some Non Multitasking like normal init stuff with some multitasking after? this way i have a normal flow of items initializing and then the multi. stuff after
     
    Last edited: Sep 1, 2009
  9. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    What should happen if one TASK last to long?
    As you know each task is broken down into states. It is up to the author to ensure that no task state runs too long. If a state runs too long other tasks that are ready to run will be delayed. In some cases that is no problem. In time critical tasks it is.
    Would it be ok to mix some Non Multitasking like normal init stuff with some multitasking after?
    There is no problem with running non multitasking code prior to starting multitasking. Once you start the multitasking engine any code that executes must yield or it will screw up the scheduling system.

    You can also run non multitasking code after the engine is started. If you do this none of the tasks will run until you return execution to the engine. I have never done this and would look at what other implications it will have on your code.

    The use of cooperative multitasking does not limit the complexity of the code or any given task. As long as you ensure that each state yields instead of waits, and never runs longer then the timer without yielding, any task length is possible.

    The one thing I did not address was interrupts. The system works much better will polling. With a little work you can extend the system to block waiting for any given register flag. But putting a IO task first in the list it will execute with within 1 timer period of the interrupt.

    You can use interrupts but you need to be sure the interrupt routine + any task does not exceed the length of the timer. If the interrupt happens more then once during the execution of a task state it may fall apart.

    If you increase the timer duration tasks can run longer prior to yielding but it will be impossible to run tasks that require frequent execution.

    Thank for the info on the error in the text.

    3v0
     
  10. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    heh my help was small yours help is better heh thanks. I understand it more now.

    So it would be best to cut my code into sections like you did with the blink ...

    Like when sending characters send about 2 to lcd then run back to main and then if free time then it will resume until all characters are sent. since this is fast most likey it shouldnt bother.

    Also instead of 2 characters maybe around 5 at a time before yielding and checking if another item needs time.
     
  11. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    Yes. That is a blunder on my part. DUR is just the index of a timer used for the duration. It has been fixed and uploaded thanks.

    3v0

     
  12. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    3v0 .... keep the posting engine happy.
     
    Last edited: Sep 2, 2009
  13. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    heh thanks !
     
  14. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    You're already ahead of me Jason, I still haven't got a timer interupt to fire properly, not that I can tell anyway.
     
  15. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    For the multitasking demo there is a zip file you can download with a MPLAB project that is compiled and running.
    The link is on the same line as the pdf.

    3v0
     
  16. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    if i start college soon (as i plan to) i will create videos of all my workings this way i can reteach myself since ill be busy with work, school and family. i will of course share my vids. But im in no way ahead. I just understand the theory.

    I think in my C18 sheet i have timer code but not 100% sure :( but as 3v0 said his code is downloadable and working . at least you can download that step through it a bit and then edit it to your liking. Then when you get better you can create a template and reuse it when ever.
     
  17. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I'm not sure what is keeping this timer interrupt from acting as expected. I know it could be a lot of thigns, since I haven't done much with timers. I'm working on modifying code from chapter 5 of this pdf (the Mplab c18 compiler users guide)

    Code (text):
    #include <p18cxxx.h>
    #include <timers.h>

    #define NUMBER_OF_LEDS 8

    long int counter = 0;

    /* 6 */ void timer_isr (void);
    /* 7 */
    /* 8 */ static unsigned char s_count = 0;
    /* 9 */
    /* 10 */ #pragma code low_vector=0x18
    /* 11 */ void low_interrupt (void)
    /* 12 */ {
    /* 13 */ _asm GOTO timer_isr _endasm
    /* 14 */ }
    /* 15 */
    /* 16 */ #pragma code
    /* 17 */
    /* 18 */ #pragma interruptlow timer_isr save=PROD
    /* 19 */ void
    /* 20 */ timer_isr (void)
    /* 21 */ {
    /* 22 */ static unsigned char led_display = 0;
    /* 23 */
    /* 24 */ INTCONbits.TMR0IF = 0;
                counter += 1;
    /* 25 */
    /* 26 */ s_count = s_count % (NUMBER_OF_LEDS + 1);
    /* 27 */
    /* 28 */ led_display = (1 << s_count++) - 1;
    /* 29 */
    /* 30 */ PORTB = led_display;
    /* 31 */ }
    /* 32 */
    /* 33 */ void
    /* 34 */ main (void)
    /* 35 */ {
    /* 36 */ TRISB = 0;
    /* 37 */ PORTB = 0;
    /* 38 */
    /* 39 */ OpenTimer0 (TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT);
    /* 40 */ INTCONbits.GIE = 1;
    /* 41 */
    /* 42 */ while (1)
    /* 43 */ {
    /* 44 */ }
    /* 45 */ }
     
    its only slightly modified from the version in the manual, I just added a variable to increment so I can see what its doing. Then I'm trying to watch that variable using an Mplab sim watch window. It isnt increasing. It could even be a problem with varaible scope, since I haven't worked with C18 much, and as I mentioned, ive been away from it for a while. It could even be that the simulator doesnt work that way, or perhapse slower than I expect. But thats why I come to you guys, when I'm this clueless, I'll just lead myself further from the answer.

    edit, forgot the details, if I monitor timer0L I get seemingly random variation, perhapse because its looping too fast for me to really tell. The counter varaible seems to stay the same.
     
    Last edited: Sep 2, 2009
  18. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,008
    Likes:
    316
    Location:
    Brisbane Australia
    ONLINE
    Timer1 is classed as a peripheral and so you need to set INTCONbits.PEIE.

    Mike.
     
  19. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    3v0, Ive been trying your tutorial, but I'm having the same problem as when I write my own timer programs, it just sits as if the timer isn't ticking. I have the code unedited, except for arranging the files into a project so it compiles in C18, and for example, now I have it set to pattern four, and the first two LEDs light, and stay lit. I just cant get that timer to actually run.

    the only warning I get is a few "call of function with out prototype" ones, referring to the part where the switch executes the led patterns.

    In case any thing is wrong, or for those who haven't seen the code, here it is. The only change Ive made is to lock the selection to pattern 4, just so I know that the switching isn't the problem. I did that just recently, but the problem with stalling at the first step of the pattern was the same.

    Code (text):
    /*
     * Junebug Demo
     * Purpose: Demonstrate cooporative multitasking
     *     using only the Junebug LED display
     *
     * File: DJ_coop.c
     * Software: BoostC or Microchip C18 compilers
     * Hardware: Junebug (or other debugger + breadboarded circuit)
     *
     * by Daniel Johnson
     * July 2008
     */

    #include "multiCompiler.h"  

    //
    // defines & macros
    //
    #define byte unsigned char

    #define TRUE 1
    #define FALSE 0

    #define LED_PATTERN_MAX 4
    #define INITIAL_PATTERN_ID 2


    #define COUNTER_MAX 3
    #define C_DEBOUNCE 0
    #define C_DELAY0 1
    #define setCounter(X,Y) counter[X] = Y

    #define SET_LATA(val,mask) lata_=(lata_&~mask)|(val&mask)
    #define SET_TRISA(val,mask) trisa_=(trisa_&~mask)|(val&mask)
    //
    // global vars
    //

    // counters triggered by timer0
    unsigned int counter[COUNTER_MAX];

    byte ledPatternChanged;
    byte seenTimerInterrupt;
     
    #include "LED.c"  

    //
    // functions
    //

    // Update counters and set seenTimerInterrupt flag
    void interrupt(void)
    {
      byte cNum;

      intcon_.TMR0IF = 0; // always clear the IF  
      for (cNum=0; cNum<COUNTER_MAX; cNum++)
      {
        if (counter[cNum] != 0)  // hold at 0
        {
          counter[cNum]--;
        }
      }
      seenTimerInterrupt = TRUE;
    }

    // ---
    // Read portb and determine switch settings
    byte readSwitches(void)
    {
      byte readVal,switchVal;

      readVal = portb_;
      switchVal = 0;
      if (!(readVal & 0x01)) switchVal += 0x01;  
      if (!(readVal & 0x04)) switchVal += 0x02;
      if (!(readVal & 0x20)) switchVal += 0x04;
      return switchVal;
    }

    // ---
    // Determine led pattern base on switches
    byte setPattern(byte switchVal)
    {
      static byte ledPatternId_ = INITIAL_PATTERN_ID;
     
      ledPatternChanged = TRUE;

      if (switchVal==1)
      {
        ledPatternId_=0;
      }
      else if ((switchVal==2) && (ledPatternId_<LED_PATTERN_MAX))
      {
        ++ledPatternId_;
      }  
      else if ((switchVal==4) && (ledPatternId_>0))
      {
        --ledPatternId_;
      }
      else
      {
        ledPatternChanged = FALSE;
      }  
      return ledPatternId_;
    }

    //
    // ---
    //
    void main (void)
    {
      byte switchVal = 4;
      byte i, ledPatternId;
     
      // sundry setup
      {
        // speed up the clock to 8MHz, 18F1320
        osccon_.IRCF0=1;  
        osccon_.IRCF1=1;
        osccon_.IRCF2=1;
       
        // configure ports
        adcon1_ = 0xFF;    // all digital
        intcon2_.RBPU = 0; // PORTB weak pullups on
        trisb_ = 0xFF;     // all inputs
        lata_ = 0;
        trisa_ = 0;        // all outputs
     
        // configure Timer0
        t0con_ = 0xD0;  
        intcon_.TMR0IF = 0;    // clear the IF
        intcon_.TMR0IE = 1;    // Enable Timer0 overflow interrupt
        t0con__.TMR0ON = 1;
        intcon_.GIE = 1;
      }
     
      // general init
      {
        ledScan = 1;
        ledIdx = 0;
        seenTimerInterrupt = FALSE;
        ledBits = 0x3F;
        ledPatternId = INITIAL_PATTERN_ID;
        ledPatternChanged = TRUE;
           
        // zero out the counters
        for (i=0; i<COUNTER_MAX;i++) counter[i] = 0;
      }

      while (1)
      {      
        ledPatternChanged = FALSE;
       
        // task1 - turn on the correct LEDs  
        serviceLEDs();

        // task2 - read the switches to select correct LED action
        if ((!counter[C_DEBOUNCE]) && (switchVal=readSwitches()))
        {
          setCounter(C_DEBOUNCE,1000);
          ledPatternId = setPattern(switchVal);
        }  

        // task3 - animate the LED display
       
        //for testing
        ledPatternId = 4;

        switch (ledPatternId)  
        {
          case 0:            // turn off the display
            ledBits = 0;
            break;
          case 1:            // 1st LED to blinks
            blinkLed();
            break;
          case 2:            // alternate 135 and 246
            alternateLEDs();
            break;
          case 3:            // 2 LEDs left to right
            marchLEDs();
            break;
          case 4:            // 2 LEDs left to right and back
            marchBackLEDs();
            break;
        }
       
        { // option sychronization
          #ifdef sync_loop
          while(! seenTimerInterrupt); // wait for timer interrupt
          seenTimerInterrupt = FALSE;
          #endif
        }  
      }
    }
     
     
    Last edited: Sep 4, 2009
  20. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    In file multicompiler.h change

    Code (text):
      #pragma code low_vector=0x18
    to
    Code (text):
      #pragma code low_vector=0x08
    Or download the new zip file which contains the fix.

    This is a bug in my code that did not cause problems until Microchip changed to the new header files. I think it has now been fixed in all the project zip files.

    3v0
     
    Last edited: Sep 5, 2009
  21. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    call of function with out prototype means that function is not seen by the main.

    Try adding:
    Code (text):

    void interrupt(void);
    byte readSwitches(void);
    byte setPattern(byte switchVal);
    void main (void);
     
    right after the:
    #include "multiCompiler.h"
     

Share This Page