您好、
在我的应用中、我有一个微控制 器、它的代码无法更改、从而向 TMS320F280039C 发送连续数据流。 我每次读取1个字节的数据、直到看到起始字符、然后连续读取47个字节的数据。
如果我在接收到 Rx 中断时按如下所示对所有数据进行阻塞式读取、我可以确保这项工作可靠:

但是、在57600波特率下、这需要8ms、而我的应用需要一个快速250us 中断来控制电机、因此我无法阻断8ms。 因此、与我在该 MCU 上的 SPI 上执行的操作一样、我切换到了以下过程:
1) 1)一次读取1个字节、直到我看到停止字符
2) 2)将 FIFO 大小设置为16字节、等待 FIFO 中断接收 FIFO 满
3) 3)将字节存储在数组中
4) 4)获取另一个满16字节的 FIFO
5) 5)将字节存储在数组中
6)获取另一个15字节的 FIFO
7) 7)将字节存储在数组中
8) 8)现在我有了完整的数据包、返回到每次读取1个字节、直到我看到停止字符。
现在的问题是、随着连续数据流进入、我会得到一个 Rx 组帧错误。 我关注的是、在 TI e2e 上、这似乎是 SCI 驱动程序中的一个错误、如果您使用具有连续数据流的 FIFO、它需要2个停止位? 如果是这种情况、这将是我们使用此 MCU 的主要问题。 我们无法将发送连续数据流的器件更改为发送2个停止位。 轮询不是一个选项、因为我的应用程序有很多必须处理的中断。
这是我的初始化
void UcapBox_InitRS485(GE_Primary_Container_t *pContainer)
{
// Register interrupt ISRs
Interrupt_register(INT_SCIA_TX, &sciATxISR);
Interrupt_register(INT_SCIA_RX, &sciARxISR);
// Initialize SCIA and its FIFO.
SCI_performSoftwareReset(REPJ_REPC_RS485_UART);
// Configure SCIA
SCI_setConfig(REPJ_REPC_RS485_UART, DEVICE_LSPCLK_FREQ, REPJ_REPC_BAUDRATE,
( SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE ) );
SCI_resetChannels(REPJ_REPC_RS485_UART);
SCI_clearInterruptStatus(REPJ_REPC_RS485_UART, SCI_INT_RXFF | SCI_INT_FE | SCI_INT_RXERR);
SCI_enableInterrupt(REPJ_REPC_RS485_UART, SCI_INT_RXFF); // We don't transmit to REPJ
SCI_enableInterrupt(REPJ_REPC_RS485_UART, SCI_INT_FE);
SCI_enableInterrupt(REPJ_REPC_RS485_UART, SCI_INT_RXERR);
SCI_resetRxFIFO(REPJ_REPC_RS485_UART);
SCI_resetTxFIFO(REPJ_REPC_RS485_UART);
SCI_enableFIFO(REPJ_REPC_RS485_UART);
SCI_enableModule(REPJ_REPC_RS485_UART);
// Set how many bytes to trigger interrupt on
SCI_setFIFOInterruptLevel(REPJ_REPC_RS485_UART, SCI_FIFO_TX0, SCI_FIFO_RX1);
SCI_performSoftwareReset(REPJ_REPC_RS485_UART);
// Enable interrupts
Interrupt_enable(INT_SCIA_RX);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
下面介绍了如何根据我是要读取1字节还是47字节来更改 FIFO 大小。
int32_t UcapBox_StartUartTransfer(GE_Primary_Container_t *pContainer)
{
pContainer->debugCnt++;
// Perform software reset of SCI in case of any errors
SCI_performSoftwareReset(REPJ_REPC_RS485_UART);
pContainer->debugCnt++;
if((dataSize < 16) && (dataSize > 0))
{
SCI_setFIFOInterruptLevel(REPJ_REPC_RS485_UART, SCI_FIFO_TX0, (SCI_RxFIFOLevel) dataSize);
}
else if(dataSize > 0)
{
SCI_setFIFOInterruptLevel(REPJ_REPC_RS485_UART, SCI_FIFO_TX0, SCI_FIFO_RX16);
}
bytesRemaining = dataSize;
pContainer->debugCnt++;
// Reset Rx FIFO
SCI_clearInterruptStatus(REPJ_REPC_RS485_UART, SCI_INT_RXFF | SCI_INT_FE | SCI_INT_RXERR);
SCI_clearOverflowStatus(REPJ_REPC_RS485_UART);
SCI_resetRxFIFO(REPJ_REPC_RS485_UART);
EINT; // Enable interrupts
SCI_enableInterrupt(REPJ_REPC_RS485_UART, SCI_INT_RXFF);
pContainer->debugCnt++;
return 1;
}
这是我的 Rx 中断-
void sciARxISRFunc(GE_Primary_Container_t *pContainer)
{
uint32_t sciInterruptStatus = SCI_getInterruptStatus(REPJ_REPC_RS485_UART);
pContainer->debugCnt++;
// Rx error occurred
if((sciInterruptStatus & SCI_INT_FE) || (sciInterruptStatus & SCI_INT_RXERR))
{
errorCnt++;
SCI_clearInterruptStatus(REPJ_REPC_RS485_UART, SCI_INT_RXFF | SCI_INT_FE | SCI_INT_RXERR);
SCI_clearOverflowStatus(REPJ_REPC_RS485_UART);
SCI_resetRxFIFO(REPJ_REPC_RS485_UART);
// Restart transfer
UcapBox_SetTransferSize(1); // go back to reading 1 byte at a time
UcapBox_StartUartTransfer(pContainer);
pContainer->debugCnt++;
}
else if (sciInterruptStatus & SCI_INT_RXFF) // we have a full FIFO
{
// Calculate bytes remaining
if ((bytesRemaining < 16) && (bytesRemaining > 0))
{
bytesRemaining = 0;
}
else if (bytesRemaining > 0)
{
bytesRemaining -= 16;
}
uint32_t tempUpperLim = 0;
if(dataSize == bytesRemaining)
{
SCI_RxFIFOLevel RxFifoLevel;
SCI_TxFIFOLevel TxFifoLevel;
// Get Fifo level
SCI_getFIFOInterruptLevel(REPJ_REPC_RS485_UART, &TxFifoLevel, &RxFifoLevel);
tempUpperLim = (uint32_t) RxFifoLevel;
}
else
{
tempUpperLim = dataSize - bytesRemaining;
}
// Store data read
int i = bytesRead;
for(i = bytesRead; i < tempUpperLim; i++)
{
pContainer->mpUcapModule->mReceiveBuffer[i] = SCI_readCharNonBlocking(REPJ_REPC_RS485_UART);
bytesRead++; // Increment bytes read
}
// Transfer complete
if(bytesRemaining == 0)
{
// Reset bytesRead
bytesRead = 0;
// Call library callback function
GE_UcapModule_Callback(pContainer, 0, 0);
// Disable interrupt until we want another one
SCI_disableInterrupt(REPJ_REPC_RS485_UART, SCI_INT_RXFF);
}
else if (bytesRemaining < 16)
{
SCI_setFIFOInterruptLevel(REPJ_REPC_RS485_UART, SCI_FIFO_TX0, (SCI_RxFIFOLevel) bytesRemaining);
}
else
{
SCI_setFIFOInterruptLevel(REPJ_REPC_RS485_UART, SCI_FIFO_TX0, SCI_FIFO_RX16);
}
// uint32_t start = GetProfilerCycles();
//
// // Read data coming in
// pContainer->mpCpuUtilization->mDebugTime1 = CalcProfilerTime(start, GetProfilerCycles());
}
SCI_clearOverflowStatus(REPJ_REPC_RS485_UART);
SCI_clearInterruptStatus(REPJ_REPC_RS485_UART, SCI_INT_RXFF | SCI_INT_FE | SCI_INT_RXERR);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
感谢您的帮助!