Changed Tturnaround time in MS/TP modules to be a minimum of 2ms, or use a dummy transmit of 4 bytes while the transceiver is disabled. 1ms delay will always give smaller than 1ms of delay due to silence timer tick.

This commit is contained in:
skarg
2010-10-18 20:42:26 +00:00
parent a5f24fa19f
commit 57781b40cb
8 changed files with 72 additions and 55 deletions
+2 -2
View File
@@ -167,7 +167,7 @@ void RS485_Turnaround_Delay(
/* delay after reception before trasmitting - per MS/TP spec */ /* delay after reception before trasmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */ /* wait a minimum 40 bit times since reception */
/* at least 1 ms for errors: rounding, clock tick */ /* at least 1 ms for errors: rounding, clock tick */
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud); turnaround_time = 2 + ((Tturnaround * 1000UL) / RS485_Baud);
while (Timer_Silence() < turnaround_time) { while (Timer_Silence() < turnaround_time) {
/* do nothing - wait for timer to increment */ /* do nothing - wait for timer to increment */
}; };
@@ -241,7 +241,7 @@ bool RS485_ReceiveError(
} }
/**************************************************************************** /****************************************************************************
* DESCRIPTION: Return true if data is available * DESCRIPTION: Return true if data is available
* RETURN: true if data is available, with the data in the parameter set * RETURN: true if data is available, with the data in the parameter set
* ALGORITHM: none * ALGORITHM: none
* NOTES: none * NOTES: none
+29 -33
View File
@@ -44,18 +44,6 @@ static uint8_t LED3_Off_Timer;
/* baud rate */ /* baud rate */
static uint32_t RS485_Baud = 9600; static uint32_t RS485_Baud = 9600;
/* The minimum time after the end of the stop bit of the final octet of a */
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
/* 40 bits is 4 octets including a start and stop bit with each octet */
#define Tturnaround (40UL)
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
/**************************************************************************** /****************************************************************************
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in * DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
* receive mode. * receive mode.
@@ -137,26 +125,6 @@ bool RS485_Set_Baud_Rate(
return valid; return valid;
} }
/****************************************************************************
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Turnaround_Delay(
void)
{
uint16_t turnaround_time;
/* delay after reception before trasmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */
/* at least 1 ms for errors: rounding, clock tick */
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
while (Timer_Silence() < turnaround_time) {
/* do nothing - wait for timer to increment */
};
}
/**************************************************************************** /****************************************************************************
* DESCRIPTION: Enable or disable the transmitter * DESCRIPTION: Enable or disable the transmitter
* RETURN: none * RETURN: none
@@ -173,6 +141,35 @@ void RS485_Transmitter_Enable(
} }
} }
/****************************************************************************
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Turnaround_Delay(
void)
{
uint8_t nbytes = 4;
RS485_Transmitter_Enable(false);
while (nbytes) {
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
/* Send the data byte */
UDR0 = 0xff;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR0A, TXC0);
}
/**************************************************************************** /****************************************************************************
* DESCRIPTION: Timers for delaying the LED indicators going off * DESCRIPTION: Timers for delaying the LED indicators going off
* RETURN: none * RETURN: none
@@ -253,7 +250,6 @@ void RS485_Send_Data(
Timer_Silence_Reset(); Timer_Silence_Reset();
} }
/**************************************************************************** /****************************************************************************
* DESCRIPTION: Return true if a framing or overrun error is present * DESCRIPTION: Return true if a framing or overrun error is present
* RETURN: true if error * RETURN: true if error
+17 -8
View File
@@ -161,15 +161,24 @@ bool RS485_Set_Baud_Rate(
void RS485_Turnaround_Delay( void RS485_Turnaround_Delay(
void) void)
{ {
uint16_t turnaround_time; uint8_t nbytes = 4;
/* delay after reception before trasmitting - per MS/TP spec */ RS485_Transmitter_Enable(false);
/* wait a minimum 40 bit times since reception */ while (nbytes) {
/* at least 1 ms for errors: rounding, clock tick */ while (!BIT_CHECK(UCSR0A, UDRE0)) {
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud); /* do nothing - wait until Tx buffer is empty */
while (!timer_silence_elapsed(turnaround_time)) { }
/* do nothing - wait for timer to increment */ /* Send the data byte */
}; UDR0 = 0xff;
nbytes--;
}
/* was the frame sent? */
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR0A, TXC0);
} }
/**************************************************************************** /****************************************************************************
+18 -7
View File
@@ -94,15 +94,26 @@ static void rs485_receiver_enable(
void rs485_turnaround_delay( void rs485_turnaround_delay(
void) void)
{ {
uint16_t turnaround_time; uint8_t nbytes = 4;
/* delay after reception before trasmitting - per MS/TP spec */ /* delay after reception before trasmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */ /* Transmit 4 dummy bytes with RS485 driver off.
/* at least 1 ms for errors: rounding, clock tick */ This equals the 40 bit times (1 start, 8 data, 1 stop). */
turnaround_time = 1 + ((Tturnaround * 1000UL) / Baud_Rate); rs485_rts_enable(false);
while (!timer_elapsed_milliseconds_short(&Silence_Timer, turnaround_time)) { while (nbytes) {
/* do nothing - wait for timer to increment */ /* Send the data byte */
}; UDR0 = 0xff;
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
nbytes--;
}
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
/* Clear the Transmit Complete flag by writing a one to it. */
BIT_SET(UCSR0A, TXC0);
} }
ISR(USART0_RX_vect) ISR(USART0_RX_vect)
+1 -1
View File
@@ -184,7 +184,7 @@ void RS485_Send_Frame(
else if (baud == 19200) else if (baud == 19200)
turnaround_time = 2; turnaround_time = 2;
else else
turnaround_time = 1; turnaround_time = 2;
while (mstp_port->SilenceTimer() < turnaround_time) { while (mstp_port->SilenceTimer() < turnaround_time) {
/* do nothing - wait for timer to increment */ /* do nothing - wait for timer to increment */
sched_yield(); sched_yield();
+1 -1
View File
@@ -78,7 +78,7 @@ void RS485_Send_Frame(
else if (RS485_Baud_Rate == 19200) else if (RS485_Baud_Rate == 19200)
turnaround_time = 2; turnaround_time = 2;
else else
turnaround_time = 1; turnaround_time = 2;
while (mstp_port->SilenceTimer < turnaround_time) { while (mstp_port->SilenceTimer < turnaround_time) {
/* The line has not been silent long enough, so wait. */ /* The line has not been silent long enough, so wait. */
+3 -2
View File
@@ -172,6 +172,7 @@ void RS485_Send_Frame(
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
bool status = true; /* return value */ bool status = true; /* return value */
/* fixme: wait turnaround time */
RS485_TRANSMIT_ENABLE(RS485_Port); RS485_TRANSMIT_ENABLE(RS485_Port);
SendBlock(RS485_Port, (char *) buffer, nbytes); SendBlock(RS485_Port, (char *) buffer, nbytes);
/* need to wait at least 9600 baud * 512 bytes = 54mS */ /* need to wait at least 9600 baud * 512 bytes = 54mS */
@@ -179,8 +180,8 @@ void RS485_Send_Frame(
while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY)) while (!(LineStatus(RS485_Port) & TX_SHIFT_EMPTY))
RTKScheduler(); RTKScheduler();
RS485_RECEIVE_ENABLE(RS485_Port); RS485_RECEIVE_ENABLE(RS485_Port);
/* SilenceTimer is cleared by the Receive State Machine when /* SilenceTimer is cleared by the Receive State Machine when
activity is detected and by the SendFrame procedure as each activity is detected and by the SendFrame procedure as each
octet is transmitted. */ octet is transmitted. */
mstp_port->SilenceTimer = 0; mstp_port->SilenceTimer = 0;
#if PRINT_ENABLED_RS485 #if PRINT_ENABLED_RS485
+1 -1
View File
@@ -383,7 +383,7 @@ void RS485_Send_Frame(
else if (baud == 19200) else if (baud == 19200)
turnaround_time = 2; turnaround_time = 2;
else else
turnaround_time = 1; turnaround_time = 2;
while (mstp_port->SilenceTimer() < turnaround_time) { while (mstp_port->SilenceTimer() < turnaround_time) {
/* do nothing - wait for timer to increment */ /* do nothing - wait for timer to increment */
}; };