Continue to Site

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.

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

Add GPS/PARSE to 8xSERVO-MOTOR CODE in Oshonsoft

It likely won't since the entire uart receive code is already surrounded by a check for RCIE=1:
Code:
'OVERRUN ERROR
If PIE1.RCIE = 1 Then  'EUSART Receive Interrupt Enable bit
    If RCSTA.OERR = 1 Then
        Gosub irqinitbuf  're-init buffer, discard bad sentence
        Goto RXIRQdone  'done, wait for next character
    Endif  'OERR

    'FRAMING ERROR
    If RCSTA.FERR = 1 Then
        dumpchar = RCREG  'Read char to clear RCIF and FERR
        Gosub irqinitbuf  'Re-init buffer, discard bad sentence
        Goto RXIRQdone  'wait for next
    Endif  'FERR

    'No UART errors, process character
    If PIR1.RCIF = 1 Then
Just checking for RCIF should be ok here since you've already checked for RCIE

Now, for the OERR handling... if OERR=1 then you have to clear it by either
clearing the CREN bit or by resetting the EUSART by clearing the SPEN bit.

The irqinitbuf code in post #295 does this... prior versions didn't.
Hi T and M,
Thanks, I'll use the #295 irqinitbuf
With the SEROUT commented out, the CODE is running much better.
I'll have to figure the best way of 'seeing' what's going on.
C
 
Hi M,
I'm trying to figure out how to send the SERVO Channels with individual numbers, instead of the #260 sweeping each channel.

I notice OSCCON = %01110000 '& h70.
The PIC has an 8mHz Crystal with 4xPLL, can I remove the OSCCON?
Is the timing the same?

EDIT: No reply! I'm a bit stuck with the calculations of the clock being 8mHz x4 (PLL). I'll ask on AAC.
C
 
Last edited:
Hi,
Here's my attempt at getting OSC changed from 8mHz to 32mHz.

It doesn't work?
C
Code:
'18F4431 32MHz PCB9 REMOTE_SLAVE SERVO 030324 0900

Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz XTL x4 =32mHz
Define CONFIG2L = 0x0c
Define CONFIG2H = 0x20
Define CONFIG3L = 0x04
Define CONFIG3H = 0x80
Define CONFIG4L = 0x80  'Set for HVP
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 20

'Define SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

Dim wordTemp As Word
Dim CHAN_Count As Byte
Dim i As Word
Dim Servo_CHAN(8) As Word
Dim servoDir(8) As Byte
Dim frame As Long 'Word
Dim rec As Byte
Dim pos As Word
Dim dir As Byte

Symbol rled = PORTD.7

'OSCCON = %01110000  '& h70 Using 8mHz XTL X4PLL
TRISA = %11000000  '7=OSC, 6=OSC,
TRISB = %00000000  '0=SEROUT
TRISC = %11110010  '6=1-slave4431_cs, 3=74HC164 MR, 2=74HC164 CLK, 0=74HC164 DATA'<<<<<<<<<<<<
TRISD = %00000000
LATC.0 = 0  'ensure data is low
LATC.2 = 0  'and clock
LATC.3 = 1  'Master reset HIGH for run.'<<<<<<<<<<<<<<

For i = 0 To 7
LATC.2 = 1  'send positive clock edge
'Servo_CHAN(i) = i * 250 + 2000  '250=1/8th-1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
Servo_CHAN(i) = i * 1000 + 8000  '250=1/8th-1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
LATC.2 = 0  'send negative edge
servoDir(i) = i And 1  '<<<<<<<added
Next i

'Start up led
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000

'TRISC = %11111010  'CCP0 (RC2) & RC0 output'<<<<<<<<<<<<<<<<<<<<
CHAN_Count = 8  'cause it to reset
T1CON = %00100000  '=All values are divided by PRESCALE=4.
T1CON.0 = 1  '&00000001=EN start timer
CCP1CON = %1000  'will go high on interrupt - will start a 0.5mS pulse
'frame = 1000  'start everything in 4000 cycles
frame = 4000  'start everything in 16000 cycles
PIR1.RCIF = 0  'RCIF: EUSART Receive Interrupt Flag bit
PIE1.RCIE = 1  'EUSART Receive Interrupt Enable bit
PIE1.CCP1IE = 1  'CCP1IE: CCP1 Interrupt Enable bit
INTCON.PEIE = 1  'PEIE/GIEL: Peripheral Interrupt Enable bit
INTCON.GIE = 1  'GIE/GIEH: Global Interrupt Enable bit

While 1  '\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

    While CHAN_Count = 0  'wait for 20mS to pass (=1/50th of a second)
    Wend
    While CHAN_Count <> 0
    Wend
    For i = 0 To 7
        dir = servoDir(i)  'doesn't matter if ISR happens as servo_CHAN isn't changed by ISR
        pos = Servo_CHAN(i)
        If dir = 1 Then
            pos = pos + 160 '40  'add 1/50th to the servo position
        Else
            pos = pos - 160 '40  'subtract it
        Endif
        'If pos < 2000 Then  'have we gone past the end?
            'pos = 2000  'yes so make it the end stop
        If pos < 8000 Then  'have we gone past the end?
            pos = 8000  'yes so make it the end stop
            dir = 1  'and turn it around
        Endif
        'If pos > 4000 Then  'same for other end
            'pos = 4000
        If pos > 16000 Then  'same for other end
            pos = 16000
            dir = 0
        Endif
        INTCON.GIE = 0
        Servo_CHAN(i) = pos
        INTCON.GIE = 1
        servoDir(i) = dir  'servoDir not used by ISR
    Next i

Wend

End

On High Interrupt  'go via location 0x0008
Save System

If PIR1.CCP1IF Then  'has CCP1 triggered?
    wordTemp.HB = CCPR1H  'get value of CCPR1 into wordTemp
    wordTemp.LB = CCPR1L
    If CCP1CON = 0x08 Then  'have we started the 1000 cycle pulse
        CCP1CON = 0x09  'yes so end the pulse after 0.5mS
        'wordTemp = wordTemp + 4000  'adding 4000 will make pulse 0.5mS long
        wordTemp = wordTemp + 16000  'adding 16000 will make pulse 0.5mS long
    Else
        LATC.0 = 0  'clear the data pin
        CCP1CON = 0x08  'No so output the timed gap
        If CHAN_Count < 8 Then
            'still doing the servos so add remainder of time
            wordTemp = wordTemp + Servo_CHAN(CHAN_Count)
            'wordTemp = wordTemp - 4000  'knock of the 4000 (0.5mS) already elapsed
            wordTemp = wordTemp - 16000  'knock of the 16000 (0.5mS) already elapsed
            frame = frame - Servo_CHAN(CHAN_Count)
            CHAN_Count = CHAN_Count + 1
        Else
            'done all the servos so just the frame gap to do
            wordTemp = wordTemp + frame
            'frame = 39000  '40,000(20mS) minus time of positive pulse(0.5mS)
            frame = 165000  '160,000(20mS) minus time of positive pulse(0.5mS)
            CHAN_Count = 0  'start all over again
            LATC.0 = 1  'will become first pulse (is data pin of shift register)
        Endif
    Endif
        CCPR1H = wordTemp.HB  'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0  'clear interrupt flag
Endif

Resume
 
Are you sure the original was using an 8MHz clock and not 32MHz?
The various constants and comments in the original imply it's counting at a 500ns rate (2MHz), and you get that with a 32MHz clock and a TMR1 prescaler of 1:4

The CONFIG setting shown:
Code:
Define CONFIG1H = 0x06  '8MHz XTL x4 HSPLL =32MHz
will get you HS oscillator, PLL enabled as the primary oscillator

Any OSCCON setting in the code may not matter if the lower two SCS1:SCS0 bits are '00', which specifies "use the primary oscillator setting", which comes from the CONFIG1H setting. You would have to have the CONFIG1H set for one of the INTOSC settings or SCS1:SCS0 = 1x to select the internal osc block for the IRCF[2:0] Internal Oscillator Frequency Select bits to matter
 
Are you sure the original was using an 8MHz clock and not 32MHz?
The various constants and comments in the original imply it's counting at a 500ns rate (2MHz), and you get that with a 32MHz clock and a TMR1 prescaler of 1:4

The CONFIG setting shown:
Code:
Define CONFIG1H = 0x06  '8MHz XTL x4 HSPLL =32MHz
will get you HS oscillator, PLL enabled as the primary oscillator

Any OSCCON setting in the code may not matter if the lower two SCS1:SCS0 bits are '00', which specifies "use the primary oscillator setting", which comes from the CONFIG1H setting. You would have to have the CONFIG1H set for one of the INTOSC settings or SCS1:SCS0 = 1x to select the internal osc block for the IRCF[2:0] Internal Oscillator Frequency Select bits to matter
Hi T,
The original, used OSCCON set to internal 8mHz, which I added into my program, which is set to an external 8mHz XTL with 4XPLL 32mHz.

The timings in the original are for 8mHz, and if I'm correct the timings will be affected by the change. I've tried changing the timings, but so far haven't got any sense out of it..
C
 
What I'm saying is that if OSCCON ends in '00' then it doesn't change the osc setting set by the CONFIG1H word, so just because there's an 'OSCCON= xxxx' statement in the code doesn't mean anything.

The comments like this:
Code:
ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
lead me to believe that's it's already set for 32MHz... 2000 counts of 500ns = 1ms, and you get 500ns counts with 32MHz and a 1:4 prescaler.

Is there a copy of the "original code" here somewhere?
 
What I'm saying is that if OSCCON ends in '00' then it doesn't change the osc setting set by the CONFIG1H word, so just because there's an 'OSCCON= xxxx' statement in the code doesn't mean anything.

The comments like this:
Code:
ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
lead me to believe that's it's already set for 32MHz... 2000 counts of 500ns = 1ms, and you get 500ns counts with 32MHz and a 1:4 prescaler.

Is there a copy of the "original code" here somewhere?
Hi T,
I think this is the original?
It runs fine and moves the SERVOs.
Note there is the CONFIG and clock settings, then OSCCON. I thought that the OSCCON changed the timing from the CONFIG, so I commented it out before trying my 32mHz numbers.

The stalling problem, may be a conflict with CCP1. When this happened before many years ago, may also be the same, as I was working on a tracker which also used CCP.
C.

Code:
'18F4431 32MHz XTL PCB9 REMOTE_SLAVE GPS_SERVO 070224 1600

Define CONFIG1L = 0x00
Define CONFIG1H = 0x06  '8mHz XTL x4 =32mHz
Define CONFIG2L = 0x0c
Define CONFIG2H = 0x20
Define CONFIG3L = 0x04
Define CONFIG3H = 0x80
Define CONFIG4L = 0x80  'Set for HVP
Define CONFIG4H = 0x00
Define CONFIG5L = 0x0f
Define CONFIG5H = 0xc0
Define CONFIG6L = 0x0f
Define CONFIG6H = 0xe0
Define CONFIG7L = 0x0f
Define CONFIG7H = 0x40

Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 20

Define SIMULATION_WAITMS_VALUE = 1  'Comment in for SIM out for PIC

Dim wordTemp As Word
Dim ServoCount As Byte
Dim i As Word
Dim ServoPos(8) As Word
Dim servoDir(8) As Byte
Dim frame As Word
Dim gpsbuf(80) As Byte
Dim strCount As Byte
Dim rec As Byte
Dim isDone As Bit

Dim pos As Word
Dim dir As Byte

Symbol rled = PORTD.7

OSCCON = %01110000  '& h70
TRISA = %11000000  '7=OSC, 6=OSC,
TRISB = %00000000  '0=SEROUT
TRISC = %11110010  '6=1-slave4431_cs, 3=74HC164 MR, 2=74HC164 CLK, 0=74HC164 DATA'<<<<<<<<<<<<
TRISD = %00000000
LATC.0 = 0  'ensure data is low
LATC.2 = 0  'and clock
LATC.3 = 1  'Master reset HIGH for run.'<<<<<<<<<<<<<<

For i = 0 To 7
LATC.2 = 1  'send positive clock edge
ServoPos(i) = i * 250 + 2000  '1ms(2000) to 1.875(1 7/8ths - 3750)ms in 1/8th mS steps
LATC.2 = 0  'send negative edge
servoDir(i) = i And 1  '<<<<<<<added
Next i

'Start up led
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000

'TRISC = %11111010  'CCP0 (RC2) & RC0 output'<<<<<<<<<<<<<<<<<<<<
ServoCount = 8  'cause it to reset
T1CON = %00100000  'prescaler = 4
T1CON.0 = 1  'start timer
CCP1CON = %1000  'will go high on interrupt - will start a 0.5mS pulse
frame = 1000  'start everything in 4000 cycles
strCount = 0
isDone = 0
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
PIR1.RCIF = 0
PIE1.RCIE = 1
PIE1.CCP1IE = 1
INTCON.PEIE = 1
INTCON.GIE = 1

While 1  '\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

    While ServoCount = 0  'wait for 20mS to pass (=1/50th of a second)
    Wend
    While ServoCount <> 0
    Wend
    For i = 0 To 7
        dir = servoDir(i)  'doesn't matter if ISR happens as servoPos isn't changed by ISR
        pos = ServoPos(i)
        If dir = 1 Then
            pos = pos + 40  'add 1/50th to the servo position
        Else
            pos = pos - 40  'subtract it
        Endif
        If pos < 2000 Then  'have we gone past the end?
            pos = 2000  'yes so make it the end stop
            dir = 1  'and turn it around
        Endif
        If pos > 4000 Then  'same for other end
            pos = 4000
            dir = 0
        Endif
        INTCON.GIE = 0
        ServoPos(i) = pos
        INTCON.GIE = 1
        servoDir(i) = dir  'servoDir not used by ISR
    Next i

        'Serout PORTB.0, 9600, "$ R W ", gpsbuf(0), gpsbuf(3), gpsbuf(44), CrLf

Wend

End

On High Interrupt  'go via location 0x0008
Save System

If PIR1.CCP1IF Then  'has CCP1 triggered?
    wordTemp.HB = CCPR1H  'get value of CCPR1 into wordTemp
    wordTemp.LB = CCPR1L
    If CCP1CON = 0x08 Then  'have we started the 1000 cycle pulse
        CCP1CON = 0x09  'yes so end the pulse after 0.5mS
        wordTemp = wordTemp + 1000  'adding 1000 will make pulse 0.5mS long
    Else
        LATC.0 = 0  'clear the data pin
        CCP1CON = 0x08  'No so output the timed gap
        If ServoCount < 8 Then
            'still doing the servos so add remainder of time
            wordTemp = wordTemp + ServoPos(ServoCount)
            wordTemp = wordTemp - 1000  'knock of the 1000 (0.5mS) already elapsed
            frame = frame - ServoPos(ServoCount)
            ServoCount = ServoCount + 1
        Else
            'done all the servos so just the frame gap to do
            wordTemp = wordTemp + frame
            frame = 39000  '40,000(20mS) minus time of positive pulse(0.5mS)
            ServoCount = 0  'start all over again
            LATC.0 = 1  'will become first pulse (is data pin of shift register)
        Endif
    Endif
        CCPR1H = wordTemp.HB  'put value back into CCPR1
        CCPR1L = wordTemp.LB
        PIR1.CCP1IF = 0  'clear interrupt flag
Endif

If PIR1.RCIF Then
    rec = RCREG  'get the received character
    If RCSTA.OERR Or RCSTA.FERR Then  'neither of these should ever occur.
            RCSTA.CREN = 0  'this is kinda wishful thinking
        If PIR1.RCIF Then
            rec = RCREG
        Endif
        RCSTA.CREN = 1  'as any data received is corrupt
        strCount = 0  'however, reset everything
        isDone = 0  'and hope for the best
    Else  'no errors so use the data
        If strCount = 0 And isDone = 0 Then  'are we already receiving
                'waiting for $           'no so wait
            If rec = "$" Then  'for $ to appear'<<<<<<<<<<<<<<<<<<<<<<<<
                gpsbuf(strCount) = rec  'start receiving
                strCount = strCount + 1
            Endif
        Else
            If isDone = 0 And strCount < 79 Then  'have we collected a full string?
                gpsbuf(strCount) = rec  'no so carry on storing
                strCount = strCount + 1
                If rec = "W" Then  'have we got the "endOfString" character'<<<<<<<<<<<<
                    isDone = 1  'yes, so set done true
                    'put break here
                Endif
            Else
                If isDone = 0 Then  '?????????<<<<<<<<<<<<<<<<<<<<<<<
                    'still waiting to start or buffer overflow
                    strCount = 0
                Endif
            Endif
        Endif  '<<<<<<<<<<<<<<<
    Endif
Endif  'end RS232 if
Resume
 
Last edited:
The OSCCON register allows you to select between different clock sources, depending on the lower two bits SCS1:SCS0...
00 = primary osc (the one set by CONFIG1H)
01 = secondary osc (TIMER1)
1x = internal osc

The code in #304 sets OSCCON = %01110000 (0x70), so the lower two bits tell it to use the primary CONFIG1H osc setting, which in this case is Define CONFIG1H = 0x06 '8mHz XTL x4 =32MHz. The comment is correct for that...
0110= HS oscillator, PLL enabled (clock frequency = 4 x FOSC1)

As long as you have an 8MHz xtal you should already be running at 32MHz with those settings.
All of the existing TMR/CCP settings in that code seem to match with that.

The only thing that doesn't is the UART setting, which is shown as:
Code:
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207

At 32MHz those register settings will get you a baud rate of 38400, not 9600 as the comment claims.
If you want 9600 baud then change the line to TXSTA.BRGH = 0

If you comment out the 'OSCCON = %01110000' in the above code nothing should change.
You shouldn't need to change anything.



 
The OSCCON register allows you to select between different clock sources, depending on the lower two bits SCS1:SCS0...
00 = primary osc (the one set by CONFIG1H)
01 = secondary osc (TIMER1)
1x = internal osc

The code in #304 sets OSCCON = %01110000 (0x70), so the lower two bits tell it to use the primary CONFIG1H osc setting, which in this case is Define CONFIG1H = 0x06 '8mHz XTL x4 =32MHz. The comment is correct for that...
0110= HS oscillator, PLL enabled (clock frequency = 4 x FOSC1)

As long as you have an 8MHz xtal you should already be running at 32MHz with those settings.
All of the existing TMR/CCP settings in that code seem to match with that.

The only thing that doesn't is the UART setting, which is shown as:
Code:
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207

At 32MHz those register settings will get you a baud rate of 38400, not 9600 as the comment claims.
If you want 9600 baud then change the line to TXSTA.BRGH = 0

If you comment out the 'OSCCON = %01110000' in the above code nothing should change.
You shouldn't need to change anything.
Hi T,
Thanks for your detailed reply. You've answered many questions here.

If commenting out OSCCON makes no difference, I'll remove it.

Is there any difference between this CODE:
-------------------------------------------------
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
-----------------------------------------------
and the Oshonsoft [ Hseropen 9600 ]?

Regarding 9600? This answers a question, where the GPS TX resets to 38400, which could be the GPS itself (default) or from the UART?

While replying to this message, I've been reading the D/S and being reminded that on this PIC, there is no TX.
The PIC has been suffering from stalling, and I have a post regarding this, but If I understand correctly, TXSTA should be set to '0'. I'll test this and report back.
C.
 
I don't use Oshonsoft, so take this fwiw...

Is there any difference between this CODE:
-------------------------------------------------
'setup USART for 9600 baud receive
RCSTA = %10010000
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
-----------------------------------------------
and the Oshonsoft [ Hseropen 9600 ]?

Probably. For one thing, as I mentioned, at 32MHz those code settings will get you 38400 baud, so it's probably more like "Hseropen 38400". Hseropen will likely enable the TX output as well.

but If I understand correctly, TXSTA should be set to '0'.
If you set TXSTA = 0 then that will reset the TXSTA.BRGH bit (which will change the baud rate to 9600), and also clear TXEN which will disable UART output.

If you don't need the UART TX, then set TXSTA = 0 right after setting RCSTA so that any other changes to TXSTA aren't effected. An Hseropen statement would likely override all those settings provided it was after the register setup and not before it.
 
Last edited:
I don't use Oshonsoft, so take this fwiw...



Probably. For one thing, as I mentioned, at 32MHz those code settings will get you 38400 baud, so it's probably more like "Hseropen 38400". Hseropen will likely enable the TX output as well.


If you set TXSTA = 0 then that will reset the TXSTA.BRGH bit (which will change the baud rate to 9600), and also clear TXEN which will disable UART output.

If you don't need the UART TX, then set TXSTA = 0 right after setting RCSTA so that any other changes to TXSTA aren't effected. An Hseropen statement would likely override all those settings provided it was after the register setup and not before it.
Hi T,
I tried the TXSTA.BRGH CODE section with TXSTA = 0 below TXSTA.BRGH = 1. This stalled.

I tired Hseropen 38400 with TXSTA = 0 below. This didn't stall.

This is in a skeleton program.
Next, to try it in a full program, where it reads the GPS, which is set to 38400, and see what happens.
Thanks.
C
 
There are at least four different combinations of BRGH, BRG16, and SPBRG/SPBRGH that get you 38400 baud at 32MHz:

BAUDCON.BRG16 = 0
TXSTA.BRGH = 0
SPBRG = 12

BAUDCON.BRG16 = 0
TXSTA.BRGH = 1
SPBRG = 51

BAUDCON.BRG16 = 1
TXSTA.BRGH = 0
SPBRGH = 0
SPBRG = 51

BAUDCON.BRG16 = 1
TXSTA.BRGH = 1
SPBRGH = 0
SPBRG = 207

I tried Hseropen 38400 with TXSTA = 0 below. This didn't stall
Setting TXSTA afterwards will reset any BRGH bit setting, so it might change the baud rate depending on the BRG16 setting as shown above.
If all you want to do is disable the TX then don't clear the whole register, just clear the TXEN bit:
Code:
Hseropen 38400
TXSTA.TXEN = 0        ' disable TX

or
Code:
'setup USART for 38400 baud receive only (disable TXEN)
RCSTA = %10010000
TXSTA = 0            ' TXEN=0, SYNC=0, BRGH=0
TXSTA.BRGH = 1
BAUDCON.BRG16 = 1
SPBRG = 207
 
Hi T,
As I added ENABLE HIGH, it stopped it stalled.
I think the problem could be around:
---------------------------------------------
When IPEN = 0:
1 = Enables all unmasked interrupts
0 = Disables all interrupts
When IPEN = 1:
1 = Enables all high-priority interrupts
0 = Disables all high-priority interrupts
-------------------------------------------
EDIT: Our messages #311 and 312 crossed at the same time!
C.
 
From what I see in the documentation they mention ENABLE HIGH and ENABLE LOW interrupt priorities,
so I would assume that means behind the scenes they use RCON IPEN=1 to enable interrupt priority.

In your code, right before the 'WHILE 1' loop you have:
Code:
INTCON.PEIE = 1
INTCON.GIE = 1

When you have IPEN=1 those two bits change function and are better thought of as:
Code:
INTCON.GIEL = 1
INTCON.GIEH = 1

So, you're enabling the low-priority intr but not specifying a vector. Not a good idea.
Also, just so you're aware, disabling the high-priority interrupt (INTCON.GIEH = 0) disables all interrupts.
In order to get a peripheral to use the low-priority vector you have to clear the proper IP bit in the IRPx register since they are all high-priority be default.

It may be better to stop messing with the INTCON bits and use ENABLE HIGH/DISABLE HIGH/ENABLE LOW/DISABLE LOW scheme.
 
From what I see in the documentation they mention ENABLE HIGH and ENABLE LOW interrupt priorities,
so I would assume that means behind the scenes they use RCON IPEN=1 to enable interrupt priority.

In your code, right before the 'WHILE 1' loop you have:
Code:
INTCON.PEIE = 1
INTCON.GIE = 1

When you have IPEN=1 those two bits change function and are better thought of as:
Code:
INTCON.GIEL = 1
INTCON.GIEH = 1

So, you're enabling the low-priority intr but not specifying a vector. Not a good idea.
Also, just so you're aware, disabling the high-priority interrupt (INTCON.GIEH = 0) disables all interrupts.
In order to get a peripheral to use the low-priority vector you have to clear the proper IP bit in the IRPx register since they are all high-priority be default.

It may be better to stop messing with the INTCON bits and use ENABLE HIGH/DISABLE HIGH/ENABLE LOW/DISABLE LOW scheme.
Hi T,
It's a bit complicated to follow!
I think I've followed what you suggest, but any time I add ENABLE HIGH it eventually stalls.

Note: Farther down the program, in part of the SERVO CODE there is INTCON.GIEH = 0/INTCON.GIEH = 1

It looks like I've got to divide the program down to only the posted SERVO CODE, and slowly build it back up to the full program, and see where it breaks.

I look in more detail tomporrow.
C.
 
Hi T,
I think I've found the culprit, which may be obvious really!
With ENABLE HIGH, and the GPS disconnected from the UART, it has now run for a while without stalling.

I may have found the culprit!
This PIC reads the GPS and transfers it to the MASTER PIC via SPI, which has WHILE/WAITs in it's CODE, I've commented out the SPI, and it's running= moving the SERVOs and showing the GPS DATA.
C
 
Last edited:
Note: Farther down the program, in part of the SERVO CODE there is INTCON.GIEH = 0/INTCON.GIEH = 1
If you're talking about this portion:
Code:
        INTCON.GIE = 0
        ServoPos(i) = pos
        INTCON.GIE = 1
That's there to disable interrupts around updating the ServoPos data array which is shared between the main program and the ISR. You could use DISABLE HIGH/ENABLE HIGH there, but it's ok the way it is.

This PIC reads the GPS and transfers it to the MASTER PIC via SPI, which has WHILE/WAITs in it's CODE,
If there's other code than what you've shown it's really hard to make any suggestions...
 

Latest threads

New Articles From Microcontroller Tips

Back
Top