请教,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、问题请教:
除了使用延时方式,各位觉得该如何解决这个问题呢?感谢!
多进一次中断判断最后一帧。
STM32直接用发送完成中断就可以了,
但是430没有这个中断。 记得以前是在发送最后一个字节后开启了一个定时器 在定时器中断中处理发送结束的 msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。 motoedy 发表于 2018-12-10 17:35
多进一次中断判断最后一帧。
STM32直接用发送完成中断就可以了,
但是430没有这个中断。 ...
不是特别清楚。
但我感觉,如果多进一次中断的话,相当于多发送一个字节,这样主机端将多接收一个字节数据(原本响应帧字节数目是正确的,只是最后一个字节错误)。 xjmlfm1 发表于 2018-12-10 22:45
msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。 ...
不是很懂,还请阁下明示。。。感谢! 本帖最后由 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; //禁止发送
。。。 //切换模式
} 擦鞋匠 发表于 2018-12-10 23:16
不是很懂,还请阁下明示。。。感谢!
查下寄存器就明白了,懒得截图了。
页:
[1]