|
|
View previous topic :: View next topic |
Author |
Message |
Nevillestone
Joined: 05 Aug 2014 Posts: 24
|
RS232 waiting for TBE |
Posted: Sun Sep 27, 2020 5:51 am |
|
|
Hi guys got no answers on the previous post but did go and search posts for examples struggling though.
I'm trying to do rs232 transmit without a ISR, trying to read either the INT_TBE as a flag or read the TXIF as a bit.
have written the attached code but keep getting the same problem no indication of when TX is complete tried 2 ways see code would appreciate some guidance on GETENV or reading the interrupt flag.
Reduced my code to bare minimum
Compiling from within MPLABX V5.35
CCS compiler V 5.074
Thanks
Code: | #include <16F883.h>
#device adc=16
#DEVICE ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=8MHz,clock_out)
//' ******************************** DEFINE I / O PINS
#define RC_RXEN PIN_A0 //' 0 = "remote controller RS485 rx enable" output
#define RC_TXEN PIN_A1 //' 1 = "remote controller RS485 tx enable" output Symbol TP = PORTC.5 ' test point on pin 16
#define AUXrel PIN_A2 //' 1 = Aux relay on (slave to L2 or L3)
#define tpoint2 PIN_A3 //' testpoint pin (pin 5)
#define RADEN PIN_B0 //' 0 = "radio input enable" output
#define LOGIC PIN_B1 //' 1 = "LOGIC power switch" output
#define RELAY PIN_B2 //' 1 = "amplifier power RELAY" output
#define BIAS PIN_B3 //' 1 = "amplifier BIAS" output
#define IP_HRT PIN_B4 //' 0 = HRT input
#define IP_PTT PIN_B5 //' 0 = PTT input
#define LB_TXEN PIN_B6 //' 1 = "lightbar RS485 tx enable" output
#define LB_RXEN PIN_B7 //' 0 = "lightbar RS485 rx enable" output
#define S_Out PIN_C2 //' siren tone output port
#define RHL PIN_C3 //' 1 = "right headlamp relay on" output
#define LHL PIN_C4 //' 1 = "left headlamp relay on" output
#define Vpulse PIN_C5 //' volume control output pulse
//setup_uart ()
#USE rs232 (UART1,baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
//'Variable definitions:
//' ********************************* DECLARE VERIABLES
int1 TXIF;
//' ******************************** DEFINE FLAGS
#define POR = PCON.1 //' 0 = power on reset has occurred
#define OERR = RCSTA.1
#define FERR = RCSTA.2
#INT_TBE
void TBE_ISR(void)
{
clear_interrupt(INT_TBE);
disable_interrupts(INT_TBE);
TXIF=1;
output_toggle(tpoint2);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
}
void main()
{
setup_comparator(NC_NC_NC_NC);
output_high (LOGIC); // 'hold power on
output_high (RADEN); // 'disable radio input
output_low (BIAS); //'set amp bias off
#USE rs232 (UART1,baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
//'*************************************************************************
//'* MAIN DRIVER ROUTINE *
//'*************************************************************************
//START(void)
{
while (1)
{
//enable_interrupts(GLOBAL); //' Enable global interrupts
//enable_interrupts(INT_RDA);
output_high (RC_RXEN); //configure 485 chip for Transmit
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
delay_ms(10);
output_low (RC_TXEN); // configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
output_high (RC_RXEN); //'disable remote controller rs485 rx receiver
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
while (TXIF==0){#bit TXIF=getenv("bit:TXIF");} //wait for TX complete
output_low (RC_TXEN); //configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
output_high (RC_RXEN); //configure 485 chip for Transmit
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
while (!INT_TBE){} //wait for TX complete
output_low (RC_TXEN); // configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
}
}
} |
_________________
Neville _________________ Neville |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sun Sep 27, 2020 7:28 am |
|
|
Really you're doing RS-485 communications and not 'RS-232', there is a big difference. Kinda wondering why you just don't use the 'RS-485' options that CCS supplies ?
As well, ANY serial communications is a lot more reliable when you use interrupts and since that PIC has a HW UART, you should use it.
Have to ask WHY poll the bits? Depending on the program, it's a huge waste of time and resources.
Curious. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Sun Sep 27, 2020 10:33 am |
|
|
There are a lot of things not done 'right' in what you post. Comments
inline:
Code: |
#include <16F883.h>
#device adc=16
#DEVICE ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(internal=8MHz,clock_out)
//' ******************************** DEFINE I / O PINS
#define RC_RXEN PIN_A0 //' 0 = "remote controller RS485 rx enable" output
#define RC_TXEN PIN_A1 //' 1 = "remote controller RS485 tx enable" output Symbol TP = PORTC.5 ' test point on pin 16
#define AUXrel PIN_A2 //' 1 = Aux relay on (slave to L2 or L3)
#define tpoint2 PIN_A3 //' testpoint pin (pin 5)
#define RADEN PIN_B0 //' 0 = "radio input enable" output
#define LOGIC PIN_B1 //' 1 = "LOGIC power switch" output
#define RELAY PIN_B2 //' 1 = "amplifier power RELAY" output
#define BIAS PIN_B3 //' 1 = "amplifier BIAS" output
#define IP_HRT PIN_B4 //' 0 = HRT input
#define IP_PTT PIN_B5 //' 0 = PTT input
#define LB_TXEN PIN_B6 //' 1 = "lightbar RS485 tx enable" output
#define LB_RXEN PIN_B7 //' 0 = "lightbar RS485 rx enable" output
#define S_Out PIN_C2 //' siren tone output port
#define RHL PIN_C3 //' 1 = "right headlamp relay on" output
#define LHL PIN_C4 //' 1 = "left headlamp relay on" output
#define Vpulse PIN_C5 //' volume control output pulse
//setup_uart ()
#USE rs232 (UART1,baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
//Further comment here. A hardware UART, should _always_ have
//ERRORS in it's setup, unless you add your own hardware error
//handling.
//'Variable deinitions:
//' ********************************* DECLARE VERIABLES
//This is wrong.
//If this is to be the TXIF bit, then declare it as a #bit here
//However this is not the bit to use....
//int1 TXIF;
#bit TXBE=getenv("bit:TRMT")
/bit is a _preprocessor directive_, not a code line. Doesn't want
//a trailing ';'. It creates a one bit variable, that is built at the defined
//location. It doesn't want to be in the code, but before it is used.
//TRMT is the TSR shift register empty bit which says it has finished
//sending. This is what you need to be testing...
//' ******************************** DEFINE FLAGS
#define POR = PCON.1 //' 0 = power on reset has occurred
#define OERR = RCSTA.1
#define FERR = RCSTA.2
#INT_TBE
void TBE_ISR(void)
{
clear_interrupt(INT_TBE); //you can't actually do this. The only thing
//that clears this interrupt is loading a byte into the transmit buffer.
disable_interrupts(INT_TBE);
TXIF=1; //you are using the same name for this iNT1 flag, and for the
//transmit interupt bit. Need to be different.
output_toggle(tpoint2);
enable_interrupts(INT_RDA);
///enable_interrupts(GLOBAL);
//NEVER ever use enable_interrupts(GLOBAL) inside an interrupt
//handler. The interrupts are disabled by the act of an interrupt being
//serviced, and automatically re-enabled when the interrupt exits.
//enabling this before exiting can result in recursion, and a crash.
/Must never be done on a PIC.
}
void main()
{
setup_comparator(NC_NC_NC_NC);
output_high (LOGIC); // 'hold power on
output_high (RADEN); // 'disable radio input
output_low (BIAS); //'set amp bias off
//'*************************************************************************
//'* MAIN DRIVER ROUTINE *
//'*************************************************************************
//START(void)
//Is this you main code. If so, it should/must be preceeded by
//main, not 'START'...
{
while (1)
{
//enable_interrupts(GLOBAL); //' Enable global interrupts
//enable_interrupts(INT_RDA);
//You should never have any interrupt without a handler
//The only handler you show is for INT_TBE, not INT_RDA
output_high (RC_RXEN); //configure 485 chip for Transmit
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
delay_ms(10);
output_low (RC_TXEN); // configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
output_high (RC_RXEN); //'disable remote controller rs485 rx receiver
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
while (TXBE==0)
; //This now uses the hardware TRMT bit to say that transmission
//has finished.
output_low (RC_TXEN); //configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
output_high (RC_RXEN); //configure 485 chip for Transmit
output_high (RC_TXEN); //'enable remote controller rs485 tx driver
putc ('U'); //'tx remote update data (32mS after rx)
while (!INT_TBE){} //wait for TX complete
//INT_TBE will set when the transmit buffer is empty
//but you have nothing to clear the interrupt. INT_TBE cannot be
//cleared if the buffer is empty. It resets itself. INT_TBE has to be
//disabled if you have nothing more to send. You can't use INT_TBE
//like this. Use TRMT
output_low (RC_TXEN); // configure 485 chip for receive
output_low (RC_RXEN); //'enable remote controller rs485 rx receiver
delay_ms(25);
}
}
}
|
|
|
|
Nevillestone
Joined: 05 Aug 2014 Posts: 24
|
|
Posted: Sun Sep 27, 2020 12:48 pm |
|
|
HI thanks for the responce
I was under the impression I was using the HW uart
#USE rs232 (UART1,baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
I'm poling the bit as the Communication is not the most important function in my SW. and will handle the comms as and when time is available.
However the I did try the interrupt and it does not fire.
I know I'm doing something wrong here. _________________ Neville |
|
|
Nevillestone
Joined: 05 Aug 2014 Posts: 24
|
|
Posted: Sun Sep 27, 2020 12:56 pm |
|
|
Sorry only saw the comments in the code now will look at them and implement.
Thanks _________________ Neville |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sun Sep 27, 2020 1:34 pm |
|
|
in the use RS232(...options....)
...
ENABLE=pin
The specified pin will be high during transmit. This may be used to enable 485 transmit
...
Using this CCS supplied option will clean up your code...
My point about using the HW UART is that it allows you to use the Interrupts, again, making for better more reliable code.
Also if you use buffers, both xmt and rcv, PIC program runs a lot better ! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Mon Sep 28, 2020 12:23 am |
|
|
To me, the thinking is 'backwards'.
Waiting for TBE, is pointless, except to operate a handshake line.
The whole point is that the hardware sends without you having to wait,
so let it get on with it. The only time you need to test TBE when
sending, is _before_ you load a new character. If the buffer is full, then
hold the character in a buffer, and go and do your other jobs.
Testing for the buffer being empty after this point, is just wasting time. |
|
|
Nevillestone
Joined: 05 Aug 2014 Posts: 24
|
|
Posted: Mon Sep 28, 2020 6:51 am |
|
|
Hi thanks for the comments, have code working now.
Regarding the RS-485 comments:
I have 2 RS-485 drives on the same Tx line each one to a different device hence one enable pin is not enough.
But thanks will take all the comments and use them.
Thanks again _________________ Neville |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Mon Sep 28, 2020 7:32 am |
|
|
You can just use the standard driver with two enables.
What you do is generate two separate streams using the same hardware
port, with different enable pins. Then when you send to the first it's enable
is operated, send to the second and it's enable is operated. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Mon Sep 28, 2020 8:43 am |
|
|
Ttelmah wrote: | To me, the thinking is 'backwards'.
Waiting for TBE, is pointless, except to operate a handshake line.
The whole point is that the hardware sends without you having to wait,
so let it get on with it. The only time you need to test TBE when
sending, is _before_ you load a new character. If the buffer is full, then
hold the character in a buffer, and go and do your other jobs.
Testing for the buffer being empty after this point, is just wasting time. |
I know you know this already Ttelmah, but for the benefit of the OP. Another instance where checking the transmit buffer is important is if your software puts the board to sleep and your chip's UART isn't set to operate while in the sleep mode you chose. In that case you want to make sure that the transmit buffer is empty before going to sleep so you don't clobber any outgoing transmitted bytes. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Mon Sep 28, 2020 3:17 pm |
|
|
I'm curious about what you're trying to do, as RS-485 is designed to have several 'slaves' (I 'think' you have 2), so really 2 RS-485 chips wouldn't be necessary ?
What I 'think' you're trying to do is 'switch' between two 'slave' devices with only one UART ??
If you do need to access 2 separate 'RS-485' devices, perhaps one could have a software UART ? (1200 baud isn't that 'fast') Or better yet, choose a PIC with 2 hardware UARTs, especially if interrupts are required.
Just trying to figure out a possible, easy... solution that's reliable for you.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Tue Sep 29, 2020 12:33 am |
|
|
Yes. I read it that he is controlling two separate RS485 busses from a
single UART. Hence needs two ENABLE lines, on just the one UART.
Why the devices can't just be on a single bus, is 'unexplained'. He seems
to be using the select rather like a chip select, rather than a bus select. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Tue Sep 29, 2020 4:12 am |
|
|
hmm, I'm now thinking that he has two 'devices', that use the RS-485 interface standard, yet they are not addressable. 1200 Baud is kinda 'slow' by today's standards ( usually 9600), even for fairly long runs of cable.
Without knowing the overall project, it'd be easier using a PIC with 2 HW UARTS. 'Muxing' the UART does require attention to what happens just after switching between the 2 devices, especially dealing with possible 'garbage' on the 'new' device. Something like clear UART buffer, switch, clear UART buffer again, send data, receive data.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Tue Sep 29, 2020 4:20 am |
|
|
Yes. One particular 'critical' thing if doing this, would be to ensure that
the busses are biased so when 'idle' they give the correct polarity for
the stop bit, and that a new transmission is never started less than
one bit time after TRMT is set. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|