本文介绍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; }