Delay loop problem

Discussion in 'Embedded Systems and Microcontrollers' started by ShaunManners, Apr 12, 2008.

  1. ShaunManners

    Thread Starter Active Member

    Feb 16, 2008
    72
    1
    Hi All,

    I am working on a project, I asked for help with in the projects forum, and consequently have been working on a 3 phase inverter using the PIC18F4431.

    This is described in Microchips document A900. I learnt the machine code and went through the code that was provided to make sure I understood it... but it doesn't work. So I thought it best to start with the basics and made an LED flash, and made it flash faster when a button was pressed.. I did it using interrupts, and all is great..

    my problem is that I can create a loop that just counts down from 255 to 0 to waste time... but when I copy the loop used in the inverter program (a loop within a loop) the program seems to get caught in an infinite loop, I know this because I turn the LED on before the delay and turn it off after - it never goes off (I have put an oscilloscope on the output to make sure of this)

    The WDT is turned off...

    The other thing is, the code works fine when I use MPLAB sim...

    can anybody see whats wrong?

    Cheers
    Shaun


    MainProg code
    Start:
    movlw b'11111100'
    movwf TRISD
    bsf PORTD, 1


    ;=======================================================================
    MainLoop
    bsf PORTD, 1
    call DELAY
    bcf PORTD, 1
    call DELAY
    goto MainLoop


    ;=======================================================================
    DELAY
    movlw 0xFF
    movwf COUNTER
    loop1
    movlw 0xFF
    movwf COUNTER1
    loop
    decfsz COUNTER1, F
    goto loop
    decfsz COUNTER,1
    goto loop1

    return
    ;=======================================================================
     
  2. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    When posting source code, you should use the "go advanced" button and click the "#" sign on the menu to surround your program with CODE tokens.

    I've taken the liberty to reformat your source so that it's more readable.

    Code ( (Unknown Language)):
    1. MainProg code
    2. Start:
    3.          movlw    b'11111100'  
    4.      movwf    TRISD
    5.      bsf      PORTD, 1
    6.  
    7. ;=============================================
    8. MainLoop
    9.      bsf      PORTD, 1
    10.      call     DELAY
    11.      bcf      PORTD, 1
    12.      call     DELAY
    13.      goto     MainLoop
    14.  
    15. ;=============================================
    16. DELAY
    17.      movlw    0xFF
    18.      movwf    COUNTER
    19. loop1
    20.      movlw    0xFF
    21.      movwf    COUNTER1
    22. loop
    23.      decfsz   COUNTER1, F
    24.      goto     loop
    25.      decfsz   COUNTER,1    
    26.          goto     loop1
    27.          
    28.      return
    29. ;=============================================
    30.  
    I'm not familiar with your implementation of Assembler. However, it appears that most of your labels such as "loop" don't have colons. Aren't they required?

    I don't see a test instruction with a label branch to enable you to exit the loop1/loop code. However, you also don't have any comments in your code, so that makes it really tough for someone else to decipher.
     
  3. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    Here is a link to a LED flash routine written in MPASM. Maybe you can glean an answer to your question from reviewing it.

    hgmjr
     
  4. ShaunManners

    Thread Starter Active Member

    Feb 16, 2008
    72
    1
    Thanks for replying!... yes you are correct, I didn't put any comments in, rather bad practice sorry.. I have added some in now... also thanks for pointing out the code formatting in the advanced settings... when i posted it I hadn't seen that and also it appears to have stripped out the tabs too...

    As for the test instruction, that is decfsz, this decrements the COUNTER variable and if it is 0 then it skips the next instruction... thus exiting the loop.

    I'm not sure about the colons, some people seem to use them, some don't.. I tried both, so it is a bit inconsitant .. I'll try adding them in for all labels.

    Cheers
    Shaun

    Code ( (Unknown Language)):
    1. MainProg code
    2. Start:
    3.          movlw    b'11111100'   ; Setup the port
    4.      movwf    TRISD
    5.      bsf      PORTD, 1      ; turn LED on
    6.  
    7. ;=============================================
    8. MainLoop
    9.      bsf      PORTD, 1     ; Turn LED on
    10.      call     DELAY         ; Add a delay
    11.      bcf      PORTD, 1    ; Turn LED off
    12.      call     DELAY         ; Add a delay
    13.      goto     MainLoop
    14.  
    15. ;=============================================
    16. DELAY
    17.      movlw    0xFF
    18.      movwf    COUNTER ; Moves FF into COUNTER (decimal 255)
    19. loop1
    20.      movlw    0xFF
    21.      movwf    COUNTER1 ;Moves FF into COUNTER1 (decimal 255)
    22. loop
    23.      decfsz   COUNTER1, F ; Decrement COUNTER1, if 0 skip "goto loop" instruction
    24.      goto     loop ;Loop until COUNTER1 is 0
    25.  
    26.      decfsz   COUNTER,1     ; Outer loop, repeats the above loop 255 times
    27.          goto     loop1
    28.          
    29.      return
    30. ;=============================================
    31.  
     
  5. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    Ok, I see:
    Code ( (Unknown Language)):
    1.          decfsz   COUNTER1,F
    and then later:
    Code ( (Unknown Language)):
    1.          decfsz   COUNTER,1
    I don't see a definition anywhere for "F" - is that legal for an implied hex 15, or an error?
    Since I see no definition for F, the assembler may be interpreting it as zero. So, you're subtracting zero from COUNTER1, which will keep it from becoming zero for quite a long time. Until you run out of power, perhaps. ;)

    Consistency in programming style is very important. "Sloppy" code is hard to read. Try to use meaningful names for everything, and put documentation throughout your code. It might seem to be a waste of time now, but when you run across that piece of code a few years later, you will have to take it apart piece by piece to figure out what the heck you were doing - and you will have far less time to make the changes than you had to write it in the first place.

    Pseudocode is a great way to introduce the function of a subroutine. It's also a good way to start developing your program.

    Write the pseudocode to describe what needs to be done, then write the actual program/subroutines to fit the pseudocode.

    The equals sign and dashes are what I use to separate sections and pseudocode from the actual code itself. They're easy on the eyes (not overly busy) and can help you locate a section of code very quickly.

    I also use a comment line as the very last line of the program, so that it's apparent right away if the file has been damaged or chopped off.

    Code ( (Unknown Language)):
    1. PROGNAME: ORG    0000H
    2. ;================================================================
    3. ; Program name: (fill it in)           Revised: (the date)
    4. ; Author: (whodunit)
    5. ; Function: (what the entire program is supposed to do)
    6. ;----------------------------------------------------------------
    7. (initialization/housekeeping)
    8. (branch to start of main routine)
    9. (variables)
    10. ;================================================================
    11. ; Main routine
    12. ; (pseudocode describing main routine)
    13. ;----------------------------------------------------------------
    14. MAIN:
    15.             (do stuff)
    16.              CALL     Subrtn1:
    17.              GOTO     MAIN:
    18. ;================================================================
    19. ; Subroutine 1
    20. ; (pseudocode describing subroutine)
    21. ;----------------------------------------------------------------
    22. Subrtn1:
    23.              (do stuff)
    24.              RETURN
    25. ;----------------------------- END ------------------------------
    26.  
     
  6. ShaunManners

    Thread Starter Active Member

    Feb 16, 2008
    72
    1
    Thanks for that, I may be able to adapt some of that... trouble with me is that I like to know why something wasn't working ;)

    Cheers
    Shaun
     
  7. hgmjr

    Moderator

    Jan 28, 2005
    9,030
    214
    That is an admirable trait. You may find that working through an example program can be a learning experience as well. There are a number of ways to skin this cat. Once you get the example working, you can then experiment to see what happens when you tweak the original code.

    After you get a bit more familiar with the processor and the assembly language, you will be able to return to your original program that gave you trouble and figure out where things went wrong.

    hgmjr
     
  8. ShaunManners

    Thread Starter Active Member

    Feb 16, 2008
    72
    1
    Thanks SgtWookie,

    The funny thing is that I am computing lecturer, and your comments above are exactly what I tell my students ;)... better practice what I preach!!

    The incosistencies are where I have been playing with the code... the F or 1 means that it puts the result of the decrement back in the F register. F is a reserved word... I think it may be declared in the include file... however, if you are right and it is interpreting it as a 0 then that would indeed cause the infinite loop.. I'll look into it.

    I also use dashes and equals to separate functions etc.. but this piece of code was so basic I hadn't bothered.. its a good idea to put that comment at the end.. also thanks for showing me the layout you use for your programs... thats something I'm still getting used to.

    Cheers
    Shaun
     
  9. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    er, WHAT include file?
    You didn't include the include statement in your program listing.
    Include "PIC18F44x.inc" ; perhaps?

    OK, I guess I'm just going to have to download MPLAB and play with it ;)
     
  10. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    What's the output frequency of your 3-phase inverter going to be? Fixed or variable?
     
  11. n9352527

    AAC Fanatic!

    Oct 14, 2005
    1,198
    4
    I don't see anything wrong in your code. This could be a hardware problem.

    Do you have the schematic diagram of your circuit? Do you use enough decoupling capacitors across the supply and close to the PIC? Do you have a current limiting resistor in series with the LED?
     
  12. a088008

    New Member

    Apr 17, 2008
    4
    0
    I agree with SgtWookie. I took the liberty of writing your algorithm in pseudocode. I put a '?' where the 'F' in your code is.

    Code ( (Unknown Language)):
    1.  
    2.  
    3. Main()
    4. {
    5.  while( true )
    6.  {
    7.   LED = on
    8.   Delay()
    9.   LED = off
    10.   Delay()
    11.  }
    12. }
    13. Delay()
    14. {
    15.  counter = 255
    16.  do
    17.  {
    18.   counter1 = 255
    19.   do
    20.   {
    21.    counter1 = counter1 - ?
    22.   }
    23.   while( counter1 != 0 )
    24.   counter = counter - 1
    25.  }
    26.  while( counter != 0 )
    27. }
    28.  
     
  13. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    Yes, F is EQUal to 1. Declared at the very beginning (or it is at the end?) of your .inc file.

    Please DO incremental testing. I learnt that the hard way! Every testable portion of code should be tested before adding more.
     
Loading...