diff --git a/bacnet-stack/ports/atmega168/bacnet.aps b/bacnet-stack/ports/atmega168/bacnet.aps index 2d414e09..1abd57cf 100644 --- a/bacnet-stack/ports/atmega168/bacnet.aps +++ b/bacnet-stack/ports/atmega168/bacnet.aps @@ -1 +1 @@ -13-Aug-2007 15:08:2721-Aug-2007 12:07:01013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCdefault\bacnet.elfC:\code\bacnet-stack\ports\atmega168\ATmega168falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR DragonAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cdlmstp.cC:\code\bacnet-stack\crc.cC:\code\bacnet-stack\mstp.cavr035.hhardware.hrs485.htimer.hC:\code\bacnet-stack\mstp.hC:\code\bacnet-stack\crc.hC:\code\bacnet-stack\dlmstp.hdefaultNOatmega168100bacnet.elfdefault\1..\..\.\-Wall -gdwarf-2 -O0 -fsigned-char -DMAX_APDU=50 -DBACDL_MSTP -DBIG_ENDIAN=0default1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe028216193737280001100000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.c100003main.c25900004timer.c25800005C:\WinAVR-20070525\avr\include\avr\interrupt.h100006C:\WinAVR-20070525\avr\include\avr\io.h100007rs485.c25700008C:\code\bacnet-stack\mstp.c25900009dlmstp.c257755 704 915 7310 0267 695 427 7220 0906 695 1066 7220 0399 229 1253 653109 0426 695 586 7220 0427 695 587 7220 0288 119 1088 6740 0421 251 1221 675638 0465 295 1265 7190 0 +13-Aug-2007 15:08:2728-Sep-2007 16:15:28013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCbacnet.elfC:\code\bacnet-stack\ports\atmega168\ATmega168falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR DragonAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cdlmstp.cC:\code\bacnet-stack\crc.cC:\code\bacnet-stack\demo\handler\txbuf.cC:\code\bacnet-stack\iam.cC:\code\bacnet-stack\npdu.cdevice.cavr035.hhardware.hrs485.htimer.hC:\code\bacnet-stack\crc.hC:\code\bacnet-stack\dlmstp.hC:\code\bacnet-stack\demo\handler\txbuf.hC:\code\bacnet-stack\iam.hC:\code\bacnet-stack\npdu.hMakefiledefaultYESMakefileatmega168100bacnet.elfdefault\1..\..\demo\handler\.\..\..\..\..\demo\object\-Wall -gdwarf-2 -DMAX_APDU=50 -DBACDL_MSTP -DBIG_ENDIAN=0 -DF_CPU=7372800UL -O0 -fsigned-chardefault1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe0282161937372800011000001920010000000001011main100000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.c100003main.c25900004C:\WinAVR-20070525\avr\include\avr\interrupt.h100005C:\WinAVR-20070525\avr\include\avr\io.h100006C:\code\bacnet-stack\mstp.c200007rs485.c25900008dlmstp.c25800009avr035.h100010C:\code\bacnet-stack\crc.c25800011timer.c258840 433 1000 4570 0527 608 687 6320 0362 582 522 6060 0291 141 1093 565158 0746 382 906 4090 0360 611 520 6350 0354 196 1030 578140 14269 717 429 7410 0 diff --git a/bacnet-stack/ports/atmega168/dlmstp.c b/bacnet-stack/ports/atmega168/dlmstp.c index 31d6b43c..6f3cee72 100644 --- a/bacnet-stack/ports/atmega168/dlmstp.c +++ b/bacnet-stack/ports/atmega168/dlmstp.c @@ -185,13 +185,13 @@ static uint8_t TransmitPacketDest; /* that a node must wait for a station to begin replying to a */ /* confirmed request: 255 milliseconds. (Implementations may use */ /* larger values for this timeout, not to exceed 300 milliseconds.) */ -#define Treply_timeout 260 +#define Treply_timeout 295 /* The minimum time without a DataAvailable or ReceiveError event that a */ /* node must wait for a remote node to begin using a token or replying to */ /* a Poll For Master frame: 20 milliseconds. (Implementations may use */ /* larger values for this timeout, not to exceed 100 milliseconds.) */ -#define Tusage_timeout 25 +#define Tusage_timeout 95 /* The number of tokens received or used before a Poll For Master cycle */ /* is executed: 50. */ diff --git a/bacnet-stack/ports/atmega168/main.c b/bacnet-stack/ports/atmega168/main.c index de707913..33f5f8ea 100644 --- a/bacnet-stack/ports/atmega168/main.c +++ b/bacnet-stack/ports/atmega168/main.c @@ -80,7 +80,6 @@ void init(void) /* Configure USART */ RS485_Initialize(); - RS485_Set_Baud_Rate(38400); /* Configure Timer0 for millisecond timer */ Timer_Initialize(); @@ -163,7 +162,7 @@ int main(void) init(); #if defined(BACDL_MSTP) - RS485_Set_Baud_Rate(38400); + //RS485_Set_Baud_Rate(38400); dlmstp_set_max_master(127); dlmstp_set_max_info_frames(1); #endif diff --git a/bacnet-stack/ports/atmega168/rs485.c b/bacnet-stack/ports/atmega168/rs485.c index d13adb99..099deb43 100644 --- a/bacnet-stack/ports/atmega168/rs485.c +++ b/bacnet-stack/ports/atmega168/rs485.c @@ -31,7 +31,7 @@ #include #include #include -#include "mstp.h" +//#include "mstp.h" /* This file has been customized for use with ATMEGA168 */ #include "hardware.h" @@ -42,7 +42,19 @@ static uint8_t LED1_Off_Timer; static uint8_t LED3_Off_Timer; /* baud rate */ -static uint32_t RS485_Baud = 38400; +static uint32_t RS485_Baud = 9600; +/* autobaud - switch baud on errors if autobaud is true */ +static bool RS485_Autobaud = true; +/* we saw some data, so we are on an active wire */ +static uint8_t RS485_Data_Count; +/* count of errors before autobaud switching */ +static uint8_t RS485_Error_Count; +/* time limit */ +#define RS485_ERROR_TIMEOUT 1000 +/* millisecond timer to limit error window */ +static uint16_t RS485_Error_Timer = RS485_ERROR_TIMEOUT; +/* number of errors in 1000ms before autobaud switching */ +#define RS485_ERROR_LIMIT 30 /* 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. */ @@ -141,6 +153,34 @@ bool RS485_Set_Baud_Rate(uint32_t baud) return valid; } +void RS485_Next_Baud_Rate(void) +{ + uint32_t baud; + + switch (RS485_Baud) { + case 9600: + baud = 19200; + break; + case 19200: + baud = 38400; + break; + case 38400: + baud = 57600; + break; + case 57600: + baud = 76800; + break; + case 76800: + baud = 115200; + break; + case 115200: + default: + baud = 9600; + break; + } + RS485_Set_Baud_Rate(baud); +} + /**************************************************************************** * DESCRIPTION: Waits on the SilenceTimer for 40 bits. * RETURN: none @@ -201,6 +241,9 @@ void RS485_LED_Timers(void) BIT_SET(PORTD,PD7); } } + if (RS485_Error_Timer) { + RS485_Error_Timer--; + } } /**************************************************************************** @@ -263,7 +306,7 @@ void RS485_Send_Data( /**************************************************************************** * DESCRIPTION: Return true if a framing or overrun error is present * RETURN: true if error -* ALGORITHM: none +* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate * NOTES: Clears any error flags. *****************************************************************************/ bool RS485_ReceiveError(void) @@ -285,6 +328,34 @@ bool RS485_ReceiveError(void) do { dummy_data = UDR0; } while (BIT_CHECK(UCSR0A,RXC0)); + /* count errors during autobaud */ + if (RS485_Error_Count < RS485_ERROR_LIMIT) { + RS485_Error_Count++; + } else { + if (RS485_Autobaud && RS485_Error_Timer) { + /* We are in autobaud mode, and there were excessive + errors while the timer was counting down */ + RS485_Next_Baud_Rate(); + RS485_Error_Timer = RS485_ERROR_TIMEOUT; + RS485_Error_Count = 0; + } else if (RS485_Autobaud) { + /* autobaud, but timer expired */ + RS485_Autobaud = false; + } + } + } else { + if (RS485_Autobaud) { + if ((RS485_Error_Timer == 0) && (RS485_Error_Count == 0)) { + if (RS485_Data_Count > 8) { + /* no errors, timer expired, and we saw data */ + RS485_Autobaud = false; + } else { + /* no errors, timer expired, and no data*/ + RS485_Error_Timer = RS485_ERROR_TIMEOUT; + } + } + } + } return ReceiveError; @@ -305,6 +376,8 @@ bool RS485_DataAvailable(uint8_t *data) *data = UDR0; DataAvailable = true; RS485_LED1_On(); + if (RS485_Data_Count < 0xFF) + RS485_Data_Count++; } return DataAvailable;