If RCSTA.OERR Or RCSTA.FERR Then 'neither of these should ever occur.
RCSTA.CREN = 0 'this is kinda wishful thinking
While PIR1.RCIF 'if any bytes in the buffer
rec = RCREG 'throw them away
Wend
RCSTA.CREN = 1 'as any data received is corrupt
RCSTA.CREN = 0
rec = RCREG 'throw them away
rec = RCREG 'throw them away
RCSTA.CREN = 1
Hi T,Code:If RCSTA.OERR Or RCSTA.FERR Then 'neither of these should ever occur. RCSTA.CREN = 0 'this is kinda wishful thinking While PIR1.RCIF 'if any bytes in the buffer rec = RCREG 'throw them away Wend RCSTA.CREN = 1 'as any data received is corrupt
Just fyi - a framing error (FERR) won't prevent the uart from getting more chars. It's set when a STOP bit wasn't detected at the right time, so it's usually a baud rate error. Nothing really needs to be done hardware-wise.
Overrun error (OERR) will completely block you out, so that one definitely has to be handled (you've lost chars). Usually it's good enough to just toggle CREN, but you might as well toss what's in the fifo too...
Code:RCSTA.CREN = 0 rec = RCREG 'throw them away rec = RCREG 'throw them away RCSTA.CREN = 1
Hi M,That's what happens when you don't have else if.
Mike.
Hi M,Sorry for going silent, PC problems which will hopefully be fixed next week.
Mike.
This posted from my tablet.
'18F4431 32MHz XTL PCB9 BASE_SLAVE NO-MATCH SERVO E 220224 1500
'array buf removed, losing 50 bytes of program memory from use
'parse routinr modified to cope with gps() which now integrates
'the gps parse routine into the main program rather than having it as a separate
'stand alone module
'????copy into the sspbuf array module removed as it is not needed anymore -?????
'I am in 2 minds about tidying up the serial print the diagnostic string data
'but have Not DONE anything with it yet
'TRIS direction information
Define CONFIG1L = 0x00
Define CONFIG1H = 0x06 '8mHz x4 =32
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
'OSH config
Define CLOCK_FREQUENCY = 32
Define SINGLE_DECIMAL_PLACES = 2
Define STRING_MAX_LENGTH = 45 '20 too short@
Define SEROUT_DELAYUS = 1000
'**********************************************************************
'* *
'* Register configuration *
'* *
'**********************************************************************
'------------- TARGET SETUP ------------------
Const PR2set = 125 'use this for the live board: gets 5ms per interrupt
'Const PR2set = 2 'use this for fast timing to speed up simulator
'Define SIMULATION_WAITMS_VALUE = 1 'Comment in for SIM out for PIC
ANSEL0 = %00000000
ANSEL1 = %00000000
Disable High 'Disable interrupts
Disable Low 'Disable interrupts
'**********************************************************************
'* *
'* IO Port configuration *
'* *
'**********************************************************************
'IN or OUT
Const TRISAinit = %11000000 '7=OSC, 6=OSC, 4=/ 3=/ 2=TEMP SEROUT
Const TRISBinit = %00000000
Const TRISCinit = %11110010 '7=1-RX, 6=1-slave4431_cs, 4-5=??, 3=74HC164 MR, 2=74HC164 CLK, 1=?, 0=74HC164
Const TRISDinit = %00100000 '6=led, 7=led, 5=synch, 2=MOSI
Const TRISEinit = %00000000 '2=TEST INDICATOR, 0= S2M_BUF_FULL
LATC.0 = 0 'ensure data is low
LATC.2 = 0 'and clock
LATC.3 = 1 'Master reset HIGH for run.'<<<<<<<<<<<<<<
TRISA = TRISAinit
TRISB = TRISBinit
TRISC = TRISCinit
TRISD = TRISDinit
TRISE = TRISEinit
'SET BITS ON/OFF before TRIS!
Const LATAinit = %00000000 'ON/OFF
Const LATBinit = %00000000
Const LATCinit = %00000000
Const LATDinit = %00000000
Const LATEinit = %00000000 'POSS MCLR RE3
'*******************************************************
'* *
'* GLOBAL VARIABLE DECLARATIONS *
'* *
'*******************************************************
'Comms
Const rxbufsize = 50 'keep this the same as the buffer size, check this.
Dim gnrmcpsn As Byte 'POSITION of character in UART RX buffer STRING.
Dim RXerr As Bit 'Errors in receiving $DATA
Dim RXIRQchar As Byte
Dim dumpchar As Byte 'For clearing Over run errors
Dim spipsn As Byte 'VARIABLE USED IN SSPBUF SEND/RECEIVE ROUTINE
Dim spichar As Byte
'SLAVE GPS
Dim strtim As String
Dim strlat As String
Dim strlong As String
'Dim qeideg As Word ' Byte
'QEI section remove@
'QEICON.VELM = 1 '1 = Velocity mode disabled
'QEICON.QEIM2 = 1 '110 = QEI enabled in 4x Update mode; position counter is reset on period match (POSCNT = MAXCNT)
'QEICON.QEIM1 = 1
'QEICON.QEIM0 = 0
'QEICON.PDEC1 = 1 '11=1:64 Velocity Pulse Reduction Ratio bits
'QEICON.PDEC1 = 1
'PIR3.IC2QEIF = 0 'Has reached the MAXCNT value, INT QEI MODULE Interrupt flag bit
'PIR3.IC3DRIF = 0 'clr in s/w REG file motion feedback filter
PIE1.RCIE = 0 '0= 'EUSART Receive Interrupt Enable bit
'CAP2BUFL = 0x00
'CAP2BUFH = 0x00
'CAP3BUFL = 0x9f 'CAP3BUFL = 0x67
'CAP3BUFH = 0x05 'CAP3BUFH = 0x01
''PIC18F4431
'FLAGS to indicate updated data
Symbol slave4431_cs = PORTC.6 'The port used as chip select
Dim gnrmc_buf_filling As Bit 'Message loading
Dim gnrmc_buf_full As Bit 'GPS-Buffer $ to W 1 = FULL 0 = Not FULL
'Dim gnrmc_buf_parsed As Bit 'parser found a GNRMC sentence and updated data
'gnrmc_buf_parsed = 0 'init new data flags (compiler may do this automatically)
'Dim s2m_buf_done As Bit 'S2M-buffer after PARSE
Symbol spi_pin_rdy = PORTE.0 'READY to send SPI DATA.
spi_pin_rdy = 0
Dim slave4431_cs_data As Bit 'The data state of the chip select line D added
Dim gnrmc_buf As String '(45) As String'Byte 'received message comes to buf'Check size (Only for GNRMC)
Dim s2m(34) As Byte '(34) As Byte 'Used to transfer data via SPI
'from the ssp buffer for receiving via the spi bus. The array has to be the same length as s2m buffer.
'onto the ssp buffer for transmitting via the spi bus. data includes the gps string,
'battery voltage and spare info.
Dim m2s(34) As Byte 'Used to transfer data to SLAVE via SPI
'********************* SERVO *******************************
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'SERVO'<<<<<<<<<<<<<<<<<
Dim dir As Byte
Dim batvolt As Byte 'TEST Battery voltage from BASE-SLAVE
Dim sparedata As Byte 'TEST Spare data from BASE-SLAVE.
Symbol yled = PORTD.6
Symbol rled = PORTD.7
'*******************************************************
'* *
'* End of variable declarations *
'* *
'*******************************************************
'*******************************************************
'* *
'* START UP CODE BEGINS HERE *
'* *
'*******************************************************
'START UP LEDS
rled = 1
WaitMs 1000
rled = 0
WaitMs 1000
yled = 1
WaitMs 1000
yled = 0
WaitMs 1000
'setup USART for 9600 baud receive
RCSTA = %10010000 '7=SPEN: Serial Port Enable bit, 6=RX9: 9-Bit Receive Enable bit, 5=SREN: Single Receive Enable bit, 4=CREN: Continuous Receive Enable bit
TXSTA.BRGH = 1 'BRGH: High Baud Rate Select bit
BAUDCON.BRG16 = 1 '16-Bit Baud Rate Register Enable bi
SPBRG = 207
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
Gosub irqinitbuf 'INIT RX'<<<<<<<<<<<<<<<¦
Serout PORTB.0, 9600, "RDY ", CrLf '"slave ready", CrLf 'USART?<<<<<<<<<<<<<<<<<<<<<<<<<<
'fire up the UART
Enable High 'enable the high interrupts
'INITIALIZE SPI
Call init_spi() 'initialise spi -here SSPEN=1 sets the pin directions for SPI
'ms20_reporttimer = 0 'force reports on entry to main loop
'++++++++++++++++++++++++++++++++++++++ SERVO ++++++++++++++++++++++++++++++++++++++++++++++++++
'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
'++++++++++++++++++++++++++++++++++++++++ SERVO END ++++++++++++++++++++++++++++++++++++++++++++++
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
'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
''*******************************************************
''* *
''* Main loop BEGINS *
''* *
''*******************************************************
'$GNRMC,111111.00,A,3723.02837,N,00150.39853,W,0.820,188.36,110706,,,A*74
'$GNRMC,000000.00,A,3723.02837,N,00150.00000,W,0.820,188.36,110706,,,A*74$GNRMC,111111.00,A,3723.02837,N,00150.11111,W,0.820,188.36,110706,,,A*74$GNRMC,222222.00,A,3723.02837,N,00150.22222,W,0.820,188.36,110706,,,A*74$GNRMX,333333.00,A,3723.02837,N,00150.33333,W,0.820,188.36,110706,,,A*74$GNRMC, 444444.00, A, 3723.02837, N, 00150.55555, W, 0.820, 188.36, 110706,,, A * 74$GNRMC, 555555.00, A, 3723.02837, N, 00150.39853, W, 0.820, 188.36, 110706,,, A * 74$GNRMC,666666.00,A,3723.02837,N,00150.66666,W,0.820,188.36,110706,,,A*74$GNRMX,777777.00,A,3723.02837,N,00150.77777,W,0.820,188.36,110706,,,A
main_loop: '/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
Toggle rled
'Toggle PORTE.0
'Serout PORTB.0, 9600, "TEST", CrLf '<<<<<<<<<<<<<<<<<
If gnrmc_buf_full = 1 Then
'Break '<<<<<<<<<<<
Gosub gnrmc_parse
'Update the transmit to master buffer with current data
batvolt = 12
sparedata = 123
Endif
If spi_pin_rdy = 1 Then 'Tell MASTER SPI ready.<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Serout PORTB.0, 9600, "SLAVE GNRMC PARSED ", s2m(0), s2m(1), s2m(2), s2m(3), s2m(4), s2m(5), s2m(6), s2m(7), s2m(8), s2m(9), s2m(10), s2m(11), s2m(12), s2m(13), s2m(14), s2m(15), s2m(16), s2m(17), s2m(18), s2m(19), s2m(20), s2m(21), s2m(22), s2m(23), s2m(24), s2m(25), s2m(26), s2m(27), s2m(28), s2m(29), s2m(30), s2m(31), #s2m(32), #s2m(33), CrLf
WaitMs 1 'Lower till not work
'Gosub irqinitbuf
Endif
'If gnrmc_buf_parsed = 0 Then 'parse tried but string was unknown, corrupt or wrong length
'Hserout "Parse fail ", CrLf
'Gosub IRQinitBuf '++++++¦
'endif
'Return
yled = 1
While slave4431_cs = 1 'If 1 then it waits till the CS makes it 0 then it LOOPs
For spipsn = 0 To 33 'GPS=0to29-$toW INC, QEI=30,31 BATVOLT=32 SPARE DATA=33 'QEI?@
SSPBUF = s2m(spipsn) 'Transfer S2M(spipsn) into SSPBUF
While SSPSTAT.BF = 0
Wend
m2s(spipsn) = SSPBUF 'Transfer M2S(spipsn) BYTE from SSPBUF into M2S(spipsn)
Next spipsn
spi_pin_rdy = 0
Wend
spipsn = 0
yled = 0
RCSTA.CREN = 1
PIE1.RCIE = 1
'Endif
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
'Wend
Goto main_loop
End
'*******************************************************
'* *
'* Functions BEGIN *
'* *
'*******************************************************
'---------------------- RX/TMR2 INTERRUPT SERVICE ----------------------
'Captures one sentence from '$' to 'W' in buf.
'Sentences must fit entirely in buf from $ to W
'Re-inits buf on any error and when any $ is received, even if in middle of sentence
'Stops UART and sets gps_buf_done when 'W' is received.
'Sentence in progress will be discarded, buffer reset and UART re-enabled when:
'Any UART error occurs
'A new '$' in the middle of a reception is found
'The buffer overflows before a 'W' is received. Non-fatal, it will just begin looking for the next
'sentence. err will be set when this happens so that main knows about it.
'Returns gps_buf_done=1 and buffer loaded with $,data,W on successful receipt of a complete sentence.
'Requires:
'rxBufSize defined as the size of buf in bytes. Declare the buffer like this:
'Const rxBufSize = 50
'Dim buf(50) As Byte 'Valid buf index range is 0 to rxBufSize-1. After $, index points to last character stored
'Expects:
'Call IRQinitBuf with PIE1.RCIE = 0 to set up for next sentence
'$GNRMC,111111.00,A,3723.02837,N,00159.39853,W,0.820,188.36,110706,,,A*74'For SIM
On High Interrupt
Save System
'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
RXIRQchar = RCREG 'read the received char, clears RCIF
'Look for $, start/restart filling buf when found
If RXIRQchar = "$" Then 'Start (re)filling buf on any $
Gosub irqinitbuf 'init buffer, index and flags@
gnrmc_buf(gnrmcpsn) = RXIRQchar 'store $ $ ADDED instead of RXIRQchar, because no $ was being stored
gnrmc_buf_filling = 1 'start storing the sentence
Goto RXIRQdone 'done with this character
Endif 'char was $
'no UART errors and character was not $
'If $ was found previously, process character looking for W and no buffer overflow.
'If haven't found $ yet, just ignore character.
If gnrmc_buf_filling = 1 Then 'if filling buffer, see if there is room in buf
'Break '<<<<<<<<<<<,
If gnrmcpsn >= (rxbufsize - 1) Then 'last char was at end of buf - buffer overflow so..
Gosub irqinitbuf 'restart buffer, discard sentence
RXerr = 1 'let main know that the buffer overflowed and is restarting
Goto RXIRQdone 'done, resume looking for next $
Endif 'buffer overflow
gnrmcpsn = gnrmcpsn + 1 'else, there's room in buf so bump index and store character, might be W
gnrmc_buf(gnrmcpsn) = RXIRQchar
If RXIRQchar = "W" Then 'if end of sentence..
RCSTA.CREN = 0 'shut down UART
PIE1.RCIE = 0 'Enable off
gnrmc_buf_filling = 0
gnrmc_buf_full = 1
Goto RXIRQdone 'and bye!
Endif 'RXIRQchar was W
Endif 'If gnrmc_buf_filling = 1
Endif 'RCIF=1
Endif 'RCIE=1
'Exit point for each RXinterrupt. Process timers
RXIRQdone:
'Resume
'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
Resume
'--------------- PARSE COMPLETE SENTENCE IN BUFFER -------------------------
'parse: extracts the main values from GPS,REMOTE and QEIDEG sentences in RXbuf 'QEI@
'into named value messages using the parse utilities above.
'Flags:
'returns prsed_gnrmc =1 if it found A good sentence
'if prsed_gnrmc =0, has bad sentence
'posted to respective string(s).?¦
'Expects: gnrmcpsn = index in buffer of the termininating 'W' char (one less than number of chars):
'Const ixGNRMC_W = 15 '$gnrmc,025,4,75,W
Const ixGNRMC_W = 44
gnrmc_parse:
'Break '<<<<<<<<<<<<<<<<<<<<<<<<<
gnrmc_buf_full = 0
'Dim tempIX As Byte 'used as index for building/adding to strings
'tempIX = 0 'string building begins at 0 for any
If gnrmcpsn <> ixGNRMC_W Then Goto gnrmc_buf_parsed '-->
'Endif
s2m(0) = "&" ' [TOT 34 BYTES ] $TEST¦
s2m(1) = gnrmc_buf(7) 'Time
s2m(2) = gnrmc_buf(8) 'Time
s2m(3) = gnrmc_buf(9) 'Time
s2m(4) = gnrmc_buf(10) 'Time
s2m(5) = gnrmc_buf(11) 'Time
s2m(6) = gnrmc_buf(12) 'Time
s2m(7) = gnrmc_buf(14) 'Time
s2m(8) = gnrmc_buf(15) 'Time
s2m(9) = gnrmc_buf(19) 'Lat
s2m(10) = gnrmc_buf(20) 'Lat
s2m(11) = gnrmc_buf(21) 'Lat
s2m(12) = gnrmc_buf(22) 'Lat
s2m(13) = gnrmc_buf(24) 'Lat
s2m(14) = gnrmc_buf(25) 'Lat
s2m(15) = gnrmc_buf(26) 'Lat
s2m(16) = gnrmc_buf(27) 'Lat
s2m(17) = gnrmc_buf(28) 'Lat
s2m(18) = gnrmc_buf(30) 'N
s2m(19) = gnrmc_buf(32) 'Lon
s2m(20) = gnrmc_buf(33) 'Lon
s2m(21) = gnrmc_buf(34) 'Lon
s2m(22) = gnrmc_buf(35) 'Lon
s2m(23) = gnrmc_buf(36) 'Lon
s2m(24) = gnrmc_buf(38) 'Lon
s2m(25) = gnrmc_buf(39) 'Lon
s2m(26) = gnrmc_buf(40) 'Lon
s2m(27) = gnrmc_buf(41) 'Lon
s2m(28) = gnrmc_buf(42) 'Lon
s2m(29) = gnrmc_buf(44) 'W
's2m(30) = POSCNTL 'QEIDEGLB
's2m(31) = POSCNTH 'QEIDEGHB
s2m(32) = batvolt 'Bat volt
s2m(33) = sparedata 'Spare DATA
gnrmc_buf_parsed: '<-- <--
spi_pin_rdy = 1 'S2M Buffer ready to SPI to MASTER
'Break '<<<<<<<<<<<< CS RC6 OFF
'ms20_gnrmcguard = gnrmcguardset '??????????
Return
'------------- UART SETUP UTILITIES -----------------
'Stops UART, selects channel indicated by datasw (0-2)
'Inits RX buffer then restarts UART and enables RX interrupt
'Expects:
'GIE is enabled
'port directions and basic TX/RX
''-------------------- INIT SENTENCE BUFFER ------------------
''Sets up index and flags for next sentence. Overwrites
''old buffer data
''May be used by main (non-interrupt code) when PIR1.RCIE = 0
irqinitbuf:
gnrmcpsn = 0 'init index
RXerr = 0 'no error
RCSTA.CREN = 1
dumpchar = RCREG '1 'clear UART RX registers
dumpchar = RCREG '2
PIE1.RCIE = 1
Return
'*******************************************************
'* *
'* START UP SPI ROUTINE *
'* *
'*******************************************************
Proc init_spi() 'PIC 18F4431
'4431
TRISC.6 = 1 '4431_CS=1
TRISD.3 = 1 'SCK from MASTER ******INPUT*****
TRISD.1 = 0 'MISO ****** OUTPUT *******
TRISD.2 = 1 'MOSI ****** INPUT *******
'MODE 0,0
SSPSTAT.SMP = 0 'Input data sampled at middle of data output time ** not about clock generation **
SSPSTAT.CKE = 0 '0 Output data changes on clock transition from active to idle ** AS ABOVE **
SSPSTAT.5 = 0 'I2C only
SSPSTAT.4 = 0 'I2C only
SSPSTAT.3 = 0 'I2C only
SSPSTAT.2 = 0 'I2C only
SSPSTAT.1 = 0 'I2C only
SSPCON = 0 'RESET THE CONTROL REGISTER
SSPCON.WCOL = 0 'Collision detect
SSPCON.SSPOV = 0 'Overflow
SSPCON.SSPEN = 1 'Configure SCK,SD0,SDI,/SS ** HAS TO BE 1. To reset or reconfigure SPI mode, clear the SSPEN bit,
'reinitialize the sspcon registers And Then set the SSPEN Bit from the datasheet !!!!!!!!!!!!!!!!
SSPCON.CKP = 1 '0 = Idle state for clock is a HIGH level
SSPCON.SSPM3 = 0 '0100 = SPI SLAVE mode, clock = FOSC/64
SSPCON.SSPM2 = 1
SSPCON.SSPM1 = 0 'SLAVE MODE
SSPCON.SSPM0 = 0
End Proc
Hi M,You try to stop receiving RS232 by disabling the interrupt but another thing may interrupt and cause it to read the char.
To prevent this change the line,
If PIR1.RCIF = 1 Then
to
If PIR1.RCIF = 1 AND PIE1.RCIE=1 Then
It would be better to turn of the RS232.
Mike.
It won't until PIE1.RCIE is set to zero which it is a little lower in the program.The 'If PIR1.RCIF = 1 AND PIE1.RCIE=1 Then' line didn't make any difference.
Hi M,It won't until PIE1.RCIE is set to zero which it is a little lower in the program.
However, you will still get overrun errors. Therefore it will be safer to disable the USART with RCSTA.SPEN=0.
Note, just checking the RCIF is dangerous if RCIE is set to zero.
Mike.
On High Interrupt
Save System
'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
RXIRQchar = RCREG 'read the received char, clears RCIF
'Look for $, start/restart filling buf when found
If RXIRQchar = "$" Then 'Start (re)filling buf on any $
Gosub irqinitbuf 'init buffer, index and flags@
gnrmc_buf(gnrmcpsn) = RXIRQchar 'store $ $ ADDED instead of RXIRQchar, because no $ was being stored
gnrmc_buf_filling = 1 'start storing the sentence
Goto RXIRQdone 'done with this character
Endif 'char was $
'no UART errors and character was not $
'If $ was found previously, process character looking for W and no buffer overflow.
'If haven't found $ yet, just ignore character.
If gnrmc_buf_filling = 1 Then 'if filling buffer, see if there is room in buf
'Break '<<<<<<<<<<<,
If gnrmcpsn >= (rxbufsize - 1) Then 'last char was at end of buf - buffer overflow so..
Gosub irqinitbuf 'restart buffer, discard sentence
RXerr = 1 'let main know that the buffer overflowed and is restarting
Goto RXIRQdone 'done, resume looking for next $
Endif 'buffer overflow
gnrmcpsn = gnrmcpsn + 1 'else, there's room in buf so bump index and store character, might be W
gnrmc_buf(gnrmcpsn) = RXIRQchar
If RXIRQchar = "W" Then 'if end of sentence..
RCSTA.CREN = 0 'shut down UART
PIE1.RCIE = 0 'Enable off
gnrmc_buf_filling = 0
gnrmc_buf_full = 1
Goto RXIRQdone 'and bye!
Endif 'RXIRQchar was W
Endif 'If gnrmc_buf_filling = 1
Endif 'RCIF=1
Endif 'RCIE=1
'Exit point for each RXinterrupt. Process timers
RXIRQdone:
'Resume
'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
Resume
'Stops UART, selects channel indicated by datasw (0-2)
'Inits RX buffer then restarts UART and enables RX interrupt
'Expects:
'GIE is enabled
'port directions and basic TX/RX
''-------------------- INIT SENTENCE BUFFER ------------------
''Sets up index and flags for next sentence. Overwrites
''old buffer data
''May be used by main (non-interrupt code) when PIR1.RCIE = 0
irqinitbuf:
gnrmcpsn = 0 'init index
RXerr = 0 'no error
RCSTA.CREN = 1
dumpchar = RCREG '1 'clear UART RX registers
dumpchar = RCREG '2
PIE1.RCIE = 1
Return
It likely won't since the entire uart receive code is already surrounded by a check for RCIE=1:The 'If PIR1.RCIF = 1 AND PIE1.RCIE=1 Then' line didn't make any difference.
'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
Hi T and M,It likely won't since the entire uart receive code is already surrounded by a check for RCIE=1:
Just checking for RCIF should be ok here since you've already checked for RCIECode:'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
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.
'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
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?