高级会员

- 积分
- 820
- 金钱
- 820
- 注册时间
- 2018-7-3
- 在线时间
- 17 小时
|

楼主 |
发表于 2018-10-2 12:09:02
|
显示全部楼层
查看手册针对TC形成有如下描述
Bit 6 TC: Transmission complete
This bit is set by hardware if the transmission of a frame containing data is complete and if
TXE is set. An interrupt is generated if TCIE=1 in the USART_CR1 register. It is cleared by
software, writing 1 to the TCCF in the USART_ICR register or by a write to the USART_TDR
register.
An interrupt is generated if TCIE=1 in the USART_CR1 register.
0: Transmission is not complete
1: Transmission is complete
Note: If TE bit is reset and no transmission is on going, the TC bit will be set immediately
关键在于最后Note这句,并不是只有发送一个字节能触发TC置1,把TE清零再置1同样能产生一个TCIE。所以在发送enable的时候将TE清零再置1,惊奇的发现hal库有这个函数,HAL_HalfDuplex_EnableTransmitter,不过里面将RE清零了,接收没问题,就懒得管了。手写清置TEslave返回数据没问题了。
问题从一开始就知道出在这个函数里面发的第一个字节,所以注销掉,使用TE位操作置TC产生中断。
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.
*/
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 );
//printf("pucSndBufferCur[0] re is %x \r\n",pucSndBufferCur[MB_SER_PDU_ADDR_OFF]);
/* Activate the transmitter. */
//发送状态转换,在中断中不断发送
eSndState = STATE_TX_XMIT;
//pucSndBufferCur_reset = 0 ;
//启动第一次发送,这样才可以进入发送完成中断
//xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
//xMBPortSerialPutByte( (char )01 );
//pucSndBufferCur++; /* next byte in sendbuffer. */
//usSndBufferCount--;
//delay_us(10);
//使能发送状态,禁止接收状态
vMBPortSerialEnable( FALSE, TRUE );
}
else
{
eStatus = MB_EIO;
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
vMBPortSerialEnable中做如下修改
if (xTxEnable)
{
__HAL_UART_ENABLE_IT(&USART2_RS485Handler,USART_IT_TC);
RS485_TX_Set(1);
//HAL_HalfDuplex_EnableTransmitter(&USART2_RS485Handler);
/* Clear TE bits */
CLEAR_BIT(USART2_RS485Handler.Instance->CR1, (USART_CR1_TE));
/* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */
SET_BIT(USART2_RS485Handler.Instance->CR1, USART_CR1_TE);
} |
|