本文介绍dsp高效接收和发送不定长度的数据,该方法减小cpu的中断次数,经过长时间检验,该方法安全可靠效率最大。我使用的是28034只有4级FIFO,在优化前中断深度设置为1,cpu频繁中断,导致正常程序受影响。经过改进,设置发送中断深度为0级,接收中断为4级,只有在数据发送完成和接收满4个字节中断。
接收流程为:等待接收中断—》读取4个fifo数据—》超时检查—》读取fifo剩余数据。这样就会接收完整的一帧数据。
发送流程:触发中断开始发送数据—》写入4个数据到发送fifo----》等到fifo为空中断–》写入下4个数据到fifo----》写入最后剩余数据。
具体如下:
(1)初始化配置
void scia_init()
{
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.bit.TXINTENA = 1;//使能发送中断
SciaRegs.SCICTL2.bit.RXBKINTENA = 1;//使能接收中断
//BRR = (LSPCLK / (SCI Asynchronous Baud * 8)) - 1 ,LSPCLK=30M,
//BRR = 0x0020, baud=115200
//BRR = 0x0007, baud=460800
//BRR = 0x0061, baud=38400
SciaRegs.SCIHBAUD =0x0000;
SciaRegs.SCILBAUD =0x0020;//
SciaRegs.SCICCR.bit.LOOPBKENA =0; // Enable loop back
SciaRegs.SCICCR.bit.STOPBITS = 2; //
SciaRegs.SCIFFTX.all=0xC020;//设置发送中断为0级
SciaRegs.SCIFFRX.all=0x0024;//设置接收中断为4级
SciaRegs.SCIFFCT.all=0x0;
SciaRegs.SCIPRI.bit.FREE = 0;//仿真模式下是否自由运行
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1; //发送FIFO复位
SciaRegs.SCIFFRX.bit.RXFIFORESET=1; //接收FIFO复位
}
(2)接收中断和发送中断
interrupt void SCI1_RXD_isr(void)
{
UINT16 RxData;
//RxData = SciaRegs.SCIRXBUF.all;
//上一个数据帧应用层未取走,数据丢弃
if ((KeyBoardRxFrame.status == UART_FRAME_RX_END) || (KeyBoardRxFrame.index >= 40))
{
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
}else
{
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
KeyBoardRxFrame.ticker = KeyBoardRxFrame.spacetime;
}
SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack
}
interrupt void SCI1_TXD_isr(void)
{
Uint16 i;
Uint16 len;
// 发送一帧数据没有完成
if(KeyBoardTxFrame.index + 4 < KeyBoardTxFrame.len)
{
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
SciaRegs.SCIFFTX.bit.TXFFINTCLR=1; // Clear SCI Interrupt flag清除后产生中断
}
else
{
//发送剩下的数据
len = KeyBoardTxFrame.len - KeyBoardTxFrame.index;
for(i = 0; (len <= 40) && (i < len); i++)
{
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
}
//一帧数据结束
if(KeyBoardTxFrame.len)
{
KeyBoardTxFrame.status = UART_FRAME_TX_IT_END;
}
}
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ACK
}
(3)读取不到4个字节的数据
void SCI1_RX_FIFO(UART_FRAME *pFrame)
{
Uint16 maxNum = 0;
while(SciaRegs.SCIFFRX.bit.RXFFST && maxNum < 4)
{
pFrame->pdata[pFrame->index++] = SciaRegs.SCIRXBUF.all;
maxNum++;
}
}
(4)在应用程序需要2ms周期查询接收数据是否结束
static void KeyboardJudgeRxFinish(void)
{
//超时或数据长度大于40一帧接收完成
if(((KeyBoardRxFrame.ticker <= 0)&&(KeyBoardRxFrame.index > 0)) || KeyBoardRxFrame.index >= 40)
{
SCI1_RX_FIFO(&KeyBoardRxFrame);
KeyBoardRxFrame.len = KeyBoardRxFrame.index;
KeyBoardRxFrame.status = UART_FRAME_RX_END;//数据接收完成,应用可以取走数据
}
if(KeyBoardRxFrame.ticker > 0)
{
KeyBoardRxFrame.ticker--;
}
}
(6)发送
void KeyboardRs485TxFrame(void)
{
SCI1SetTxMode();
//如果当前帧正在发送,又重新请求发送一帧数据,则请求的数据丢弃
if(KeyBoardTxFrame.status == UART_FRAME_TX_ING)
{
return ;
}
//启动发送第一个字节后,产生中断,接着数据在中断中发送完成
KeyBoardTxFrame.index = 0;
SciaRegs.SCIFFTX.bit.TXFFINTCLR=1;//启动发送中断
KeyBoardTxFrame.status = UART_FRAME_TX_ING;
}