View Full Version : Framing error if I disable transmitter after shift register is empty?
Demon
- 23rd September 2024, 09:11
TX pin can be set manually, BUT THIS IS ONLY MASKING THE PROBLEM, NOT A REAL SOLUTION.
See Richard's post #33 and onwards for details.
UsartTX var LatC.6
UsartTX = 1
TXSTA.5 = 0
------------------------------------------------------
16F1937
Gutted my program to try to figure this out.
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
DEFINE OSC 32
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' ...not available
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %00000000
TRISD = %00000000
TRISE = %00000000
BlinkLED VAR LatB.5
Pause 500
hserout ["Hello world", 10]
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout ["TEST", 10]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Mainloop:
BlinkLED = 1
BlinkLED = 0
goto mainloop
end
Checking on Logic Probe, the line remains LOW after the last HSEROUT (4K7 pull-up on pin).
Yet processing is normal if I comment TXSTA.5 = 0.
richard
- 23rd September 2024, 10:03
as best i can see the data sheet indicates that what u are trying should be ok
9753
could hserout pacing be too slow to buffer tx data, and not really triggering back-back transmissions ?
if so then the last byte is still not sent yet.
if you used a decent chip you could make the tx pin open drain and not need this sort of worry
Demon
- 23rd September 2024, 18:18
I'm using a 16F1937, and I've done this successully in the past on this PIC model.
Check this out, it's always after the last HSEROUT:
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout ["1"]
hserout ["2"]
hserout ["3"]
hserout ["4"]
hserout ["5"]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
' TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
9754
Demon
- 23rd September 2024, 18:22
...could hserout pacing be too slow to buffer tx data, and not really triggering back-back transmissions ?
if so then the last byte is still not sent yet....
I thought this would ensure all bytes were transmitted?
while TXSTA.1 = 0
wend
...if you used a decent chip you could make the tx pin open drain and not need this sort of worry
I don't see why a 16F1937 could not do this reliably...?
Demon
- 23rd September 2024, 18:30
The last byte DOES get transmitted.
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout ["1"]
pause 1
hserout ["2"]
pause 1
hserout ["3"]
pause 1
hserout ["4"]
pause 1
hserout ["5"]
pause 1
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Something happens when the transmitter is disabled:
9755
I compare with my code and wiring on my old test circuit, and I can't see anything different...?
Ioannis
- 23rd September 2024, 19:12
The Shift register you mentioned is the 2 Bytes Buffer?
Ioannis
Demon
- 23rd September 2024, 21:22
The Shift register you mentioned is the 2 Bytes Buffer?
Ioannis
I suppose so. This is from the datasheet for TXSTA register:
bit 1 TRMT: Transmit Shift Register Status bit
1 = TSR empty
0 = TSR full
Demon
- 23rd September 2024, 21:30
It's getting even dumber by the minute. :D
TX code on 1st 16F1937:
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
DEFINE OSC 32
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' ...not available
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
BlinkLED VAR LatB.5
Pause 200
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[", 1, "]"]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Mainloop:
BlinkLED = 1
BlinkLED = 0
goto mainloop
end
RX code on 2nd 16F1937:
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
include "DT_INTS-14.bas"
include "ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _ReceiveInterrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
DEFINE OSC 32
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' ...not available
ANSELD = %00000000
ANSELE = %00000000 ' Pin E0 = ADC input
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
LEDblink var PORTD.0
RecvData var BYTE[11]
LEDblink = 0
goto Start
ReceiveInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
TXSTA.5 = 1
hserout [ "[", 0, "]" ]
while TXSTA.1 = 0 ' Check TRMT bit
wend
TXSTA.5 = 0
@ INT_RETURN
Start:
Pause 200 ' Let PIC and LCD stabilize
@ INT_ENABLE RX_INT
Mainloop:
LEDblink = 1
LEDblink = 0
GOTO Mainloop
end
The RX PIC has the exact same HSEROUT code:
- enable transmitter
- transmit data
- wait until buffer is empty
- disable transmitter
DISABLE transmitter causes a FRAMING ERROR on 1st PIC, but not on Ack message on 2nd PIC.
9756
This has to be a really stupid error cause there's practically no code left. :D
EDIT: Does it make a difference if I disable transmitter inside the Interrupt routine?
EDIT SOME MORE: I moved the DISABLE out of the ISR and into Mainloop, it didn't make a difference during RX on the 2nd PIC.
tumbleweed
- 23rd September 2024, 22:12
I'm not sure exactly what you intend to do, but TRMT gets asserted half-way into the STOP bit, so if you immediately disable the TX then the STOP bit will be half the time and generate a framing error.
The datasheet doesn't really specify that TXEN controls the state of the TX output pin (see datasheet section 25.1.1.1), but if it does return control back to the IO PORTC/TRISC registers then you'd have to make sure that the TX pin (RC6) is set to output high.
If you want it to be an input/tristate with an external pullup then set TRISC6.
amgen
- 23rd September 2024, 22:44
checking your stuff........ if you use interrupts (DT ints), for RX interrupts, you would not use PB hserin in the int routine. Rather get the characters in your routine and store them in the locations you designated and advance counter and check for some beginning or ending character....... with this I receive up to 1000 characters and store them in ram on 18f with 4k ram..... you would fix for your code. If successful receive, raised a flag telling basic to process the data for whatever your looking for
'''-------------RCV INT ROUTINE----------------''''
RCint:
RCX=RCREG
'@ bcf RCSTA,4
'@ bsf RCSTA,4
'''@ CLRF CREN ;RESET RCV overrun
'''@ SETF CREN
IF RCX=8 THEN '''CHECK FOR BACK SPACE BS 8dec
SELECT CASE RCVindx
CASE 0
GOTO LEAVEOK1
CASE 1
RCVindx=RCVindx-1 :RCVOK=0
RCVdata[RCVindx]=0
GOTO LEAVEOK1
CASE IS >1
RCVindx=RCVindx-1
RCVdata[RCVindx]=0
GOTO LEAVEOK1
END SELECT
ENDIF
if RCX = "[" then
RCVindx=0:RCVok=1:DATAready=0
goto leaveok
endif
if RCVok=0 then LEAVEOK1
if RCX = "]" then
rcvok=0:dataready=1
endif
leaveok: 'LEAVE AND STORE RCVD CHAR
RCVdata[RCVindx]=RCX
RCVindx=RCVindx+1
RCVdata[RCVindx]=0 'TACK A 0 AT END OF ARRAY
IF RCVindx > 999 THEN
RCVindx=999
ENDIF
LEAVEOK1: 'LEAVE WITHOUT STORING RCVD CHAR
RCFLAG=1
Demon
- 23rd September 2024, 22:49
I'm not sure exactly what you intend to do, ...
I'll be adding several more PICs on the network later, along with a tri-state BUSY line. The BUSY line will determine which PIC will be permitted to TRANSMIT at any given time. And that's why I ENABLE / TX / DISABLE, that code is in anticipation of more PICs being added.
...If you want it to be an input/tristate with an external pullup then set TRISC6
I have 4K7 pull-ups on both TX and RX pins. I only have RX set as Input. I plan on using a separate Busy line as tri-state.
I still don't see why PIC #1 gets a framing error, when PIC #2 doesn't and it's using essentially the exact same code...?
Demon
- 23rd September 2024, 22:53
checking your stuff........ if you use interrupts (DT ints), for RX interrupts, you would not use PB hserin in the int routine. Rather get the characters in your routine and store them in the locations you designated and advance counter and check for some beginning or ending character...
But the 2nd RX PIC receives perfectly. It's the 1st TX PIC that gives a framing error. And yet the 2nd RX gives an ACK using the HSEROUT structure, and it can DISABLE transmitter just fine.
I just don't get why PIC #1 cannot TXSTA.5 = 0, but PIC #2 can.
(I am going to keep that code on file, cause I'm sure it's going to be useful one day)
EDIT: I'm starting to think maybe I'm too dense to see the forest...
Demon
- 23rd September 2024, 23:00
Question: why do people use TX INT?
I can understand why you want to use RX INT, cause you don't know when the data will be incoming, but I do know when the data is being transmitted.
I'm just wondering out loud that maybe I'm not using the best technique to transmit...?
amgen
- 23rd September 2024, 23:07
don't give up on yourself or sell yourself short !...... it is a good project :)
Demon
- 23rd September 2024, 23:22
don't give up on yourself or sell yourself short !...... it is a good project :)
It's an awesome project. I can almost see the light at the end of the tunnel. I've done unit tests of every component all the way up to interfacing with MS Flight Sim. I'm just not seeing why I can't disable the transmitter in PIC #1.
I added a PAUSE to guarantee that everything is sent on PIC #1. The 2 PICs transmit successfully back and forth, and then I get a lone FRAMING ERROR all by itself, and PIC #2 locks up (there are no more blinking LED on channel 3).
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[1]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
PAUSE 100
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
So it's not an issue of losing bytes, it's definitely something peculiar about TXSTA.5 = 0.
9757
tumbleweed
- 23rd September 2024, 23:54
DISABLE transmitter causes a FRAMING ERROR on 1st PIC, but not on Ack message on 2nd PIC
In post 8 the trace is showing that the analyzer is detecting a framing error being generated by the transmitter when it sends the ']' and disables TXEN.
The TX data line should never idle low... that looks like a serial BREAK condition to the receiving side and will likely generate framing and overrun errors on that end.
A framing error by itself doesn't really cause any issues, but an overrun error will stop everything in its tracks until you clear the error. I see you have 'DEFINE HSER_CLROERR 1', so hopefully that's trying to take care of it, but maybe not. The way you have the receive arranged if things get out of sync then it might lock up waiting for something that's not going to happen.
As I said, if setting TXEN=0 causes the TX data line to go low that you need to change the TRIS/LAT register settings in your setup to stop that from happening.
Try initializing the pins with LATC6 = 1 and TRISC6 = 1. That should set the default state of the TX pin to high, which is the proper idle state.
You'll have to rethink all of this later when you try to add more devices since you can't just tie multiple TX outputs together, even if they're "disabled".
They would need to be tri-state/open-drain in the idle state, not driven high or low.
Demon
- 23rd September 2024, 23:54
I decreased the pause to 300uSec so everything is in the window when zoomed in.
The 2 transmits are working just fine, with the framing error over on the right.
9758
Demon
- 23rd September 2024, 23:56
...You'll have to rethink all of this later when you try to add more devices since you can't just tie multiple TX outputs together, even if they're "disabled".
They would need to be tri-state/open-drain in the idle state, not driven high or low.
Yes, they'll definitely be tri-state.
Demon
- 24th September 2024, 01:12
PIC #1:
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[1]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
hserin [ wait("["), STR RecvData\11\"]" ]
hserout [ "[2]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
pauseus 300
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Mainloop:
BlinkLED = 1
BlinkLED = 0
goto mainloop
end
PIC #2:
ReceiveInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
UsartFlag = 1
@ INT_RETURN
Start:
Pause 200 ' Let PIC and LCD stabilize
Mainloop:
LEDblink = 1
if UsartFlag = 1 then
TXSTA.5 = 1
hserout [ "[0]" ]
while TXSTA.1 = 0 ' Check TRMT bit
wend
UsartFlag = 0
TXSTA.5 = 0
endif
LEDblink = 0
GOTO Mainloop
end
1. PICs can talk back and forth with no errors.
2. PIC #2 can disable transmitter every single time.
3. Framing error as soon as PIC #1 disables transmitter, causing PIC #2 to lock up (no more blink LED on bottom channel).
9759
Demon
- 24th September 2024, 01:20
IT'S THE DARN PIC !
I swapped the coding between the 2 PICs, and PIC #1 now has a framing error every time it tries to disable the transmitter.
9760
I'm going to swap it for another unit and see if that changes things.
richard
- 24th September 2024, 02:12
when you disable the transmitter how are you setting the tx pin
code ?
Demon
- 24th September 2024, 02:23
Hmmm, I moved PIC #2 up in PIC #1 spot, and put in a new unit in PIC #2 spot.
PIC#1 can now disable transmitter at will, YAY! So that confirms that there's nothing on the breadboard interfering with that PIC.
New PIC #2 gets a framing error, but neither of the PICs freeze now (I put the blinky channel right under each PIC).
9761
PIC#1:
Start:
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[1]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
hserin [ wait("["), STR RecvData\11\"]" ]
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[2]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Mainloop:
BlinkLED = 1
BlinkLED = 0
GOTO Mainloop
end
PIC #2:
@ INT_ENABLE RX_INT
goto Start
ReceiveInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
UsartFlag = 1
@ INT_RETURN
Start:
Mainloop:
LEDblink = 1
if UsartFlag = 1 then
TXSTA.5 = 1
hserout [ "[0]" ]
while TXSTA.1 = 0 ' Check TRMT bit
wend
UsartFlag = 0
TXSTA.5 = 0
endif
LEDblink = 0
GOTO Mainloop
end
Might have a few ideas more ideas to try out...
Demon
- 24th September 2024, 02:24
when you disable the transmitter how are you setting the tx pin
code ?
I'm not doing anything to it. Should I?
richard
- 24th September 2024, 02:38
explain how disabling tx-module sets the pin to "tristate"
Demon
- 24th September 2024, 02:41
I'm not using tri-state yet, cause for now I have only two PICs talking, and they're not sharing any lines (but I will be the future, hence why I'd like to master enable/disable of transmitter).
It's direct TX-to-RX and RX-to-TX with 1 set of 4K7 pull-ups.
Right now it's only an exercise.
richard
- 24th September 2024, 02:45
It's direct TX-to-RX and RX-to-TX with 1 set of 4K7 pull-ups.
yet when tx is disabled the pin is hard driven to logic 0 , explain how disabling tx-module sets the pin to "tristate"
Demon
- 24th September 2024, 02:49
I'm not setting anything to tri-state, yet. Using TXSTA.5 = 1 / TXSTA.5 = 0 is just preparing myself for when I will use Usart pins in tri-state.
I thought I could just turn Usart TX and RX on/off whenever I wanted (when nothing was in the buffer).
Or was that a wrong assumption? :confused:
richard
- 24th September 2024, 02:51
post the code . no point guessing
Demon
- 24th September 2024, 02:56
post the code . no point guessing
Mainloop is in post #22.
Complete code PIC #1:
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
DEFINE OSC 32
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
TXSTA = %00100100 ' DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
' bit 7 CSRC: Clock Source Select bit
' Asynchronous mode:
' Don’t care
' Synchronous mode:
' 1 = Master mode (clock generated internally from BRG)
' 0 = Slave mode (clock from external source)
' bit 6 TX9: 9-bit Transmit Enable bit
' 1 = Selects 9-bit transmission
' 0 = Selects 8-bit transmission
' bit 5 TXEN: Transmit Enable bit(1)
' 1 = Transmit enabled
' 0 = Transmit disabled
' bit 4 SYNC: EUSART Mode Select bit
' 1 = Synchronous mode
' 0 = Asynchronous mode
' bit 3 SENDB: Send Break Character bit
' Asynchronous mode:
' 1 = Send Sync Break on next transmission (cleared by hardware upon completion)
' 0 = Sync Break transmission completed
' Synchronous mode:
' Don’t care
' bit 2 BRGH: High Baud Rate Select bit
' Asynchronous mode:
' 1 = High speed
' 0 = Low speed
' Synchronous mode:
' Unused in this mode
' bit 1 TRMT: Transmit Shift Register Status bit
' 1 = TSR empty
' 0 = TSR full
' bit 0 TX9D: Ninth bit of Transmit Data
' Can be address/data bit or a parity bit.
RCSTA = %10010000 'DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
' bit 7 SPEN: Serial Port Enable bit
' 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
' 0 = Serial port disabled (held in Reset)
' bit 6 RX9: 9-bit Receive Enable bit
' 1 = Selects 9-bit reception
' 0 = Selects 8-bit reception
' bit 5 SREN: Single Receive Enable bit
' Asynchronous mode:
' Don’t care
' Synchronous mode – Master:
' 1 = Enables single receive
' 0 = Disables single receive
' This bit is cleared after reception is complete.
' Synchronous mode – Slave
' Don’t care
' bit 4 CREN: Continuous Receive Enable bit
' Asynchronous mode:
' 1 = Enables receiver
' 0 = Disables receiver
' Synchronous mode:
' 1 = Enables continuous receive until enable bit CREN is cleared (CREN overrides SREN)
' 0 = Disables continuous receive
' bit 3 ADDEN: Address Detect Enable bit
' Asynchronous mode 9-bit (RX9 = 1):
' 1 = Enables address detection, enable interrupt and load the receive buffer when RSR<8> is set
' 0 = Disables address detection, all bytes are received and ninth bit can be used as parity bit
' Asynchronous mode 8-bit (RX9 = 0):
' Don’t care
' bit 2 FERR: Framing Error bit
' 1 = Framing error (can be updated by reading RCREG register and receive next valid byte)
' 0 = No framing error
' bit 1 OERR: Overrun Error bit
' 1 = Overrun error (can be cleared by clearing bit CREN)
' 0 = No overrun error
' bit 0 RX9D: Ninth bit of Received Data
' This can be address/data bit or a parity bit and must be calculated by user firmware.
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' ...not available
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
BlinkLED VAR LatB.5
RecvData var BYTE[11]
Pause 200 ' Let PIC and LCD stabilize
BlinkLED = 0
Start:
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[1]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
hserin [ wait("["), STR RecvData\11\"]" ]
TXSTA.5 = 1 ' TXEN: Transmit Enable bit
hserout [ "[2]" ]
while TXSTA.1 = 0 ' Check TRMT: Transmit Shift Register Status bit
wend
TXSTA.5 = 0 ' <----- Causes Framing error after last byte !
Mainloop:
BlinkLED = 1
BlinkLED = 0
GOTO Mainloop
end
Complete code PIC #2:
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
#ENDCONFIG
include "DT_INTS-14.bas"
include "ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _ReceiveInterrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
DEFINE OSC 32
SPLLEN CON %1 ' PLL enable
IRCF CON %1110 ' to enable 8 MHz
SCS CON %00 ' system clock determined by FOSC
OSCCON = (SPLLEN << 7) | (IRCF << 3) | SCS
TXSTA = %00100100 ' DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
' bit 7 CSRC: Clock Source Select bit
' Asynchronous mode:
' Don’t care
' Synchronous mode:
' 1 = Master mode (clock generated internally from BRG)
' 0 = Slave mode (clock from external source)
' bit 6 TX9: 9-bit Transmit Enable bit
' 1 = Selects 9-bit transmission
' 0 = Selects 8-bit transmission
' bit 5 TXEN: Transmit Enable bit(1)
' 1 = Transmit enabled
' 0 = Transmit disabled
' bit 4 SYNC: EUSART Mode Select bit
' 1 = Synchronous mode
' 0 = Asynchronous mode
' bit 3 SENDB: Send Break Character bit
' Asynchronous mode:
' 1 = Send Sync Break on next transmission (cleared by hardware upon completion)
' 0 = Sync Break transmission completed
' Synchronous mode:
' Don’t care
' bit 2 BRGH: High Baud Rate Select bit
' Asynchronous mode:
' 1 = High speed
' 0 = Low speed
' Synchronous mode:
' Unused in this mode
' bit 1 TRMT: Transmit Shift Register Status bit
' 1 = TSR empty
' 0 = TSR full
' bit 0 TX9D: Ninth bit of Transmit Data
' Can be address/data bit or a parity bit.
RCSTA = %10010000 'DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
' bit 7 SPEN: Serial Port Enable bit
' 1 = Serial port enabled (configures RX/DT and TX/CK pins as serial port pins)
' 0 = Serial port disabled (held in Reset)
' bit 6 RX9: 9-bit Receive Enable bit
' 1 = Selects 9-bit reception
' 0 = Selects 8-bit reception
' bit 5 SREN: Single Receive Enable bit
' Asynchronous mode:
' Don’t care
' Synchronous mode – Master:
' 1 = Enables single receive
' 0 = Disables single receive
' This bit is cleared after reception is complete.
' Synchronous mode – Slave
' Don’t care
' bit 4 CREN: Continuous Receive Enable bit
' Asynchronous mode:
' 1 = Enables receiver
' 0 = Disables receiver
' Synchronous mode:
' 1 = Enables continuous receive until enable bit CREN is cleared (CREN overrides SREN)
' 0 = Disables continuous receive
' bit 3 ADDEN: Address Detect Enable bit
' Asynchronous mode 9-bit (RX9 = 1):
' 1 = Enables address detection, enable interrupt and load the receive buffer when RSR<8> is set
' 0 = Disables address detection, all bytes are received and ninth bit can be used as parity bit
' Asynchronous mode 8-bit (RX9 = 0):
' Don’t care
' bit 2 FERR: Framing Error bit
' 1 = Framing error (can be updated by reading RCREG register and receive next valid byte)
' 0 = No framing error
' bit 1 OERR: Overrun Error bit
' 1 = Overrun error (can be cleared by clearing bit CREN)
' 0 = No overrun error
' bit 0 RX9D: Ninth bit of Received Data
' This can be address/data bit or a parity bit and must be calculated by user firmware.
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ANSELA = %00000000
ANSELB = %00000000
'ANSELC = %00000000 ' ...not available
ANSELD = %00000000
ANSELE = %00000000 ' Pin E0 = ADC input
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00000000
LEDblink var LatD.0
RecvData var BYTE[11]
UsartFlag Var byte
Pause 200 ' Let PIC and LCD stabilize
LEDblink = 0
UsartFlag = 0
@ INT_ENABLE RX_INT
goto Start
ReceiveInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
UsartFlag = 1
@ INT_RETURN
Start:
Mainloop:
LEDblink = 1
if UsartFlag = 1 then
TXSTA.5 = 1
hserout [ "[0]" ]
while TXSTA.1 = 0 ' Check TRMT bit
wend
UsartFlag = 0
TXSTA.5 = 0
endif
LEDblink = 0
GOTO Mainloop
end
I prefer to use:
TXSTA = %00100100
RCSTA = %10010000
instead of:
DEFINE HSER_TXSTA 24h
DEFINE HSER_RCSTA 90h
So that I can actually see what bits are set (or is there more going on in the background with DEFINE?)
richard
- 24th September 2024, 03:03
so there is the problem
TRISC = % 10000000
portc pin 6 is set as an output
the latc.6 value is undefined but obviously 0
when tx module is disabled the pin reverts to be an output driven low , hence framing error
tumble weed pointed this out twice
and i said in post#2
if you used a decent chip you could make the tx pin open drain and not need this sort of worry
Demon
- 24th September 2024, 03:12
so there is the problem
TRISC = % 10000000
portc pin 6 is set as an output
the latc.6 value is undefined but obviously 0...
Should I set LatC.6 to 1 when I disable the transmitter? :confused:
...when tx module is disabled the pin reverts to be an output driven low , hence framing error
tumble weed pointed this out twice...
I thought the pull-ups were supposed to handle that?
...and i said in post#2
if you used a decent chip you could make the tx pin open drain and not need this sort of worry
I chose 16F1937 mainly because of availability and price over at JLCPCB.
And I don't know how to "make the tx pin open drain"; I've never done that.
Microchip lists the 16F1937 as "in production", is there something I should know about this chip?
I don't honestly don't understand why you consider it not a decent chip?
Demon
- 24th September 2024, 03:17
UsartTX var LatC.6
UsartTX = 1
TXSTA.5 = 0
Framing error is gone on PIC #2
WOOT!
My new sig line "I understand quick, but you gotta explain slowly and a repeat a dozen times!" :D
richard
- 24th September 2024, 03:25
there is another issue with that chip
from data sheet async reception chapter
9762
Should I set LatC.6 to 1 when I disable the transmitter?
no , it will look like it works but the pin is now hard driven high , not tristated at all
I thought the pull-ups were supposed to handle that?
if the pin was tristated then it would
And I don't know how to "make the tx pin open drain"; I've never done that.
that chip cannot do it, more suitable to task chips have a ODCONx register
I don't honestly don't understand why you consider it not a decent chip?
poorly suited to task at hand in my view
richard
- 24th September 2024, 03:32
you have now declared the thread solved when it is not!
the problem is only temporally masked and will rear its ugly head when you enable another transmitter
Demon
- 24th September 2024, 03:34
there is another issue with that chip
from data sheet async reception chapter ...
Oh crap, I didn't see that. :sad:
Demon
- 24th September 2024, 03:35
you have now declared the thread solved when it is not!
the problem is only temporally masked and will rear its ugly head when you enable another transmitter
Yeah, I thought the problem went away. I'll edit them back.
Ioannis
- 24th September 2024, 13:29
Since the output on that specific chip will remain as driven output, and if you insist on using this, a crapy solution maybe to add a diode at the output before the pin is connected to the bus.
The cathode to the PIC usart output and anode to the bus.
Like an OR connection of all the PICs that will be in parallel. Then a pull up will hold line to HIGH state.
This is subject to capacitances over the bus and the pull-up resistor may not be able to charge that capacitances fast enough but you can test it and see if your are OK with the speed you may obtain.
The chip that you found to be faulty, may have been hit by ESD charge. Are you familiar with ESD protection? Are you taking measures when you handle ESD sensitive components?
Ioannis
Demon
- 24th September 2024, 18:55
Since the output on that specific chip will remain as driven output, and if you insist on using this, a crapy solution maybe to add a diode at the output before the pin is connected to the bus. ...
I "like" the 16F1937, but I have no allegiance towards it (I only have 15 on hand, I'll keep them for "something else"). :D I'm starting the slow/annoying process of choosing another PIC, with added requirement for ODCON register.
... The chip that you found to be faulty, may have been hit by ESD charge. Are you familiar with ESD protection? Are you taking measures when you handle ESD sensitive components?
Ioannis
I don't have carpet, and that's the extent of my ESD protections. I think I somehow messed it up when I first powered it up on the breadboard. It's a real possibility that I applied power to the wrong pins.
Demon
- 25th September 2024, 04:25
... if the pin was tristated then it would
that chip cannot do it, more suitable to task chips have a ODCONx register ...
Like this on a 16F18877?
ODCONC.6 = 0 ' Permit transmission (source current at will)
hserout [ ...message... ]
while TXSTA.1 = 0 ' Check TRMT bit
wend
ODCONC.6 = 1 ' Deny transmission (sink current only)
Am I supposed to set TRIS as well?
(I remember reading somewhere that USART ignores TRIS, or something...?)
richard
- 25th September 2024, 04:56
Like this on a 16F18877?
not really , why would you want to change it back and forth?
is there a pullup for the tx line ?
post entire code snippets are nil value
richard
- 25th September 2024, 05:28
(I remember reading somewhere that USART ignores TRIS, or something...?)
you may well have but if you think every pic chip is the same then you will be in for a world of hurt . read the data sheet
Ioannis
- 25th September 2024, 14:55
I don't have carpet, and that's the extent of my ESD protections.
Well the carpet is one thing. Even if you just walked the room and returned back to you chair (even worse if it has suspension), then you may well have charged enough to destroy the chips.
You have to remember to ground yourself just before you touch components or even better have a wrist band to permantly ground your body (through a high value resistor of course).
ESD can destroy just a tiny part of the chip, enough to drive you crazy!
Ioannis
tumbleweed
- 25th September 2024, 15:22
Am I supposed to set TRIS as well?
The USART section in the datasheet for your device will tell you if you should set/clear the TRIS bits for the TX/RX pins.
If the chip supports open-drain mode then you just need to setup the TX pin to enable it at startup (ODCONC.6 = 1).
There's no need to set and clear it, and you won't need to enable/disable TXEN anymore either.
Add a pullup to the TX line (you say you already have one), and you can connect all the TX lines from the different pics together now.
If your pic has PPS you'll probably need to set that up too to assign the pin to the UART TXD function.
PPS output functions aren't typically enabled by default.
Demon
- 25th September 2024, 22:07
not really , why would you want to change it back and forth?...
To be able to add more PICs later on the TX line.
...is there a pullup for the tx line ?...
Yup, on RX also. Both are on PIC #1.
(Using 16F18877 for testing)
PIC #1:
#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF
#ENDCONFIG
include "DT_INTS-14_16F18877.bas"
include "ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _RXInterrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE RX_INT ; Enables RX interrupts
ENDASM
DEFINE OSC 32
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
DEFINE HSER_RXREG PORTC
DEFINE HSER_RXBIT 7
DEFINE HSER_TXREG PORTC
DEFINE HSER_TXBIT 6
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00001000
LEDblink var LatB.5
RecvData var BYTE[11]
UsartFlag Var byte
pause 200
LEDblink = 0
UsartFlag = 0
goto Start
RXInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
UsartFlag = 1
@ INT_RETURN
Start:
' ODCONC.6 = 0
hserout [ "[X]" ]
while TX1STA.1 = 0 ' Check TRMT bit
wend
' ODCONC.6 = 1
Mainloop:
LEDblink = 1
if UsartFlag = 0 then
UsartFlag = 0
endif
LEDblink = 0
goto Mainloop
end
PIC #2:
#CONFIG
__config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
__config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
__config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_OFF & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
__config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
__config _CONFIG5, _CP_OFF & _CPD_OFF
#ENDCONFIG
include "DT_INTS-14_16F18877.bas"
include "ReEnterPBP.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _ReceiveInterrupt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE RX_INT ; Enables RX interrupts
ENDASM
DEFINE OSC 32
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
Define HSER_BAUD 115200
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRGH 0
DEFINE HSER_SPBRG 68
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
DEFINE HSER_RXREG PORTC
DEFINE HSER_RXBIT 7
DEFINE HSER_TXREG PORTC
DEFINE HSER_TXBIT 6
ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
TRISD = %00000000
TRISE = %00001000
LEDblink var LatD.0
RecvData var BYTE[11]
UsartFlag Var byte
pause 200
LEDblink = 0
UsartFlag = 0
goto Start
ReceiveInterrupt:
hserin [ wait("["), STR RecvData\11\"]" ]
UsartFlag = 1
@ INT_RETURN
Start:
Mainloop:
LEDblink = 1
if UsartFlag = 1 then
' ODCONC.6 = 0
hserout [ "[Y]" ]
while TX1STA.1 = 0 ' Check TRMT bit
wend
' ODCONC.6 = 1
UsartFlag = 0
endif
LEDblink = 0
GOTO Mainloop
end
Results:
9764
Custom DT_INTS-14.bas (IOC, RX, CCPx):
'************************************************* **************************
'* Name : DT_INTS-14_16F1885x-7x.bas *
'* Author : Darrel Taylor (modified by Demon) *
'* Version : 1.15 (8/29/2024) *
'* Date : OCT 13, 2009 *
'************************************************* **************************
'* REV 1.15 Customized for 16F1885xx-7x (IOC, USART-RX, CCPx) *
'* REV 1.10 Fixes Duplicate label error when Handlers cross page boundary *
'* Fixes error with 16F1's and MPLAB 8.53 (high) *
'* REV 1.00 Completely re-written, with optimization and F1 chips in mind *
'* REV 0.93 Fixed CMIF and EEIF problem with older PIC's *
'* that have the Flags in PIR1 instead of PIR2 *
'* Rev 0.92 solves a "Missed Interrupt" and *
'* banking switching problem *
'************************************************* **************************
DEFINE DT_INTS_VERSION 110
DEFINE INTHAND INT_ENTRY
;-- Place a copy of these variables in your Main program -------------------
;-- The compiler will tell you which lines to un-comment --
;-- Do Not un-comment these lines --
;---------------------------------------------------------------------------
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
;wsave VAR BYTE $70 SYSTEM ' alternate save location for W
' if using $70, comment wsave1-3
' --- IF any of these three lines cause an error ?? ------------------------
' Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
;wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
;wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
;wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
' --------------------------------------------------------------------------
ssave VAR BYTE BANK0 SYSTEM ' location for STATUS register
psave VAR BYTE BANK0 SYSTEM ' location for PCLATH register
fsave VAR BYTE BANK0 SYSTEM ' location for FSR register
RetAddr VAR WORD BANK0
INT_Bits VAR BYTE BANK0
Serviced VAR INT_Bits.0
Vars_Saved VAR INT_Bits.1
GIE VAR INTCON.7
PEIE VAR INTCON.6
ASM
ifdef PM_USED ; verify MPASM is the assembler
"ERROR: DT_INTS does not support the PM assembler, USE MPASM"
endif
;---------------------------------------------------------------------------
ifdef ReEnterUsed
ifdef ReEnterVersion
if (ReEnterVersion < 34)
error "Wrong version of ReEnterPBP.bas - Ver 3.4 or higher required
endif
else
error "Wrong version of ReEnterPBP.bas - Ver 3.4 or higher required
endif
endif
;---------------------------------------------------------------------------
if (BANK0_END == 0x7F)
ifdef BANK1_END
if (BANK1_END == 0xEF) ; doesn't find 12F683
variable ACCESSRAM = 1
else
variable ACCESSRAM = 0
endif
else
variable ACCESSRAM = 0
endif
else
variable ACCESSRAM = 0
endif
;---------------------------------------------------------------------------
#define OrChange Or change to wsave BYTE $70 SYSTEM
AddWsave macro B
if (B == 0)
if (ACCESSRAM == 1)
error " Add:" wsave VAR BYTE $70 SYSTEM
else
error " Add:" wsave VAR BYTE $20 SYSTEM
endif
endif
if (B == 1)
if (ACCESSRAM == 1)
error " Add:" wsave1 VAR BYTE $A0 SYSTEM, OrChange
else
error " Add:" wsave1 VAR BYTE $A0 SYSTEM
endif
endif
if (B == 2)
if (ACCESSRAM == 1)
error " Add:" wsave2 VAR BYTE $120 SYSTEM, OrChange
else
error " Add:" wsave2 VAR BYTE $120 SYSTEM
endif
endif
if (B == 3)
if (ACCESSRAM == 1)
error " Add:" wsave3 VAR BYTE $1A0 SYSTEM, OrChange
else
error " Add:" wsave3 VAR BYTE $1A0 SYSTEM
endif
endif
endm
#define WsaveE1(B) Chip has RAM in BANK#v(B), but wsave#v(B) was not found.
;#define WsaveE2(B) Uncomment wsave#v(B) in the DT_INTS-14.bas file.
#define WsaveCouldBe This chip has access RAM at $70
#define WsaveError(B) error WsaveE1(B)
ifndef FSR0L ; not a 16F1
ifndef wsave
; if (ACCESSRAM == 1)
error wsave variable not found,
AddWsave(0)
variable wsave = 0 ; stop further wsave errors
; else
; endif
else
if (wsave == 0x70)
if (ACCESSRAM == 0)
error This chip does not have AccessRAM at $70, change to wsave VAR BYTE $20 SYSTEM
endif
else
if (wsave != 0x20)
error wsave must be either $20 or $70
endif
endif
endif
ifdef BANK1_START
ifndef wsave1
ifdef wsave
if (wsave != 0x70)
WsaveError(1)
AddWsave(1)
endif
else
if (ACCESSRAM == 1)
if (wsave != 0x70)
WsaveCouldBe
endif
endif
endif
endif
endif
ifdef BANK2_START
ifndef wsave2
ifdef wsave
if (wsave != 0x70)
WsaveError(2)
AddWsave(2)
endif
endif
endif
endif
ifdef BANK3_START
ifndef wsave3
ifdef wsave
if (wsave != 0x70)
WsaveError(3)
AddWsave(3)
endif
endif
endif
endif
endif
ENDASM
ASM
asm = 0
Asm = 0
ASM = 0
pbp = 1
Pbp = 1
PBP = 1
yes = 1
Yes = 1
YES = 1
no = 0
No = 0
NO = 0
;---[Original DEFINES]------------------------------------------------------
#define ALL_INT INTCON,GIE, INTCON,GIE ;-- Global Interrupts *
; #define IOC_INT INTCON,IOCIF, INTCON,IOCIE ;-- Int On Change
; #define RX_INT PIR1,RCIF, PIE1,RCIE ;-- USART Receive
; #define CCP1_INT PIR1,CCP1IF, PIE1,CCP1IE ;-- CCP1
; #define CCP2_INT PIR2,CCP2IF, PIE2,CCP2IE ;-- CCP2
; #define CCP3_INT PIR3,CCP3IF, PIE3,CCP3IE ;-- CCP3
; #define CCP4_INT PIR3,CCP4IF, PIE3,CCP4IE ;-- CCP4
; #define CCP5_INT PIR3,CCP5IF, PIE3,CCP5IE ;-- CCP5
#define IOC_INT PIR0,IOCIF, PIE0,IOCIE ;-- Int On Change *
#define RX_INT PIR3,RCIF, PIE3,RCIE ;-- USART Receive
#define CCP1_INT PIR6,CCP1IF, PIE6,CCP1IE ;-- CCP1
#define CCP2_INT PIR6,CCP2IF, PIE6,CCP2IE ;-- CCP2
#define CCP3_INT PIR6,CCP3IF, PIE6,CCP3IE ;-- CCP3
#define CCP4_INT PIR6,CCP4IF, PIE6,CCP4IE ;-- CCP4
#define CCP5_INT PIR6,CCP5IF, PIE6,CCP5IE ;-- CCP5
ENDASM
ASM
;---[Returns the Address of a Label as a Word]------------------------------
GetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
; movlw High Label ; get high byte MPLAB 8.53 killed high
movlw Label >> 8 ; get high byte
movwf Wout + 1
endm
;---[find correct bank for a BIT variable]----------------------------------
CHKRP?T macro reg, bit
CHK?RP reg
endm
;---[This creates the main Interrupt Service Routine (ISR)]-----------------
INT_CREATE macro
local OverCREATE
L?GOTO OverCREATE
INT_ENTRY
ifndef FSR0L
if (CODE_SIZE <= 2)
movwf wsave ; 1 copy W to wsave register
swapf STATUS,W ; 2 swap status reg to be saved into W
clrf STATUS ; 3 change to bank 0
movwf ssave ; 4 save status reg to a bank 0 register
movf PCLATH,W ; 5 move PCLATH reg to be saved into W reg
movwf psave ; 6 save PCLATH reg to a bank 0 register
endIF
movf FSR,W ; 7 move FSR reg to be saved into W reg
movwf fsave ; 8 save FSR reg to a bank 0 register
else
banksel 0 ; BANK 0 for F1 chips
endif
variable PREV_BANK = 0
MOVE?CT 0, _Vars_Saved
List_Start
ifdef LoopWhenServiced
MOVE?CT 0, _Serviced ; indicate nothing has been serviced
endif
INT_LIST ; Expand the users list of interrupt handlers
; INT_LIST macro must be defined in main program
ifdef LoopWhenServiced
BIT?GOTO 1, _Serviced, List_Start
endif
ifdef ReEnterUsed ; if ReEnterPBP.bas was included
CHKRP?T _Vars_Saved
btfss _Vars_Saved ; if PBP system vars have been saved
goto INT_EXIT
L?GOTO _RestorePBP ; Restore PBP system Vars
endif
INT_EXIT
variable PREV_BANK = 0
ifndef FSR0L ; if chip is not an F1 - restore context
clrf STATUS ; BANK 0
movf fsave,W ; Restore the FSR reg
movwf FSR
movf psave,w ; Restore the PCLATH reg
movwf PCLATH
swapf ssave,w ; Restore the STATUS reg
movwf STATUS
swapf wsave,f
swapf wsave,w ; Restore W reg
endif
retfie ; Exit the interrupt routine
;-----------------------------
LABEL?L OverCREATE
bsf INTCON, 6 ; Enable Peripheral interrupts
bsf INTCON, 7 ; Enable Global interrupts
endm
ENDASM
ASM
;---[Add an Interrupt Source to the user's list of INT Handlers]------------
#INT_HANDLER macro FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
list
local AfterSave, AfterUserRoutine, NoInt
ifdef FlagBit
CHK?RP EnableReg
btfss EnableReg, EnableBit ; if the INT is enabled
goto NoInt
CHK?RP FlagReg
btfss FlagReg, FlagBit ; and the Flag set?
goto NoInt
ifdef LoopWhenServiced
MOVE?CT 1, _Serviced
endif
if (Type == PBP) ; If INT handler is PBP
ifdef ReEnterUsed
btfsc _Vars_Saved
goto AfterSave
GetAddress AfterSave, _RetAddr
L?GOTO _SavePBP ; Save PBP system Vars
LABEL?L AfterSave
else
error ReEnterPBP must be INCLUDEd to use PBP type interrupts
endif
endif
GetAddress AfterUserRoutine, _RetAddr ; save return address
L?GOTO Label ; goto the users INT handler
LABEL?L AfterUserRoutine
if (Reset == YES)
CHK?RP FlagReg
bcf FlagReg, FlagBit ; reset flag (if specified)
endif
else
INT_ERROR "INT_Handler"
endif
NoInt
banksel 0
PREV_BANK = 0
endm
;-----------------------------------
#define INT_HANDLER(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
ifndef INT_Handler
#define INT_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define int_handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define Int_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define Int_handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
#define int_Handler(FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset) #INT_HANDLER FlagReg,FlagBit, EnableReg,EnableBit, Label, Type,Reset
endif
;---[Returns from a "goto" subroutine]--------(RetAddr must be set first)---
#INT_RETURN macro
CHK?RP _RetAddr
movf _RetAddr + 1, W ; Set PCLATH with top byte of return address
movwf PCLATH
movf _RetAddr, W ; Go back to where we were
movwf PCL
endm
;_____________________________
#define INT_RETURN #INT_RETURN
ifndef INT_Return
#define INT_Return #INT_RETURN
#define int_return #INT_RETURN
#define Int_Return #INT_RETURN
#define Int_return #INT_RETURN
#define int_Return #INT_RETURN
endif
;----[Display not found error]----------------------------------------------
INT_ERROR macro From
error From - Interrupt Flag ( FlagReg,FlagBit ) not found.
endm
;---[Enable an interrupt source]--------------------------------------------
ifndef INT_ENABLECLEARFIRST
#define INT_ENABLECLEARFIRST 1 ; default to Clear First
endif ; use DEFINE INT_ENABLECLEARFIRST 0 to NOT clear First
#INT_ENABLE macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
ifdef INT_ENABLECLEARFIRST
if (INT_ENABLECLEARFIRST == 1) ; if specified
MOVE?CT 0, FlagReg, FlagBit ; clear the flag first
endif
endif
MOVE?CT 1, EnableReg, EnableBit ; enable the INT source
else
INT_ERROR "INT_ENABLE"
endif
endm
;_____________________________
#define INT_ENABLE(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Enable
#define INT_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_Enable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_ENABLE FlagReg, FlagBit, EnableReg, EnableBit
endif
;---[Disable an interrupt source]-------------------------------------------
#INT_DISABLE macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
MOVE?CT 0, EnableReg, EnableBit ; disable the INT source
else
INT_ERROR "INT_DISABLE"
endif
endm
;_____________________________
#define INT_DISABLE(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Disable
#define INT_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define Int_disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
#define int_Disable(FlagReg, FlagBit, EnableReg, EnableBit) #INT_DISABLE FlagReg, FlagBit, EnableReg, EnableBit
endif
;---[Clear an interrupt Flag]-----------------------------------------------
#INT_CLEAR macro FlagReg, FlagBit, EnableReg, EnableBit
ifdef FlagBit
MOVE?CT 0, FlagReg, FlagBit ; clear the flag
else
INT_ERROR "INT_CLEAR"
endif
endm
;_____________________________
#define INT_CLEAR(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
ifndef INT_Clear
#define INT_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define int_clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define Int_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define Int_clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
#define int_Clear(FlagReg, FlagBit, EnableReg, EnableBit) #INT_CLEAR FlagReg, FlagBit, EnableReg, EnableBit
endif
ENDASM
Demon
- 25th September 2024, 22:16
The USART section in the datasheet for your device will tell you if you should set/clear the TRIS bits for the TX/RX pins....
I've misunderstood/misinterpreted the data sheet before. :D Seriously, I read the EUSART section and my eyes gloss over when they start making distinctions between half-duplex, full-duplex, synchronous, asynchronous...)
..If the chip supports open-drain mode then you just need to setup the TX pin to enable it at startup (ODCONC.6 = 1).
There's no need to set and clear it, and you won't need to enable/disable TXEN anymore either...
Something like..?
TRISC.7=1
ODCONC.6 = 1
Loop:
TX, RX, rinse repeat
I would have thought you need to reset ODCONC.6 to "standard push/pull"...? (Possible example of not always understanding what the datasheet "means").
...If your pic has PPS you'll probably need to set that up too to assign the pin to the UART TXD function.
PPS output functions aren't typically enabled by default.
Yes, I figured that much. There's just so many peripherals available (coming from a guy that started with a 16F628).
EDIT: I just rechecked the EUSART section (starts at page 543), and they never mention ODCON (last occurence is at page 233).
The datasheet says very little about ODCON:
9765
richard
- 26th September 2024, 01:40
An open-drain or open-collector output pin is driven by a single transistor, which pulls the pin to only one voltage (generally, to ground). When the output device is off, the pin is left floating (open, or hi-z). A common example is an n-channel transistor which pulls the signal to ground when the transistor is on or leaves it open when the transistor is off.
Open-drain refers to such a circuit implemented in FET technologies because the transistor’s drain terminal is connected to the output; open-collector means a bipolar transistor’s collector is performing the function.
When the Open-drain transistor is off, the signal line is free to be driven low by another device, it generally will be pulled up by a resistor. The resistor prevents an undefined, floating state.
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.