OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4555|回复: 5

FreeModbus 移植文件出问题了 求帮助

[复制链接]

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
发表于 2019-1-23 11:16:38 | 显示全部楼层 |阅读模式
2金钱
移植了MODBUS
可是用MODBUS POLL连接显示一直是timeout error
希望有大佬帮忙看看代码
不知道问题出在了哪!求帮助
谢谢啦


参考连接1:http://www.openedv.com/forum.php ... mp;highlight=MODBUS
参考链接2:https://www.a_m_o_bbs.com/forum.php?mod=viewthread&tid=5491615&extra=&highlight=freemodbus&page=1

0190123111153.png

MODBUS测试.rar

8.66 MB, 下载次数: 14

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
 楼主| 发表于 2019-1-23 11:20:27 | 显示全部楼层
portserial.c文件:
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "rs485.h"
/* ----------------------- static functions ---------------------------------*/
static void prvvUARTTxReadyISR( void );
static void prvvUARTRxISR( void );
/* ----------------------- Start implementation -----------------------------*/
/**
* @brief 控制接收和发送状态
* @param xRxEnable 接收使能、
* xTxEnable 发送使能
* @retval None
*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{

if(xRxEnable)
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
//使能接收和接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
//MAX485操作 低电平为接收模式
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
else
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
//MAX485操作 高电平为发送模式
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}

if(xTxEnable)
{
//使能发送完成中断
USART_ITConfig(USART2, USART_IT_TC, ENABLE);
        GPIO_SetBits(GPIOD,GPIO_Pin_2);
//prvvUARTTxReadyISR();
}
else
{
//禁止发送完成中断
USART_ITConfig(USART2, USART_IT_TC, DISABLE);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}

}
/**
* @brief 串口初始化
* @param ucPORT 串口号
* ulBaudRate 波特率
* ucDataBits 数据位
* eParity 校验位
* @retval None
*/
BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
(void)ucPORT; //不修改串口
(void)ucDataBits; //不修改数据位长度
(void)eParity; //不修改校验格式

GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

//使能USART2,GPIOA
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA,D时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟

//GPIOA2 USART2_Tx
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIOA.3 USART2_Rx
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮动输入
GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = ulBaudRate; //只修改波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
//USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
switch(eParity)
    {
    case MB_PAR_NONE:USART_InitStructure.USART_Parity = USART_Parity_No;
                USART_InitStructure.USART_WordLength = USART_WordLength_8b;
                break;
    case MB_PAR_ODD:USART_InitStructure.USART_Parity = USART_Parity_Odd;
                USART_InitStructure.USART_WordLength = USART_WordLength_9b;
                break;
    case MB_PAR_EVEN:USART_InitStructure.USART_Parity = USART_Parity_Even;
                USART_InitStructure.USART_WordLength = USART_WordLength_9b;
                break;
    default:break;
    }


//串口初始化
USART_Init(USART2, &USART_InitStructure);
//使能USART2
USART_Cmd(USART2, ENABLE);
//vMBPortSerialEnable(FALSE,FALSE);
//USART_ClearFlag(USART2,USART_FLAG_TC);
       
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//设定USART2 中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//最后配置485发送和接收模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
//GPIOD.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);

return TRUE;
}



/*xMBPortSerialPutByte和xMBPortSerialGetByte两个函数用于串口发送和接收数据,在这里只要调用STM32的库函数即可。*/
BOOL
xMBPortSerialPutByte( CHAR ucByte )
{
        //发送数据
USART_SendData(USART2, ucByte);
while(USART_GetFlagStatus(USART2,USART_FLAG_TC) != SET);
return TRUE;
}

BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{
           //接受数据
        *pucByte = USART_ReceiveData(USART2);
    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.
*/
static void prvvUARTTxReadyISR( void )
{
//mb.c eMBInit函数中
//pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM
//发送状态机
pxMBFrameCBTransmitterEmpty();
}

/* Create an interrupt handler for the receive interrupt for your target
* processor. This function should then call pxMBFrameCBByteReceived( ). The
* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
* character.
*/
/*FreeModbus协议栈通过串口中断接收一帧数据,用户需在串口接收中断中回调prvvUARTRxISR()函数;*/
static void prvvUARTRxISR( void )
{
//mb.c eMBInit函数中
//pxMBFrameCBByteReceived = xMBRTUReceiveFSM
//接收状态机
pxMBFrameCBByteReceived();
}


void USART2_IRQHandler(void)
{
//发生接收中断
if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
prvvUARTRxISR();
//清除中断标志位
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}

//发生完成中断
if(USART_GetITStatus(USART2, USART_IT_TC)== SET)
{
prvvUARTTxReadyISR();
//清除中断标志
USART_ClearITPendingBit(USART2, USART_IT_TC);
}
}

void
EnterCriticalSection( void )
{
  __disable_irq();
}

void
ExitCriticalSection( void )
{
  __enable_irq();
}


回复

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
 楼主| 发表于 2019-1-23 11:21:07 | 显示全部楼层
porttimer.c文件/* ----------------------- Platform includes --------------------------------*/
#include "port.h"
#include "stm32f10x_tim.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"

/* ----------------------- static functions ---------------------------------*/
static void prvvTIMERExpiredISR( void );
/*
初始化时钟xMBPortTimersInit()
添加打开和关闭时钟的函数void vMBPortTimersEnable(  )
以及voidvMBPortTimersDisable(  ),
还有超时中断函数voidTIM2_IRQHandler(void)。
*/
/* ----------------------- Start implementation -----------------------------*/
BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

        TIM_DeInit(TIM2); //重新将Timer3设置为缺省值
  uint16_t PrescalerValue = 0;

  //使能定时器2时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能

  //定时器时间基配置说明
  //系统时钟为72MHz,APB1经过2分频为36MHz
  //TIM2的时钟倍频后为72MHz(硬件自动倍频,达到最大)
  //TIM2的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us
  //TIM最大计数值为usTim1Timerout50us
  PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1;
  //定时器1初始化
  TIM_TimeBaseStructure.TIM_Period = (uint16_t) usTim1Timerout50us;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  //预装载使能
  TIM_ARRPreloadConfig(TIM2, ENABLE);

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  //定时器2中断优先级
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  //清除溢出中断标志位
  TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
  //定时器2溢出中断关闭
  TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
  //定时器2禁能
  TIM_Cmd(TIM2,  DISABLE);
  return TRUE;
}


inline void
vMBPortTimersEnable(  )
{
       
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  //设定定时器2的初始值
  TIM_SetCounter(TIM2,0x0000);
  //定时器2启动
  TIM_Cmd(TIM2, ENABLE);
       
  /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
}

inline void
vMBPortTimersDisable(  )
{
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
  TIM_SetCounter(TIM2,0x0000);
  //关闭定时器2
  TIM_Cmd(TIM2, DISABLE);
  /* Disable any pending timers. */
}

/* Create an ISR which is called whenever the timer has expired. This function
* must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that
* the timer has expired.
*/
static void prvvTIMERExpiredISR( void )
{
    ( void )pxMBPortCBTimerExpired(  );
}

void TIM2_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  {
    //清除定时器T4溢出中断标志位
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

    prvvTIMERExpiredISR( );
  }
}




回复

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
 楼主| 发表于 2019-1-23 11:21:51 | 显示全部楼层
mbrtu.c 文件
/* ----------------------- System includes ----------------------------------*/
#include "stdlib.h"
#include "string.h"

/* ----------------------- Platform includes --------------------------------*/
#include "port.h"

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbrtu.h"
#include "mbframe.h"

#include "mbcrc.h"
#include "mbport.h"

/* ----------------------- Defines ------------------------------------------*/
#define MB_SER_PDU_SIZE_MIN     4       /*!< Minimum size of a Modbus RTU frame. */
#define MB_SER_PDU_SIZE_MAX     256     /*!< Maximum size of a Modbus RTU frame. */
#define MB_SER_PDU_SIZE_CRC     2       /*!< Size of CRC field in PDU. */
#define MB_SER_PDU_ADDR_OFF     0       /*!< Offset of slave address in Ser-PDU. */
#define MB_SER_PDU_PDU_OFF      1       /*!< Offset of Modbus-PDU in Ser-PDU. */

/* ----------------------- Type definitions ---------------------------------*/
typedef enum
{
    STATE_RX_INIT,              /*!< Receiver is in initial state. */
    STATE_RX_IDLE,              /*!< Receiver is in idle state. */
    STATE_RX_RCV,               /*!< Frame is beeing received. */
    STATE_RX_ERROR              /*!< If the frame is invalid. */
} eMBRcvState;

typedef enum
{
    STATE_TX_IDLE,              /*!< Transmitter is in idle state. */
    STATE_TX_XMIT               /*!< Transmitter is in transfer state. */
} eMBSndState;

/* ----------------------- Static variables ---------------------------------*/
static volatile eMBSndState eSndState;
static volatile eMBRcvState eRcvState;

volatile UCHAR  ucRTUBuf[MB_SER_PDU_SIZE_MAX];

static volatile UCHAR *pucSndBufferCur;
static volatile USHORT usSndBufferCount;

static volatile USHORT usRcvBufferPos;

/* ----------------------- Start implementation -----------------------------*/


eMBErrorCode eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    ULONG           usTimerT35_50us;

    ( void )ucSlaveAddress;
    ENTER_CRITICAL_SECTION(  );

    /* Modbus RTU uses 8 Databits. */
    if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE )
    {
        eStatus = MB_EPORTERR;
    }
    else
    {
        /* If baudrate > 19200 then we should use the fixed timer values
         * t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
         */
        if( ulBaudRate > 19200 )
        {
            usTimerT35_50us = 35;       /* 1800us. */
        }
        else
        {
            /* The timer reload value for a character is given by:
             *
             * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
             *             = 11 * Ticks_per_1s / Baudrate
             *             = 220000 / Baudrate
             * The reload for t3.5 is 1.5 times this value and similary
             * for t3.5.
             */
            usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );
        }
        if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
        {
            eStatus = MB_EPORTERR;
        }
    }
    EXIT_CRITICAL_SECTION(  );

    return eStatus;
}

/*函数功能
*1:设置接收状态机eRcvState为STATE_RX_INIT;
*2:使能串口接收,禁止串口发送,作为从机,等待主机传送的数据;
*3:开启定时器,3.5T时间后定时器发生第一次中断,此时eRcvState为STATE_RX_INIT,上报初始化完成事件,然后设置eRcvState为空闲STATE_RX_IDLE;
*4:每次进入3.5T定时器中断,定时器被禁止,等待串口有字节接收后,才使能定时器;
*/
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(  );
}

void
eMBRTUStop( void )
{
    ENTER_CRITICAL_SECTION(  );
    vMBPortSerialEnable( FALSE, FALSE );
    vMBPortTimersDisable(  );
    EXIT_CRITICAL_SECTION(  );
}
/*eMBPoll函数轮询到EV_FRAME_RECEIVED事件时,调用peMBFrameReceiveCur(),此函数是用户为函数指针peMBFrameReceiveCur()的赋值
*此函数完成的功能:从一帧数据报文中,取得modbus从机地址给pucRcvAddress,PDU报文的长度给pusLength,PDU报文的首地址给pucFrame,函数
*形参全部为地址传递*/
eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
{
    BOOL            xFrameReceived = FALSE;
    eMBErrorCode    eStatus = MB_ENOERR;

    ENTER_CRITICAL_SECTION(  );
    assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );/*断言宏,判断接收到的字节数<256,如果>256,终止程序*/

    /* Length and CRC check */
    if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )  && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) )
    {
        /* Save the address field. All frames are passed to the upper layed  and the decision if a frame is used is done there.
         */
        *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF];

        /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
         * size of address field and CRC checksum.
         */
        *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );

        /* Return the start of the Modbus PDU to the caller. */
        *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF];
        xFrameReceived = TRUE;
    }
    else
    {
        eStatus = MB_EIO;
    }

    EXIT_CRITICAL_SECTION(  );
    return eStatus;
}
/*函数功能
*1:对响应报文PDU前面加上从机地址;
*2:对响应报文PDU后加上CRC校;
*3:使能发送,启动传输;
*/
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.
     */
        //判断主机状态 IDLE为空闲状态
    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;
               
               
                //插入代码 启动第一次发送,这样才可以进入发送完成中断
                xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
                pucSndBufferCur++;
                usSndBufferCount--;
               
        vMBPortSerialEnable( FALSE, TRUE ); /*使能发送,禁止接收*/
    }
    else
    {
        eStatus = MB_EIO;
    }
    EXIT_CRITICAL_SECTION(  );
    return eStatus;
}

BOOL xMBRTUReceiveFSM( void )
{
    BOOL            xTaskNeedSwitch = FALSE;
    UCHAR           ucByte;

    assert( eSndState == STATE_TX_IDLE ); /*确保没有数据在发送*/

    /* Always read the character. */
    ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );

    switch ( eRcvState )
    {
        /* If we have received a character in the init state we have to
         * wait until the frame is finished.
         */
    case STATE_RX_INIT:
        vMBPortTimersEnable(  );
        break;

        /* In the error state we wait until all characters in the
         * damaged frame are transmitted.
         */
    case STATE_RX_ERROR:
        vMBPortTimersEnable(  );
        break;

        /* In the idle state we wait for a new character. If a character
         * is received the t1.5 and t3.5 timers are started and the
         * receiver is in the state STATE_RX_RECEIVCE.
         */
    case STATE_RX_IDLE:
        usRcvBufferPos = 0;
        ucRTUBuf[usRcvBufferPos++] = ucByte;
        eRcvState = STATE_RX_RCV;

        /* Enable t3.5 timers. */
        vMBPortTimersEnable(  );
        break;

        /* We are currently receiving a frame. Reset the timer after
         * every character received. If more than the maximum possible
         * number of bytes in a modbus frame is received the frame is
         * ignored.
         */
    case STATE_RX_RCV:
        if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
        {
            ucRTUBuf[usRcvBufferPos++] = ucByte;
        }
        else
        {
            eRcvState = STATE_RX_ERROR;
        }
        vMBPortTimersEnable(  );
        break;
    }
    return xTaskNeedSwitch;
}

BOOL xMBRTUTransmitFSM( void )
{
    BOOL            xNeedPoll = FALSE;

    assert( eRcvState == STATE_RX_IDLE );

    switch ( eSndState )
    {
        /* 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;

    case STATE_TX_XMIT:
                /*发送器处于发送状态,在从机发送函数eMBRTUSend中赋值STATE_TX_XMIT*/
        /* check if we are finished. */
        if( usSndBufferCount != 0 )
        {
            xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
            pucSndBufferCur++;  /* next byte in sendbuffer. */
            usSndBufferCount--;
        }
        else
        {
            xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );/*协议栈事件状态赋值为EV_FRAME_SENT,发送完成事件,eMBPoll函数会对此事件进行处理*/
            /* Disable transmitter. This prevents another transmit buffer
             * empty interrupt. */
            vMBPortSerialEnable( TRUE, FALSE );
            eSndState = STATE_TX_IDLE;
        }
        break;
    }

    return xNeedPoll;
}
/*函数功能
*1:从机接受完成一帧数据后,接收状态机eRcvState为STATE_RX_RCV;
*2:上报“接收到报文”事件(EV_FRAME_RECEIVED)
*3:禁止3.5T定时器,设置接收状态机eRcvState状态为STATE_RX_IDLE空闲;
*/
BOOL xMBRTUTimerT35Expired( void )
{
    BOOL            xNeedPoll = FALSE;

    switch ( eRcvState )
    {
        /* Timer t35 expired. Startup phase is finished. */
    case STATE_RX_INIT:
        xNeedPoll = xMBPortEventPost( EV_READY );
        break;

        /* A frame was received and t35 expired. Notify the listener that
         * a new frame was received. */
    case STATE_RX_RCV:
        xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
        break;

        /* An error occured while receiving the frame. */
    case STATE_RX_ERROR:
        break;

        /* Function called in an illegal state. */
    default:
        assert( ( eRcvState == STATE_RX_INIT ) ||
                ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) );
    }

    vMBPortTimersDisable(  );/*当接收到一帧数据后,禁止3.5T定时器,只到接受下一帧数据开始,开始计时*/
    eRcvState = STATE_RX_IDLE;/*处理完一帧数据,接收器状态为空闲*/

    return xNeedPoll;
}


回复

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
 楼主| 发表于 2019-1-23 11:59:05 | 显示全部楼层
求帮助
回复

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-9-11
在线时间
5 小时
 楼主| 发表于 2019-1-24 11:14:50 | 显示全部楼层
别沉啊  
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 13:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表