void MainTask(void *pvParameters){ while(1){ if(!modbus_is_running){ vMBPortSerialEnable(0,0); SensorsTask(0); vMBPortSerialEnable(1,0); } ModbusTask(0); } }
eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; ENTER_CRITICAL_SECTION( ); /* Check if the receiver is still in idle state. If not we where to * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength; /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); /* Activate the transmitter. */ //发送状态转换,在中断中不断发送 eSndState = STATE_TX_XMIT; //使能发送状态,禁止接收状态 vMBPortSerialEnable( FALSE, TRUE ); }
/** * Send a ModBus frame. * @param ucSlaveAddress - Slave address to send to * @param pucFrame - Pointer to frame * @param usLength - Frame length * @return */ eMBErrorCode eMBRTUSend(UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; //printf ("Sending addr=%d cmd=%d len=%d\n", ucSlaveAddress, pucFrame[0], usLength); //printf ("rxstate = %d txstate = %d\n",eRcvState, eSndState); ENTER_CRITICAL_SECTION( ); /* Check if the receiver is still in idle state. If not, some slave * sent an unsolicited or late frame on the network. We have to abort * sending the frame. */ if(( eRcvState == STATE_RX_IDLE ) && ( eSndState == STATE_TX_IDLE )) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength; /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); //printf ("CRC=%04x\n", usCRC16); pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); /* Activate the transmitter. */ eSndState = STATE_TX_XMIT; vMBPortSerialEnable( FALSE, TRUE ); }
/** ----------------------------------------------------------------------------------------------------------------------- eMBRTUStop ----------------------------------------------------------------------------------------------------------------------- * Event Handler for GPI module * * @date DEC/02/2013 * @author FW_DEV_2 * @pre None * @return None ************************************************************************************************************************ */ void eMBRTUStop( void ) { ENTER_CRITICAL_SECTION( ); vMBPortSerialEnable( FALSE, FALSE ); vMBPortTimersDisable( ); EXIT_CRITICAL_SECTION( ); }
void eMBASCIIStop( void ) { ENTER_CRITICAL_DECLARE( ); ENTER_CRITICAL_SECTION( ); vMBPortSerialEnable( FALSE, FALSE ); vMBPortTimersDisable( ); EXIT_CRITICAL_SECTION( ); }
BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { UCHAR cfg = 0; if( ucDataBits != 8 ) { return FALSE; } switch ( eParity ) { case MB_PAR_NONE: break; case MB_PAR_ODD: cfg |= UART_PARITY_ODD; break; case MB_PAR_EVEN: cfg |= UART_PARITY_EVEN; break; default: return FALSE; } /* Baud Rate -> U0BR = (CLOCK/(16*BAUD) */ U0BRH = CLOCK / ( 16 * ulBaudRate ) >> 8; U0BRL = CLOCK / ( 16 * ulBaudRate ) & 0x00FF; /* Enable Alternate Function of UART Pins */ PAAF |= PORTA_UART_RXD | PORTA_UART_TXD; /* Disable Interrupts */ DI( ); /* Configure Stop Bits, Parity and Enable Rx/Tx */ U0CTL0 = cfg | RX_ENABLE | TX_ENABLE; U0CTL1 = 0x00; /* Low Priority Rx/Tx Interrupts */ IRQ0ENH &= ~UART0_TXD_INT_EN_H & ~UART0_RXD_INT_EN_H; vMBPortSerialEnable( FALSE, FALSE ); /* Set Rx/Tx Interruption Vectors */ SET_VECTOR( UART0_RX, prvvUARTRxISR ); SET_VECTOR( UART0_TX, prvvUARTTxReadyISR ); /* Enable Interrupts */ EI( ); return TRUE; }
void eMBASCIIStart( void ) { ENTER_CRITICAL_SECTION( ); vMBPortSerialEnable( TRUE, FALSE ); eRcvState = STATE_RX_IDLE; EXIT_CRITICAL_SECTION( ); /* No special startup required for ASCII. */ ( void )xMBPortEventPost( EV_READY ); }
BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { UCHAR ucUCSRC = 0; /* prevent compiler warning. */ (void)ucPORT; UBRR = UART_BAUD_CALC( ulBaudRate, F_CPU ); switch ( eParity ) { case MB_PAR_EVEN: ucUCSRC |= _BV( UPM1 ); break; case MB_PAR_ODD: ucUCSRC |= _BV( UPM1 ) | _BV( UPM0 ); break; case MB_PAR_NONE: break; } switch ( ucDataBits ) { case 8: ucUCSRC |= _BV( UCSZ0 ) | _BV( UCSZ1 ); break; case 7: ucUCSRC |= _BV( UCSZ1 ); break; } #if defined (__AVR_ATmega168__) UCSRC |= ucUCSRC; #elif defined (__AVR_ATmega169__) UCSRC |= ucUCSRC; #elif defined (__AVR_ATmega8__) UCSRC = _BV( URSEL ) | ucUCSRC; #elif defined (__AVR_ATmega16__) UCSRC = _BV( URSEL ) | ucUCSRC; #elif defined (__AVR_ATmega32__) UCSRC = _BV( URSEL ) | ucUCSRC; #elif defined (__AVR_ATmega128__) UCSRC |= ucUCSRC; #endif vMBPortSerialEnable( FALSE, FALSE ); #ifdef RTS_ENABLE RTS_INIT; #endif return TRUE; }
/* Create an interrupt handler for the transmit buffer empty interrupt * (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character. */ interrupt void prvvUARTTxReadyISR( void ) { static unsigned int uiCnt = 0; #if (TEST == TEST_TX) if(uiCnt++ < 10) xMBPortSerialPutByte('a'); else vMBPortSerialEnable(false,false); #elif (TEST == NO_TEST) pxMBFrameCBTransmitterEmpty( ); #endif PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack }
/** ----------------------------------------------------------------------------------------------------------------------- eMBRTUSend ----------------------------------------------------------------------------------------------------------------------- * Send RTU Frame * * @date DEC/02/2013 * @author FW_DEV_2 * @pre None * @return None ************************************************************************************************************************ */ eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; int i =0; ENTER_CRITICAL_SECTION( ); printf("Inside eMBRTUSend\n"); /*for(i=0;i<usLength;i++) { printf("Sending data is %x\n",*pucFrame++); }*/ /* Check if the receiver is still in idle state. If not we where to * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; //printf("pucSndBufferCur data is %x\n",*pucSndBufferCur); usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ //pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; //pucSndBufferCur[MB_SER_PDU_PDU_OFF] = pucFrame[0]; //pucSndBufferCur[MB_SER_PDU_PDU_OFF+1] = pucFrame[1]; //pucSndBufferCur[MB_SER_PDU_PDU_OFF+2] = pucFrame[2]; usSndBufferCount += (usLength); /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 ); //ucRTUBuf[usSndBufferCount] = '\0'; //usSndBufferCount = 8; //printf("Buffer count is %d\n",usSndBufferCount); /* Activate the transmitter. */ eSndState = STATE_TX_XMIT; //vMBPortSerialEnable( FALSE, TRUE ); vMBPortSerialEnable( FALSE, FALSE ); xMBRTUTransmitFSM(); }
void eMBRTUStart( void ) { ENTER_CRITICAL_SECTION( ); /* Initially the receiver is in the state STATE_RX_INIT. we start * the timer and if no character is received within t3.5 we change * to STATE_RX_IDLE. This makes sure that we delay startup of the * modbus protocol stack until the bus is free. */ eRcvState = STATE_RX_INIT; vMBPortSerialEnable( TRUE, FALSE ); vMBPortTimersEnable( ); EXIT_CRITICAL_SECTION( ); }
BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) { UCHAR ucUCSRC = 0; /* prevent compiler warning. */ (void) ucPORT; // set computed value by util/setbaud.h UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; #if USE_2X UCSR0A |= (1<<U2X0); #else UCSR0A &= ~(1 << U2X0); #endif switch (eParity) { case MB_PAR_EVEN: ucUCSRC |= _BV(UPM01); break; case MB_PAR_ODD: ucUCSRC |= _BV( UPM01 ) | _BV(UPM00); break; case MB_PAR_NONE: break; } switch (ucDataBits) { case 8: ucUCSRC |= _BV( UCSZ00 ) | _BV(UCSZ01); break; case 7: ucUCSRC |= _BV(UCSZ01); break; } UCSR0C |= ucUCSRC; vMBPortSerialEnable( FALSE, FALSE); #ifdef RTS_ENABLE RTS_INIT; #endif return TRUE; }
/** * Start ModBus master */ void eMBRTUStart(void) { DEBUG_PUTSTRING("MODBUS Start"); ENTER_CRITICAL_SECTION( ); /* Initially the receiver is in the state STATE_RX_INIT. we start * the timer and if no character is received within t3.5 we change * to STATE_RX_IDLE. This makes sure that we delay startup of the * modbus protocol stack until the bus is free. */ eRcvState = STATE_RX_INIT; vMBPortSerialEnable( TRUE, FALSE ); vMBPortTimersEnable( ); EXIT_CRITICAL_SECTION( ); /* Give the target an initial kick */ xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); xMBPortSerialPutByte(0); sleep(2); }
eMBErrorCode eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; UCHAR usLRC; ENTER_CRITICAL_DECLARE( ); ENTER_CRITICAL_SECTION( ); /* Check if the receiver is still in idle state. If not we where too * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1; /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength; /* Calculate LRC checksum for Modbus-Serial-Line-PDU. */ usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucASCIIBuf[usSndBufferCount++] = usLRC; /* Activate the transmitter. */ eSndState = STATE_TX_START; vMBPortSerialEnable( FALSE, TRUE ); } else { eStatus = MB_EIO; } EXIT_CRITICAL_SECTION( ); return eStatus; }
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { BOOL xResult = TRUE; UARTParity_TypeDef eUARTParity; UARTMode_TypeDef eUARTMode; (void)ucPort; switch ( eParity ) { case MB_PAR_EVEN: eUARTParity = UART_EVEN_PARITY; break; case MB_PAR_ODD: eUARTParity = UART_ODD_PARITY; break; case MB_PAR_NONE: eUARTParity = UART_NO_PARITY; break; } switch ( ucDataBits ) { case 7: if( eParity == MB_PAR_NONE ) { /* not supported by our hardware. */ xResult = FALSE; } else { eUARTMode = UARTM_7D_P; } break; case 8: if( eParity == MB_PAR_NONE ) { eUARTMode = UARTM_8D; } else { eUARTMode = UARTM_8D_P; } break; default: xResult = FALSE; } if( xResult != FALSE ) { /* Setup the UART port pins. */ GPIO_Config( MB_UART_TX_PORT, 1 << MB_UART_TX_PIN, GPIO_AF_PP ); GPIO_Config( MB_UART_RX_PORT, 1 << MB_UART_RX_PIN, GPIO_IN_TRI_CMOS ); /* Configure the UART. */ UART_OnOffConfig( MB_UART_DEV, ENABLE ); UART_FifoConfig( MB_UART_DEV, DISABLE ); UART_FifoReset( MB_UART_DEV, UART_RxFIFO ); UART_FifoReset( MB_UART_DEV, UART_TxFIFO ); UART_LoopBackConfig( MB_UART_DEV, DISABLE ); UART_Config( MB_UART_DEV, ulBaudRate, eUARTParity, UART_1_StopBits, eUARTMode ); UART_RxConfig( UART0, ENABLE ); vMBPortSerialEnable( FALSE, FALSE ); /* Configure the IEC for the UART interrupts. */ EIC_IRQChannelPriorityConfig( MB_UART_IRQ_CH, MB_IRQ_PRIORITY ); EIC_IRQChannelConfig( MB_UART_IRQ_CH, ENABLE ); } return xResult; }
BOOL xMBASCIITransmitFSM( void ) { BOOL xNeedPoll = FALSE; UCHAR ucByte; assert( eRcvState == STATE_RX_IDLE ); switch ( eSndState ) { /* Start of transmission. The start of a frame is defined by sending * the character ':'. */ case STATE_TX_START: ucByte = ':'; xMBPortSerialPutByte( ( CHAR )ucByte ); eSndState = STATE_TX_DATA; eBytePos = BYTE_HIGH_NIBBLE; break; /* Send the data block. Each data byte is encoded as a character hex * stream with the high nibble sent first and the low nibble sent * last. If all data bytes are exhausted we send a '\r' character * to end the transmission. */ case STATE_TX_DATA: if( usSndBufferCount > 0 ) { switch ( eBytePos ) { case BYTE_HIGH_NIBBLE: ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) ); xMBPortSerialPutByte( ( CHAR ) ucByte ); eBytePos = BYTE_LOW_NIBBLE; break; case BYTE_LOW_NIBBLE: ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) ); xMBPortSerialPutByte( ( CHAR )ucByte ); pucSndBufferCur++; eBytePos = BYTE_HIGH_NIBBLE; usSndBufferCount--; break; } } else { xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR ); eSndState = STATE_TX_END; } break; /* Finish the frame by sending a LF character. */ case STATE_TX_END: xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter ); /* We need another state to make sure that the CR character has * been sent. */ eSndState = STATE_TX_NOTIFY; break; /* Notify the task which called eMBASCIISend that the frame has * been sent. */ case STATE_TX_NOTIFY: eSndState = STATE_TX_IDLE; xNeedPoll = xMBPortEventPost( EV_FRAME_SENT ); /* Disable transmitter. This prevents another transmit buffer * empty interrupt. */ vMBPortSerialEnable( TRUE, FALSE ); eSndState = STATE_TX_IDLE; break; /* We should not get a transmitter event if the transmitter is in * idle state. */ case STATE_TX_IDLE: /* enable receiver/disable transmitter. */ vMBPortSerialEnable( TRUE, FALSE ); break; }
BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { (void)ucPORT; ENTER_CRITICAL_SECTION( ); PieVectTable.SCIRXINTA = &prvvUARTRxISR; PieVectTable.SCITXINTA = &prvvUARTTxReadyISR; SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback // No parity,8 char bits, // async mode, idle-line protocol SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK, // Disable RX ERR, SLEEP, TXWAKE SciaRegs.SCIFFTX.bit.SCIFFENA = 0; //UCDATABITS SETTINGS ------------------------------------------- switch(ucDataBits){ case 8: SciaRegs.SCICCR.bit.SCICHAR = 0x7; break; case 7: SciaRegs.SCICCR.bit.SCICHAR = 0x6; break; default: SciaRegs.SCICCR.bit.SCICHAR = 0x7; } //EPARITY SETTINGS ---------------------------------------------- switch(eParity){ case MB_PAR_EVEN: SciaRegs.SCICCR.bit.PARITYENA = 1; SciaRegs.SCICCR.bit.PARITY = 1; break; case MB_PAR_ODD: SciaRegs.SCICCR.bit.PARITYENA = 1; SciaRegs.SCICCR.bit.PARITY = 0; break; case MB_PAR_NONE: SciaRegs.SCICCR.bit.PARITYENA = 0; break; default: SciaRegs.SCICCR.bit.PARITYENA = 0; } //ULBAUDRATE SETTINGS ------------------------------------------- #if (CPU_FRQ_150MHZ) SciaRegs.SCIHBAUD =0x0001; // 9600 baud @LSPCLK = 37.5MHz. SciaRegs.SCILBAUD =0x00E7; #endif #if (CPU_FRQ_100MHZ) SciaRegs.SCIHBAUD =0x0001; // 9600 baud @LSPCLK = 20MHz. SciaRegs.SCILBAUD =0x0044; #endif PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER9.bit.INTx1=1; // PIE Group 9, int1 PieCtrlRegs.PIEIER9.bit.INTx2=1; // PIE Group 9, INT2 //IER = 0x100; // Enable CPU INT IER |= M_INT9; // Enable CPU INT SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset vMBPortSerialEnable( FALSE, FALSE ); EXIT_CRITICAL_SECTION( ); return TRUE; }
void main( void ) { eMBErrorCode eStatus; /* Use external 32.768 Hz crystal to generate 4.194.304 Hz bus clock */ ICGC1 = 0x38; // ??=0,RANGE=0,REFS=1,CLKS=1:1,OSCSTEN=0,??=0:0 while( ICGS2_DCOS == 0 ); #if 0 /* Test code for porting */ #if 1 /* Timer test * Comment out call to pxMBPortCBTimerExpired() in prvvTIMERExpiredISR when testing the timer */ /* Disable the COP watchdog */ SOPT = 0x53; // COPE=0,COPT=1,STOPE=0,??=1:0:0,BKGDPE=1,??=1 ( void )xMBPortTimersInit( 20000 ); EnableInterrupts; for( ;; ) { vMBPortTimersEnable( ); _Wait; // wait for an interrupt /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; PTFDD_PTFDD0 = 1; } #else /* Receiver test * Comment out call to pxMBFrameCBByteReceived() in prvvUARTRxISR() when testing the receiver */ /* Disable the COP watchdog */ SOPT = 0x53; // COPE=0,COPT=1,STOPE=0,??=1:0:0,BKGDPE=1,??=1 /* Enable the receiver. */ assert( xMBPortSerialInit( 0, 9600, 8, MB_PAR_NONE ) ); EnableInterrupts; for( ;; ) { UCHAR ucByte; vMBPortSerialEnable( TRUE, FALSE ); _Wait; // wait for an interrupt assert( xMBPortSerialGetByte( &ucByte ) ); /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; PTFDD_PTFDD0 = 1; /* Transmitter test * Comment out call to pxMBFrameCBTransmitterEmpty() in prvvUARTTxReadyISR() when testing the transmitter */ #if 0 vMBPortSerialEnable( FALSE, TRUE ); assert( xMBPortSerialPutByte( ucByte ) ); _Wait; // wait for an interrupt /* toggle LED1 */ PTFD_PTFD0 = !PTFD_PTFD0; #endif // Transmitter test } #endif // Receiver test #else /* Demo * NOTE: Make sure the callbacks in the three ISPs have been restored after above testing */ /* Initialization */ eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN ); // eStatus = eMBInit( MB_ASCII, 0x0A, 0, 38400, MB_PAR_EVEN ); /* Enable the Modbus Protocol Stack. */ eStatus = eMBEnable( ); /* Start polling */ EnableInterrupts; for( ;; ) { /* Poll for Modbus events */ ( void )eMBPoll( ); /* Count the number of polls */ usRegInputBuf[0]++; /* Count the number of timer overflows */ if( TPM1SC_TOF ) { TPM1SC_TOF = 0; ENTER_CRITICAL_SECTION( ); if( ++usRegInputBuf[1] == 0 ) // Happens every 2 seconds usRegInputBuf[2]++; // Happens every 36.4 hours EXIT_CRITICAL_SECTION( ); } /* Keep the COP watchdog happy */ __RESET_WATCHDOG( ); } #endif // Test code when porting }
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { CHAR szDevice[16]; BOOL bStatus = TRUE; struct termios xNewTIO; speed_t xNewSpeed; if(ucPort != 255) { snprintf( szDevice, 16, "/dev/ttyS%d", ucPort ); } else { snprintf( szDevice, 16, "%s", devString ); } if( ( iSerialFd = open( szDevice, O_RDWR | O_NOCTTY ) ) < 0 ) { vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't open serial port %s: %s\n", szDevice, strerror( errno ) ); bStatus = FALSE; } else if( tcgetattr( iSerialFd, &xOldTIO ) != 0 ) { vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't get settings from port %s: %s\n", szDevice, strerror( errno ) ); bStatus = FALSE; } else { bzero( &xNewTIO, sizeof( struct termios ) ); xNewTIO.c_iflag |= IGNBRK | INPCK; xNewTIO.c_cflag |= CREAD | CLOCAL; switch ( eParity ) { case MB_PAR_NONE: break; case MB_PAR_EVEN: xNewTIO.c_cflag |= PARENB; break; case MB_PAR_ODD: xNewTIO.c_cflag |= PARENB | PARODD; break; default: bStatus = FALSE; } switch ( ucDataBits ) { case 8: xNewTIO.c_cflag |= CS8; break; case 7: xNewTIO.c_cflag |= CS7; break; default: bStatus = FALSE; } switch ( ulBaudRate ) { case 9600: xNewSpeed = B9600; break; case 19200: xNewSpeed = B19200; break; case 38400: xNewSpeed = B38400; break; case 57600: xNewSpeed = B57600; break; case 115200: xNewSpeed = B115200; break; default: bStatus = FALSE; } if( bStatus ) { if( cfsetispeed( &xNewTIO, xNewSpeed ) != 0 ) { vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %s\n", ulBaudRate, strerror( errno ) ); } else if( cfsetospeed( &xNewTIO, xNewSpeed ) != 0 ) { vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %s\n", ulBaudRate, szDevice, strerror( errno ) ); } else if( tcsetattr( iSerialFd, TCSANOW, &xNewTIO ) != 0 ) { vMBPortLog( MB_LOG_ERROR, "SER-INIT", "Can't set settings for port %s: %s\n", szDevice, strerror( errno ) ); } else { vMBPortSerialEnable( FALSE, FALSE ); bStatus = TRUE; } } } return bStatus; }
BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { TCHAR szDevice[8]; BOOL bStatus = TRUE; DCB dcb; memset( &dcb, 0, sizeof( dcb ) ); dcb.DCBlength = sizeof( dcb ); dcb.BaudRate = ulBaudRate; _stprintf_s( szDevice, 8, _T( "COM%d" ), ucPort ); switch ( eParity ) { case MB_PAR_NONE: dcb.Parity = NOPARITY; dcb.fParity = 0; break; case MB_PAR_EVEN: dcb.Parity = EVENPARITY; dcb.fParity = 1; break; case MB_PAR_ODD: dcb.Parity = ODDPARITY; dcb.fParity = 1; break; default: bStatus = FALSE; } switch ( ucDataBits ) { case 8: dcb.ByteSize = 8; break; case 7: dcb.ByteSize = 7; break; default: bStatus = FALSE; } if( bStatus ) { /* we don't use XON/XOFF flow control. */ dcb.fInX = dcb.fOutX = FALSE; /* we don't need hardware handshake. */ dcb.fOutxCtsFlow = dcb.fOutxCtsFlow = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fDtrControl = DTR_CONTROL_ENABLE; /* misc parameters */ dcb.fErrorChar = FALSE; dcb.fBinary = TRUE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; /* Open the serial device. */ g_hSerial = CreateFile( szDevice, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if( g_hSerial == INVALID_HANDLE_VALUE ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't open serial port %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else if( !SetCommState( g_hSerial, &dcb ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't set settings for serial device %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else if( !SetCommMask( g_hSerial, 0 ) ) { vMBPortLog( MB_LOG_ERROR, _T( "SER-INIT" ), _T( "Can't set communication event mask for serial device %s: %s" ), szDevice, Error2String( GetLastError( ) ) ); bStatus = FALSE; } else { vMBPortSerialEnable( FALSE, FALSE ); bStatus = TRUE; } } return bStatus; }
// ------------------------------------------------------------------------------ BOOL xMBPortSerialInit (UCHAR ucPORT __attribute__ ( (unused)), ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) { LONG lUBRR; UCHAR ucUCSRC = UCSRC_SEL; switch (eParity) { case MB_PAR_EVEN: ucUCSRC |= _BV (UPM1); break; case MB_PAR_ODD: ucUCSRC |= _BV (UPM1) | _BV (UPM0); break; case MB_PAR_NONE: ucUCSRC |= _BV (USBS); // Remark : the use of no parity requires 2 stop bits. break; default: return FALSE; } switch (ucDataBits) { case 8: ucUCSRC |= _BV (UCSZ0) | _BV (UCSZ1); break; case 7: ucUCSRC |= _BV (UCSZ1); break; default: return FALSE; } UCSRC = ucUCSRC; #if defined(AVRIO_SERIAL_BAUD_USE_X2) // Utilisation exclusive de X2 lUBRR = SERIAL_BAUD_X2 (ulBaudRate); UCSRA |= _BV (U2X); #else lUBRR = SERIAL_BAUD_X1 (ulBaudRate); if (lUBRR <= 0) { lUBRR = SERIAL_BAUD_X2 (ulBaudRate); UCSRA |= _BV (U2X); } #endif if ( (lUBRR <= 0) || (lUBRR > 65535)) { return FALSE; } UBRRL = lUBRR & 0xFF; UBRRH = lUBRR >> 8; vTxEnInit (); vMBLedInit(); vMBLedErrInit (); vMBLedComInit (); vMBPortSerialEnable (FALSE, FALSE); READY_SET (); return TRUE; }
bool xMBPortSerialInit(uint8_t ucPort, speed_t ulBaudRate, uint8_t ucDataBits, eMBParity eParity) { char szDevice[16]; bool bStatus = true; #ifdef CONFIG_SERIAL_TERMIOS struct termios xNewTIO; #endif snprintf(szDevice, 16, "/dev/ttyS%d", ucPort); if ((iSerialFd = open(szDevice, O_RDWR | O_NOCTTY)) < 0) { vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't open serial port %s: %d\n", szDevice, errno); } #ifdef CONFIG_SERIAL_TERMIOS else if (tcgetattr(iSerialFd, &xOldTIO) != 0) { vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't get settings from port %s: %d\n", szDevice, errno); } else { bzero(&xNewTIO, sizeof(struct termios)); xNewTIO.c_iflag |= IGNBRK | INPCK; xNewTIO.c_cflag |= CREAD | CLOCAL; switch (eParity) { case MB_PAR_NONE: break; case MB_PAR_EVEN: xNewTIO.c_cflag |= PARENB; break; case MB_PAR_ODD: xNewTIO.c_cflag |= PARENB | PARODD; break; default: bStatus = false; } switch (ucDataBits) { case 8: xNewTIO.c_cflag |= CS8; break; case 7: xNewTIO.c_cflag |= CS7; break; default: bStatus = false; } if (bStatus) { /* Set the new baud. The following might be compatible with other * OSs for the following reason. * * (1) In NuttX, cfset[i|o]speed always return OK so failures will * really only be reported when tcsetattr() is called. * (2) NuttX does not support separate input and output speeds so it * is not necessary to call both cfsetispeed() and * cfsetospeed(), and * (3) In NuttX, the input value to cfiset[i|o]speed is not * encoded, but is the absolute baud value. The following might * not be */ if (cfsetispeed(&xNewTIO, ulBaudRate) != 0 /* || cfsetospeed(&xNewTIO, ulBaudRate) != 0 */) { vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't set baud rate %ld for port %s: %d\n", ulBaudRate, szDevice, errno); } else if (tcsetattr(iSerialFd, TCSANOW, &xNewTIO) != 0) { vMBPortLog(MB_LOG_ERROR, "SER-INIT", "Can't set settings for port %s: %d\n", szDevice, errno); } else { vMBPortSerialEnable(false, false); bStatus = true; } } } #endif return bStatus; }