CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

RS232 waiting for TBE

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Nevillestone



Joined: 05 Aug 2014
Posts: 21

View user's profile Send private message

RS232 waiting for TBE
PostPosted: Sun Sep 27, 2020 5:51 am     Reply with quote

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: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Sep 27, 2020 7:28 am     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Sun Sep 27, 2020 10:33 am     Reply with quote

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: 21

View user's profile Send private message

PostPosted: Sun Sep 27, 2020 12:48 pm     Reply with quote

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: 21

View user's profile Send private message

PostPosted: Sun Sep 27, 2020 12:56 pm     Reply with quote

Sorry only saw the comments in the code now will look at them and implement.
Thanks
_________________
Neville
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Sep 27, 2020 1:34 pm     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Mon Sep 28, 2020 12:23 am     Reply with quote

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: 21

View user's profile Send private message

PostPosted: Mon Sep 28, 2020 6:51 am     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Mon Sep 28, 2020 7:32 am     Reply with quote

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: 1314

View user's profile Send private message

PostPosted: Mon Sep 28, 2020 8:43 am     Reply with quote

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: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Sep 28, 2020 3:17 pm     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Tue Sep 29, 2020 12:33 am     Reply with quote

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: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Sep 29, 2020 4:12 am     Reply with quote

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: 19195

View user's profile Send private message

PostPosted: Tue Sep 29, 2020 4:20 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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