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 */
/* wait a minimum 40 bit times since reception */
/* 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) {
/* 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
* ALGORITHM: none
* NOTES: none
+29 -33
View File
@@ -44,18 +44,6 @@ static uint8_t LED3_Off_Timer;
/* baud rate */
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
* receive mode.
@@ -137,26 +125,6 @@ bool RS485_Set_Baud_Rate(
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
* 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
* RETURN: none
@@ -253,7 +250,6 @@ void RS485_Send_Data(
Timer_Silence_Reset();
}
/****************************************************************************
* DESCRIPTION: Return true if a framing or overrun error is present
* RETURN: true if error
+17 -8
View File
@@ -161,15 +161,24 @@ bool RS485_Set_Baud_Rate(
void RS485_Turnaround_Delay(
void)
{
uint16_t turnaround_time;
uint8_t nbytes = 4;
/* 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_elapsed(turnaround_time)) {
/* do nothing - wait for timer to increment */
};
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);
}
/****************************************************************************
+18 -7
View File
@@ -94,15 +94,26 @@ static void rs485_receiver_enable(
void rs485_turnaround_delay(
void)
{
uint16_t turnaround_time;
uint8_t nbytes = 4;
/* 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) / Baud_Rate);
while (!timer_elapsed_milliseconds_short(&Silence_Timer, turnaround_time)) {
/* do nothing - wait for timer to increment */
};
/* Transmit 4 dummy bytes with RS485 driver off.
This equals the 40 bit times (1 start, 8 data, 1 stop). */
rs485_rts_enable(false);
while (nbytes) {
/* 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)
+1 -1
View File
@@ -184,7 +184,7 @@ void RS485_Send_Frame(
else if (baud == 19200)
turnaround_time = 2;
else
turnaround_time = 1;
turnaround_time = 2;
while (mstp_port->SilenceTimer() < turnaround_time) {
/* do nothing - wait for timer to increment */
sched_yield();
+1 -1
View File
@@ -78,7 +78,7 @@ void RS485_Send_Frame(
else if (RS485_Baud_Rate == 19200)
turnaround_time = 2;
else
turnaround_time = 1;
turnaround_time = 2;
while (mstp_port->SilenceTimer < turnaround_time) {
/* 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) */
bool status = true; /* return value */
/* fixme: wait turnaround time */
RS485_TRANSMIT_ENABLE(RS485_Port);
SendBlock(RS485_Port, (char *) buffer, nbytes);
/* 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))
RTKScheduler();
RS485_RECEIVE_ENABLE(RS485_Port);
/* SilenceTimer is cleared by the Receive State Machine when
activity is detected and by the SendFrame procedure as each
/* SilenceTimer is cleared by the Receive State Machine when
activity is detected and by the SendFrame procedure as each
octet is transmitted. */
mstp_port->SilenceTimer = 0;
#if PRINT_ENABLED_RS485
+1 -1
View File
@@ -383,7 +383,7 @@ void RS485_Send_Frame(
else if (baud == 19200)
turnaround_time = 2;
else
turnaround_time = 1;
turnaround_time = 2;
while (mstp_port->SilenceTimer() < turnaround_time) {
/* do nothing - wait for timer to increment */
};