/** ----------------------------------------------------------------------------------------------------------------------- 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( ); }
/* ----------------------- Start implementation -----------------------------*/ BOOL xMBPortTimersInit( USHORT usTim1Timerout50us ) { /* Calculate overflow counter an OCR values for Timer1. */ usTimerOCRADelta = ( MB_TIMER_TICKS * usTim1Timerout50us ) / ( MB_50US_TICKS ); TCCR1A = 0x00; TCCR1B = 0x00; TCCR1C = 0x00; vMBPortTimersDisable( ); return TRUE; }
/** * @brief Timer Initialize * @param None * @retval None */ BOOL xMBPortTimersInit( USHORT usTimeOut50us ) { /* TIMx is used as Modbus timer */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; uint16_t PrescalerValue = 0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMx, ENABLE); /* Timer Config SystemCoreClock / (PrescalerValue + 1) = 20KHz (50us) Timer Count Max = usTimeOut50us */ /* Compute the prescaler value */ PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTimeOut50us; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); TIM_ARRPreloadConfig(TIMx, ENABLE); /** * @brief Configure the nested vectored interrupt controller. * @param None * @retval None */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* Enable the TIMx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIMx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); vMBPortTimersDisable(); return TRUE; }
BOOL xMBASCIIReceiveFSM( void ) { BOOL xNeedPoll = FALSE; UCHAR ucByte; UCHAR ucResult; assert( eSndState == STATE_TX_IDLE ); ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte ); switch ( eRcvState ) { /* A new character is received. If the character is a ':' the input * buffer is cleared. A CR-character signals the end of the data * block. Other characters are part of the data block and their * ASCII value is converted back to a binary representation. */ case STATE_RX_RCV: /* Enable timer for character timeout. */ vMBPortTimersEnable( ); if( ucByte == ':' ) { /* Empty receive buffer. */ eBytePos = BYTE_HIGH_NIBBLE; usRcvBufferPos = 0; } else if( ucByte == MB_ASCII_DEFAULT_CR ) { eRcvState = STATE_RX_WAIT_EOF; } else { ucResult = prvucMBCHAR2BIN( ucByte ); switch ( eBytePos ) { /* High nibble of the byte comes first. We check for * a buffer overflow here. */ case BYTE_HIGH_NIBBLE: if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX ) { ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 ); eBytePos = BYTE_LOW_NIBBLE; break; } else { /* not handled in Modbus specification but seems * a resonable implementation. */ eRcvState = STATE_RX_IDLE; /* Disable previously activated timer because of error state. */ vMBPortTimersDisable( ); } break; case BYTE_LOW_NIBBLE: ucASCIIBuf[usRcvBufferPos] |= ucResult; usRcvBufferPos++; eBytePos = BYTE_HIGH_NIBBLE; break; } } break; case STATE_RX_WAIT_EOF: if( ucByte == ucMBLFCharacter ) { /* Disable character timeout timer because all characters are * received. */ vMBPortTimersDisable( ); /* Receiver is again in idle state. */ eRcvState = STATE_RX_IDLE; /* Notify the caller of eMBASCIIReceive that a new frame * was received. */ xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED ); } else if( ucByte == ':' ) { /* Empty receive buffer and back to receive state. */ eBytePos = BYTE_HIGH_NIBBLE; usRcvBufferPos = 0; eRcvState = STATE_RX_RCV; /* Enable timer for character timeout. */ vMBPortTimersEnable( ); } else { /* Frame is not okay. Delete entire frame. */ eRcvState = STATE_RX_IDLE; } break; case STATE_RX_IDLE: if( ucByte == ':' ) { /* Enable timer for character timeout. */ vMBPortTimersEnable( ); /* Reset the input buffers to store the frame. */ usRcvBufferPos = 0;; eBytePos = BYTE_HIGH_NIBBLE; eRcvState = STATE_RX_RCV; } break; } return xNeedPoll; }