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...