Software PWM lockup on a 16F877A


Closed Thread
Results 1 to 14 of 14
  1. #1

    Default Software PWM lockup on a 16F877A

    16F877A @ 20MHz
    I've finally sorted out the serial lines so that i receive test messages upon start-up...

    the program is quite a simple way of doing an interrupt based software PWM (IMHO)

    However...
    it goes through a sequence designed to check i have everything setup properly, it flashes an LED and sends a couple of messages up the comm port...
    At the moment, i have my laptop set to talk down the comm lines for diagnostics purposes...

    The program gets into the main loop and then locks up...
    according to what it throws back up the comm port, it receives two bytes from my laptop (not sent by me) 210 and 59 and then locks up. The two bytes are the same every time i run it...

    the fact that it transmits these two bytes back successfully indicates the comms RX INT handler is behaving... not sure where these bytes come from but thats an issue to be sorted later...

    This implementation is only a 10 channel software PWM system to test my code before moving onto a monster 50 PWM channels...
    It uses TMR0-INT for the time slicing... it should already be set to FOSC/4 acording to the manual. The only thing i'm concerned about is that tmr0 is used by the watchdog...

    Below is the code, i have no idea why it's crashing nor where it is crashing. Hopefully someone can spot a stupid mistake...
    Be aware, some of the code is commented out because it's written for the target PIC18...

    Code:
    Define  OSC				20						' Set clock speed
    
    'MEMCON.7 = 0                                    ' Disable external memory bus
    ADCON1.0 = 1
    ADCON1.1 = 1
    ADCON1.2 = 1
    ADCON1.3 = 1
    TRISA = %00000000
    TRISB = %00000000
    TRISC = %00000000
    TRISD = %00000000
    TRISE = %00000000
    
    PORTA = 0
    PORTB = 0
    PORTC = 0
    PORTD = 0
    PORTE = 0
    
    'Setup UART1
    'BAUDCON.3 = 0                                  ' (BRG16)   8 bit baud rate gen
    'BAUDCON.1 = 0                                  ' (WUE)     Wake up disabled
    'BAUDCON.0 = 0                                  ' (ABDEN)   Auto Baud disabled
    'SPBRG = 64 '129                                    ' 19.2Kbps @ 20MHz
    'TXSTA.6 = 0                                    ' (TX9)     8 bit transmission
    'TXSTA.4 = 0                                    ' (SYNC)    Asynchronous mode
    'TXSTA.2 = 1                                    ' (BRGH)    Low Speed
    'TXSTA.5 = 1                                    ' (TXEN)    Transmit enable
    RCSTA.6 = 0                                    ' (RX9)     8 bit receive
    RCSTA.3 = 0                                    ' (ADDEN)   Address detect disabled
    RCSTA.4 = 1                                    ' (CREN)    Continueous recieve enabled
    RCSTA.7 = 1                                    ' (SPEN)    Port Enable
    
    'DEFINE HSER_RCSTA 208
    DEFINE HSER_TXSTA 32
    DEFINE HSER_BAUD 19200
    HSEROUT ["Initialising",10,13]
    RXcounter VAR BYTE
    RXBUFFER VAR BYTE[12]
    
    C1B1 VAR PORTA.0
    C1B2 VAR PORTA.1
    C1B3 VAR PORTA.2
    C1B4 VAR PORTA.3
    C1B5 VAR PORTA.4
    C2B1 VAR PORTB.0
    C2B2 VAR PORTB.1
    C2B3 VAR PORTB.2
    C2B4 VAR PORTB.3
    C2B5 VAR PORTB.4
    'C3B1 VAR PORTD.1
    'C3B2 VAR PORTD.2
    'C3B3 VAR PORTD.3
    'C3B4 VAR PORTD.4
    'C3B5 VAR PORTE.0
    'C4B1 VAR PORTE.1
    'C4B2 VAR PORTE.2
    'C4B3 VAR PORTE.3
    'C4B4 VAR PORTE.4
    'C4B5 VAR PORTE.5
    'C5B1 VAR PORTE.6
    'C5B2 VAR PORTE.7
    'C5B3 VAR PORTF.0
    'C5B4 VAR PORTF.1
    'C5B5 VAR PORTF.2
    'C6B1 VAR PORTF.3
    'C6B2 VAR PORTF.4
    'C6B3 VAR PORTF.5
    'C6B4 VAR PORTF.6
    'C6B5 VAR PORTG.0
    'C7B1 VAR PORTG.1
    'C7B2 VAR PORTG.3
    'C7B3 VAR PORTG.4
    'C7B4 VAR PORTG.5
    'C7B5 VAR PORTG.6
    'C8B1 VAR PORTG.7
    'C8B2 VAR PORTH.0
    'C8B3 VAR PORTH.1
    'C8B4 VAR PORTH.2
    'C8B5 VAR PORTH.3
    'C9B1 VAR PORTH.4
    'C9B2 VAR PORTH.5
    'C9B3 VAR PORTH.6
    'C9B4 VAR PORTH.7
    'C9B5 VAR PORTJ.0
    'C10B1 VAR PORTJ.1
    'C10B2 VAR PORTJ.2
    'C10B3 VAR PORTJ.3
    'C10B4 VAR PORTJ.4
    'C10B5 VAR PORTJ.5
    
    PWMINT var byte[8]
    
    PWMARKER var byte
    PWMARKER = 1
    
    BITCOUNTER VAR BYTE
    BITCOUNTER = 1
    PERIODCOUNTER VAR BYTE
    PERIODCOUNTER = 1
    PROGCOUNTER VAR BYTE
    PROGCOUNTER = 1
    
    'DV  VAR BYTE[30]                        ; Program Duration Var
    BV1 VAR BYTE                        ; Zone1 Red
    BV2 VAR BYTE                        ; Zone1 Green
    BV3 VAR BYTE                        ; Zone1 Blue
    BV4 VAR BYTE                        ; Zone1 Yellow
    BV5 VAR BYTE                        ; Zone1 White
    BV6 VAR BYTE                        ; Zone2 Red
    BV7 VAR BYTE                        ; Zone2 Green
    BV8 VAR BYTE                        ; Zone2 Blue
    BV9 VAR BYTE                        ; Zone2 Yellow
    BV10 VAR BYTE                       ; Zone2 White
    'BV11 VAR BYTE[30]
    'BV12 VAR BYTE[30]
    'BV13 VAR BYTE[30]
    'BV14 VAR BYTE[30]
    'BV15 VAR BYTE[30]
    'BV16 VAR BYTE[30]
    'BV17 VAR BYTE[30]
    'BV18 VAR BYTE[30]
    'BV19 VAR BYTE[30]
    'BV20 VAR BYTE[30]
    'BV21 VAR BYTE[30]
    'BV22 VAR BYTE[30]
    'BV23 VAR BYTE[30]
    'BV24 VAR BYTE[30]
    'BV25 VAR BYTE[30]
    'BV26 VAR BYTE[30]
    'BV27 VAR BYTE[30]
    'BV28 VAR BYTE[30]
    'BV29 VAR BYTE[30]
    'BV30 VAR BYTE[30]
    'BV31 VAR BYTE[30]
    'BV32 VAR BYTE[30]
    'BV33 VAR BYTE[30]
    'BV34 VAR BYTE[30]
    'BV35 VAR BYTE[30]
    'BV36 VAR BYTE[30]
    'BV37 VAR BYTE[30]
    'BV38 VAR BYTE[30]
    'BV39 VAR BYTE[30]
    'BV40 VAR BYTE[30]
    'BV41 VAR BYTE[30]
    'BV42 VAR BYTE[30]
    'BV43 VAR BYTE[30]
    'BV44 VAR BYTE[30]
    'BV45 VAR BYTE[30]
    'BV46 VAR BYTE[30]
    'BV47 VAR BYTE[30]
    'BV48 VAR BYTE[30]
    'BV49 VAR BYTE[30]
    'BV50 VAR BYTE[30]
    
    Mode VAR BYTE
    Mode = 0
    
    BV1[0] = 0
    BV2[0] = 0
    BV3[0] = 0
    BV4[0] = 0
    BV5[0] = 0
    BV6[0] = 0
    BV7[0] = 0
    BV8[0] = 0
    BV9[0] = 0
    BV10[0] = 0
    
    Gosub initcheck
    
    'DEFINE  USE_LOWPRIORITY  0
    INCLUDE "DT_INTS-14.bas"       ; Base Interrupt System
    INCLUDE "ReEnterPBP.bas"    ; Include if using PBP interrupts
    'INCLUDE "ReEnterPBP-18LP.bas"  ; Include if using Low Pr. PBP INTS
    
    ;----[High Priority Interrupts]-----------------------------------------------
    ASM
    INT_LIST  macro    ; IntSource,        Label,       Type, ResetFlag?
            INT_Handler   TMR0_INT,      _SOFTPWM,       PBP,    yes
    ;        INT_Handler    SSP_INT,     _I2C-handler    PBP,    yes
            INT_Handler    RX_INT,       _RX1_INT,       PBP,    yes
    ;        INT_Handler    TMR1_INT,     _KEYPAD_HANDLER        PBP,    yes
        endm
    
        INT_CREATE                  ; Creates the High Priority interrupt processor
    ENDASM
    @    INT_ENABLE  TMR0_INT        ; Enable Timer 0 Interrupts  
    ;    INT_ENABLE  SSP_INT         ; Enables MSSP interupts
    @    INT_ENABLE  RX_INT          ; Enables UART Recieve interupts
    ;    INT_ENABLE  TMR1_INT        ; Enable Timer 1 Interrupts  
    
    'Set-up MSSP
    'SSPSTAT.7 = 1                                   ' Slew enabled for 400KHz
    'SSPSTAT.6 = 0                                   ' Disable SMBus inputs
    'SSPCON1.3 = 
    'SSPCON1.2 = 
    'SSPCON1.1 = 
    'SSPCON1.0 = 
    'SSPCON1.5 - 1                                   ' Enabled MSSP
    
    ' Setup interupt timers
    ' TMR0 - PWM
    TMR0 = 0
    'TMR0L = 0                                       ' Reset TMR0 counter Low byte
    'TMR0H = 0                                       ' Reset TMR0 counter High byte
    'T0CON.6 = 1                                     ' TMR0 as 8bit
    'T0CON.5 = 0                                     ' FOSC/4 clock source
    'T0CON.4 = 1                                     ' High to low
    'T0CON.3 = 1                                     ' Prescaler not asigned
    'T0CON.2 = 0                                     ' NA 'Select 1:16 prescale
    'T0CON.1 = 0                                     ' NA 'Select 1:16 prescale
    'T0CON.0 = 0                                     ' NA 'Select 1:16 prescale
    'T0CON.7 = 1                                     ' TMR0 on
    
    ' TMR1 - keypad
    'T1CON.7 = 1
    'T1CON.6 = 0
    'T1CON.5 = 1
    'T1CON.4 = 1
    'T1CON.3 = 0
    'T1CON.1 = 0
    'T1CON.0 = 1
    goto loop
    
    loop:
    TOGGLE PORTD.0
    Pause 100
    goto loop
    
    SOFTPWM:
    IF Mode > 0 then 
        goto SOFTPWMAUTO
        ELSE
        GOTO SOFTPWMMAN
        ENDIF
    
    @ INT_RETURN
    RETURN
    
    SOFTPWMAUTO:
    if bitcounter < BV1[PROGCOUNTER] then
        HIGH C1B1 
        ELSE
        LOW C1B1   
        ENDIF
    
    if bitcounter < BV2[PROGCOUNTER] then
        HIGH C1B2 
        ELSE
        LOW C1B2   
        ENDIF
    
    if bitcounter < BV3[PROGCOUNTER] then
        HIGH C1B3 
        ELSE
        LOW C1B3   
        ENDIF
    
    if bitcounter < BV4[PROGCOUNTER] then
        HIGH C1B4 
        ELSE
        LOW C1B4   
        ENDIF
    
    if bitcounter < BV5[PROGCOUNTER] then
        HIGH C1B5 
        ELSE
        LOW C1B5   
        ENDIF
    
    if bitcounter < BV6[PROGCOUNTER] then
        HIGH C2B1 
        ELSE
        LOW C2B1   
        ENDIF
    
    if bitcounter < BV7[PROGCOUNTER] then
        HIGH C2B2 
        ELSE
        LOW C2B2   
        ENDIF
    
    if bitcounter < BV8[PROGCOUNTER] then
        HIGH C2B3 
        ELSE
        LOW C2B3   
        ENDIF
    
    if bitcounter < BV9[PROGCOUNTER] then
        HIGH C2B4 
        ELSE
        LOW C2B4   
        ENDIF
    
    if bitcounter < BV10[PROGCOUNTER] then
        HIGH C2B5 
        ELSE
        LOW C2B5   
        ENDIF
    
    IF BITCOUNTER = 255 then
        BITCOUNTER = 1
        PROGCOUNTER = PROGCOUNTER + 1
        ELSE
        BITCOUNTER = BITCOUNTER + 1
        ENDIF
    Return
    
    SOFTPWMMAN:
    if bitcounter < BV1 then
        HIGH C1B1 
        ELSE
        LOW C1B1   
        ENDIF
    
    if bitcounter < BV2 then
        HIGH C1B2 
        ELSE
        LOW C1B2   
        ENDIF
    
    if bitcounter < BV3 then
        HIGH C1B3 
        ELSE
        LOW C1B3   
        ENDIF
    
    if bitcounter < BV4 then
        HIGH C1B4 
        ELSE
        LOW C1B4   
        ENDIF
    
    if bitcounter < BV5 then
        HIGH C1B5 
        ELSE
        LOW C1B5   
        ENDIF
    
    if bitcounter < BV6 then
        HIGH C2B1 
        ELSE
        LOW C2B1   
        ENDIF
    
    if bitcounter < BV7 then
        HIGH C2B2 
        ELSE
        LOW C2B2   
        ENDIF
    
    if bitcounter < BV8 then
        HIGH C2B3 
        ELSE
        LOW C2B3   
        ENDIF
    
    if bitcounter < BV9 then
        HIGH C2B4 
        ELSE
        LOW C2B4   
        ENDIF
    
    if bitcounter < BV10 then
        HIGH C2B5 
        ELSE
        LOW C2B5   
        ENDIF
    
    IF BITCOUNTER = 255 then
        BITCOUNTER = 1
        ELSE
        BITCOUNTER = BITCOUNTER + 1
        ENDIF
    RETURN
    
    RX1_INT:
    RXBUFFER(RXcounter) = RCREG
    HSEROUT [DEC RXBUFFER(RXcounter),10,13]                  ' test
    IF RXBUFFER(RXcounter) = 255 and RXcounter = 11 then
        BV1 = RXBUFFER[1]
        BV2 = RXBUFFER[2]
        BV3 = RXBUFFER[3]
        BV4 = RXBUFFER[4]
        BV5 = RXBUFFER[5]
        BV6 = RXBUFFER[6]
        BV7 = RXBUFFER[7]
        BV8 = RXBUFFER[8]
        BV9 = RXBUFFER[9]
        BV10 = RXBUFFER[10] 
        RXcounter = 0
        ENDIF
    
    IF RXBUFFER(RXcounter) = 255 and RXcounter <> 11 THEN
        toggle PORTB.7
        HSEROUT ["RX ERROR",10,13]
        RXcounter = 0
        ENDIF
    
    IF RXcounter = 12 then  
        toggle PORTB.7
        RXcounter = 0
        ENDIF
        
    RXcounter = RXcounter + 1
    @ INT_RETURN
    
    'KEYPAD_HANDLER:
    'If KEYPAD = 0 then
    '@ INT_RETURN
    '    ENDIF
    
    'IF KEYPAD = 1 then                  ;RED +
    '    If zone = 1 then
    '    BV1 = BV1 + 1
    '    ENDIF
    '    IF zone = 2 THEN
    '    BV6 = BV6 + 1    
    '    endif
    'endif
    
    @ INT_RETURN
    
    initcheck:
    HSEROUT ["Initialising2",10,13]
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    toggle PORTB.7
    Pause 200
    Low PORTB.7
    HSEROUT ["Initialised",10,13]
    return
    Any help appreciated...

  2. #2


    Did you find this post helpful? Yes | No

    Default

    i've just spotted a var error in softpwman routine...
    I'll correct it now and post back...

    :edit
    Nope, still does it
    Last edited by comwarrior; - 27th June 2010 at 21:05.

  3. #3


    Did you find this post helpful? Yes | No

    Default

    right, i changed the PWM to use TMR2 and it still locks up...
    The only thing i can think of now is to start disabling some of the routines to isolate the problem...

    Can no one shed any light on this?

  4. #4
    Join Date
    Apr 2007
    Posts
    34


    Did you find this post helpful? Yes | No

    Default

    just a quick glance -

    Code:
    SOFTPWM:
    IF Mode > 0 then 
        goto SOFTPWMAUTO
        ELSE
        GOTO SOFTPWMMAN
        ENDIF
    
    @ INT_RETURN
    RETURN
    shouldn't that be gosub softpwm... because otherwise it will not come back and process the @ INT_RETURN?

    just a guess

  5. #5


    Did you find this post helpful? Yes | No

    Default

    Call me a Muppet and stripe me pink!

    I could have sworn they were gosubs! Honestly... i seen gosubs...
    Well spotted!

    I'll re-program in the morning...

  6. #6


    Did you find this post helpful? Yes | No

    Default

    ok... getting annoyed!
    Changed the goto's to gosubs... same fault...
    Disabled BOTH interupts so that all it has to do is flash an LED using pauses... same fault...
    I've disabled the watchdog, power on timer, brownout reset and LVP and it still does it...

    i'm seriously lost now... Help needed

  7. #7


    Did you find this post helpful? Yes | No

    Default

    Just for the hell of it... I tried another PIC same model and it does it on that too...

    Any help is VERY appreciated

  8. #8


    Did you find this post helpful? Yes | No

    Angry

    You are not going to believe this!

    i tried a test program, disabled analog, turns all ports to output, sets all ports to low and then enters the same loop to toggle the LED... SIMPLE!
    It failed and locked up...

    so i asked myself, what is the diference between the 3mm red LED on PORTB.7 and the one on PORTD.0? so i switched them over... same result...

    Just for the hell of it, i switched the resisters over and tried it... and it works!
    I switched the resisters back and it locks up...

    I took the suspect resister out and stuck it on my multimeter... it read less than 1ohm!
    The resisters are supposed to be 68 ohms... this one is a faulty one...

    So, the problem must have been caused by too much current through one of the IO lines...
    I have lost 4 days trying to debug a problem caused by a 5 pence component that i would have never suspected if i was anywhere near sane!

    So now i'm going to re-enable all my code and try it... god darn it!

  9. #9
    Join Date
    Apr 2007
    Posts
    34


    Did you find this post helpful? Yes | No

    Default

    Haha good to hear you found a problem!
    I know that feeling too well, you're not alone!

  10. #10


    Did you find this post helpful? Yes | No

    Default

    it's absolutely ridiculous though!
    I would have expected a supply of 5V to kill a 3.3V 3mm red led...
    but no, the PIC just had to be clever...
    Anyways, it's bed time...

  11. #11
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by masosi View Post
    just a quick glance -

    Code:
    SOFTPWM:
    IF Mode > 0 then 
        goto SOFTPWMAUTO
        ELSE
        GOTO SOFTPWMMAN
        ENDIF
    
    @ INT_RETURN
    RETURN
    shouldn't that be gosub softpwm... because otherwise it will not come back and process the @ INT_RETURN?

    just a guess
    Except, we are not supposed to gosub outside of our interrupt handlers.
    See: http://www.picbasic.co.uk/forum/show...3788#post83788

    Does it work for you, or is it acting funny?

  12. #12
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    Well, that's true if you jump out of the ISR never to RETURN to it. You can definetely GOSUB "out of" the ISR as long as you don't "wander off" and doesn't RETURN to within the ISR to finally end up at the INT_RETURN.
    Code:
    myINT:
      GOSUB mySUB1
      GOSUB mySUB2
      TOGGLE PortB.0
    @ INT_RETURN
    The above will work just fine as long as mySUB1 and mySUB2 RETURN to within the ISR.

  13. #13
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    With 18F's or 16F1's, you can get away with GOSUBing to other routines from the interrupt handler.

    But with 12F's and 16F's, you are limited by a very small Stack (8 levels).
    Most PBP statements only use 1 or 2, but a couple of them can use up to 4 levels, which only leaves 4 levels for your program and it's GOSUB's.

    When you get an interrupt, the hardware itself uses 1 level.
    When the interrupt happens, it could be 2 or 3 gosubs deep already in your main program.
    Then using Basic Language statements in the interrupt handler will want some more levels.

    If you use another level by gosubing from the handler, then you are really pushing your luck.
    It may work fine for some programs, but it could be catastrophic for others.

    With 18F's and 16F1's, there are plenty of stack levels to go around. But not with the "little" guys.
    DT

  14. #14


    Did you find this post helpful? Yes | No

    Default

    So far, she does run... however, i'm having a right mare with the comms hardware setup and the comms handler...(shakes head)
    Now that i have 6 18F4550's from crownhill i may revert the program back to using them...
    The program does sweet FA, everything is driven from interrupts, their is only the 'automatic' and 'manual' modes that have gosubs and they are correctly returned so i don't think it's over/under runs that are the problem now...

    I'll post more info later on, I'm going to take a break for a couple of hours and have a blast on CnC...

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts