搜索
bottom↓
回复: 7

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

[复制链接]
(73889686)

出0入0汤圆

发表于 2018-12-10 17:32:11 | 显示全部楼层 |阅读模式
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、程序如下:
  1. BOOL xMBRTUTransmitFSM(xMBData *const data)
  2. {
  3.     BOOL xNeedPoll = FALSE;

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

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

  37.     return xNeedPoll;
  38. }
复制代码



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

(73889460)

出0入0汤圆

发表于 2018-12-10 17:35:57 | 显示全部楼层
多进一次中断判断最后一帧。
STM32直接用发送完成中断就可以了,
但是430没有这个中断。
(73874794)

出0入0汤圆

发表于 2018-12-10 21:40:23 | 显示全部楼层
记得以前是在发送最后一个字节后开启了一个定时器 在定时器中断中处理发送结束的
(73870909)

出0入0汤圆

发表于 2018-12-10 22:45:08 | 显示全部楼层
msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。
(73869100)

出0入0汤圆

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

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

出0入0汤圆

 楼主| 发表于 2018-12-10 23:16:27 | 显示全部楼层
xjmlfm1 发表于 2018-12-10 22:45
msp430虽然没有发送完成中断,但是有发送缓冲区空中断,一样可以达到目的的。 ...

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

出0入0汤圆

发表于 2018-12-11 07:57:50 | 显示全部楼层
本帖最后由 motoedy 于 2018-12-11 08:08 编辑
擦鞋匠 发表于 2018-12-10 23:15
不是特别清楚。
但我感觉,如果多进一次中断的话,相当于多发送一个字节,这样主机端将多接收一个字节数 ...


最后一帧或最后一帧发完再进一次中断,不发数。
系统对时间要求不是很严格的话,可以用while,多进一次中断或最后一帧在中断时间长点,类似你的delay;
  1. if(SendNum==0)
  2. {
  3.   while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer 是不是为空
  4.   IE1&=~UTXIE0;                                //禁止发送
  5.   。。。                                             //切换模式
  6. }
复制代码

系统对时间有要求的话,可以用if,用if会多进几次中断,但是不会每次在中断里占用太长时间。
  1. if(SendNum==0)
  2. {
  3.   if(UCA0IFG&UCTXIFG);                      // USCI_A0 TX buffer 是不是为空
  4.   IE1&=~UTXIE0;                               //禁止发送
  5.   。。。                                            //切换模式
  6. }
复制代码
(73834010)

出0入0汤圆

发表于 2018-12-11 09:00:07 | 显示全部楼层
擦鞋匠 发表于 2018-12-10 23:16
不是很懂,还请阁下明示。。。感谢!

查下寄存器就明白了,懒得截图了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号 )

GMT+8, 2021-4-13 22:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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