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:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user