擦鞋匠 发表于 2018-12-10 17:32:11

请教,MSP430F5438a移植FreeModbus,如何判断响应帧发送完成?

1、开发环境:
IAR7.10 + MSP430F5438a 485芯片是MAX3471(该芯片属于需要手动切换发送模式和接收模式)

2、问题描述:
由于MSP430没有发送完成中断(stm32串口有TXE和TC,而msp430只有UCTXIFG,类似于stm32的TXE)。于是在响应帧中发送最后一个字节时,如果仅仅满足UCTXIFG置位就切换485芯片为接收模式,可能会导致最后一个字节数据发送错误!例如:
发送:01 03 0B B8 00 01 06 0B
接收:01 03 02 2D B2 25 FF(实际上最后一位应该是0x61)

3、我的解决办法:
使用延时的方式,但是个人感觉有些不妥,主要原因包括:
<1>、如果切换波特率的话,这个延时的时间是需要修改的,除非设置一个很大的值
<2>、这个函数是在中断中,更加不应该延时。
<3>、我记得当时我在stm32上移植时,就是使用TXE中断,但没有遇到这个问题(不知该如何解释)

4、程序如下:
BOOL xMBRTUTransmitFSM(xMBData *const data)
{
    BOOL xNeedPoll = FALSE;

    switch (data->eSndState)
    {
      /* We should not get a transmitter event if the transmitter is in
         * idle state.*/
    case STATE_TX_IDLE:
      /* enable receiver/disable transmitter. */
      data->pxMBCall->pvMBPortSerialEnable(TRUE, FALSE);
      break;

    case STATE_TX_XMIT:
      /* check if we are finished. */
      if (data->usSndBufferCount != 0)
      {
                        data->pxMBCall->pxMBPortSerialPutByte(*data->pucSndBufferCur);
                        data->pucSndBufferCur++;/* next byte in sendbuffer. */
                        data->usSndBufferCount--;
      }
      else
      {
            //xNeedPoll = xMBPortEventPost(data, EV_FRAME_SENT);
            
            /*
             * 由于MSP430没有TX发送完成中断,导致最后一个字节发送动作开始之后,
             * 不能立马切换到接收模式,需要等待最后一个字节发送完成之后。
             */
            delay_us(300); /* 至少需要200us,目前使用300us */
            
            /* Disable transmitter. This prevents another transmit buffer
             * empty interrupt. */
            data->pxMBCall->pvMBPortSerialEnable(TRUE, FALSE);
                        data->eSndState = STATE_TX_IDLE;
      }
      break;
    }

    return xNeedPoll;
}


5、问题请教:
除了使用延时方式,各位觉得该如何解决这个问题呢?感谢!

motoedy 发表于 2018-12-10 17:35:57

多进一次中断判断最后一帧。
STM32直接用发送完成中断就可以了,
但是430没有这个中断。

登云钓月 发表于 2018-12-10 21:40:23

记得以前是在发送最后一个字节后开启了一个定时器 在定时器中断中处理发送结束的

xjmlfm1 发表于 2018-12-10 22:45:08

msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。

擦鞋匠 发表于 2018-12-10 23:15:17

motoedy 发表于 2018-12-10 17:35
多进一次中断判断最后一帧。
STM32直接用发送完成中断就可以了,
但是430没有这个中断。 ...

不是特别清楚。
但我感觉,如果多进一次中断的话,相当于多发送一个字节,这样主机端将多接收一个字节数据(原本响应帧字节数目是正确的,只是最后一个字节错误)。

擦鞋匠 发表于 2018-12-10 23:16:27

xjmlfm1 发表于 2018-12-10 22:45
msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。 ...

不是很懂,还请阁下明示。。。感谢!

motoedy 发表于 2018-12-11 07:57:50

本帖最后由 motoedy 于 2018-12-11 08:08 编辑

擦鞋匠 发表于 2018-12-10 23:15
不是特别清楚。
但我感觉,如果多进一次中断的话,相当于多发送一个字节,这样主机端将多接收一个字节数 ...

最后一帧或最后一帧发完再进一次中断,不发数。
系统对时间要求不是很严格的话,可以用while,多进一次中断或最后一帧在中断时间长点,类似你的delay;
if(SendNum==0)
{
while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer 是不是为空
IE1&=~UTXIE0;                              //禁止发送
。。。                                             //切换模式
}
系统对时间有要求的话,可以用if,用if会多进几次中断,但是不会每次在中断里占用太长时间。
if(SendNum==0)
{
if(UCA0IFG&UCTXIFG);                      // USCI_A0 TX buffer 是不是为空
IE1&=~UTXIE0;                               //禁止发送
。。。                                          //切换模式
}

xjmlfm1 发表于 2018-12-11 09:00:07

擦鞋匠 发表于 2018-12-10 23:16
不是很懂,还请阁下明示。。。感谢!

查下寄存器就明白了,懒得截图了。
页: [1]
查看完整版本: 请教,MSP430F5438a移植FreeModbus,如何判断响应帧发送完成?