|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本文介绍DSP高效接收和发送不定长度的数据,该方法减小cpu的中断次数,经过长时间检验,该方法安全可靠效率最大。我使用的是28034只有4级FIFO,在优化前中断深度设置为1,cpu频繁中断,导致正常程序受影响。经过改进,设置发送中断深度为0级,接收中断为4级,只有在数据发送完成和接收满4个字节中断。
5 x- `" y, u* x1 m$ A 接收流程为:等待接收中断—》读取4个fifo数据—》超时检查—》读取fifo剩余数据。这样就会接收完整的一帧数据。5 f0 ^" b$ D: `3 I! `+ C7 d
发送流程:触发中断开始发送数据—》写入4个数据到发送fifo----》等到fifo为空中断–》写入下4个数据到fifo----》写入最后剩余数据。 d& v5 s: s% o4 _8 ^0 V+ S) K
具体如下:
( v+ U" Y- Z: w$ s+ O0 i8 K(1)初始化配置
" f( @' [2 B/ x! F( y) ]void scia_init()
, D* }3 G2 t% i& l3 K{/ L# q- D$ _3 ~
// Note: clocks were turned on to the SCIA peripheral
m8 K2 Q& e0 e // in the InitSysCtrl() function
4 N! Q0 e1 g- W+ E* p) J SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback1 e+ O% o8 n8 s( N. E
// No parity,8 char bits,
6 A! t7 \% A4 ]7 ?$ n9 m8 f // async mode, idle-line protocol
# X2 x+ i* E& F- r4 U& ` SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,& E0 z+ ]7 x$ o; X/ |
// Disable RX ERR, SLEEP, TXWAKE, ]0 r$ g2 Q% [. Z$ i5 ]
SciaRegs.SCICTL2.bit.TXINTENA = 1;//使能发送中断
' L. b* |" Z8 G5 W) J
`; M9 y$ f# G$ v
6 p0 e1 o. Z$ P- C* Z2 T4 i SciaRegs.SCICTL2.bit.RXBKINTENA = 1;//使能接收中断
: \ c8 I6 T/ e+ Z8 R5 B! S
7 P8 m: T9 p4 I. m, U* J7 d' y //BRR = (LSPCLK / (SCI Asynchronous Baud * 8)) - 1 ,LSPCLK=30M,. T6 H2 [9 j1 c9 r( n
//BRR = 0x0020, baud=115200
1 {6 e8 y' T$ R; i* q //BRR = 0x0007, baud=460800% c' r( @, H. U$ a+ W0 w9 n. w
//BRR = 0x0061, baud=38400
: V) X2 ]& T" _0 d6 k& [ SciaRegs.SCIHBAUD =0x0000;* W' R- o3 c; Y8 \
SciaRegs.SCILBAUD =0x0020;//5 X. x1 H- z% }- f
SciaRegs.SCICCR.bit.LOOPBKENA =0; // Enable loop back ^( q* z9 X$ M* }) J: V
SciaRegs.SCICCR.bit.STOPBITS = 2; //
) M; \1 c V% S: ? q* G; U SciaRegs.SCIFFTX.all=0xC020;//设置发送中断为0级
# V0 m d) l; j' o' R1 [$ H SciaRegs.SCIFFRX.all=0x0024;//设置接收中断为4级' h" v# {7 A9 J% n* w
SciaRegs.SCIFFCT.all=0x0;
# k' n7 |; P* m5 w W SciaRegs.SCIPRI.bit.FREE = 0;//仿真模式下是否自由运行; f6 j. h0 T' B2 @0 B* J
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
0 y& j9 x( S2 |$ d SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1; //发送FIFO复位/ z: B, |* L. S( o. }
SciaRegs.SCIFFRX.bit.RXFIFORESET=1; //接收FIFO复位 ' Q4 P. y0 M1 I; h4 `
}% y4 G5 b1 p' g$ N B* F
+ G) }* M! Y7 m
(2)接收中断和发送中断
& \! P& p6 |' }4 |! p
0 x6 G) Q6 U: l' C8 ointerrupt void SCI1_RXD_isr(void)( J) o- ]& m( S9 r
{
) g. J) B5 X7 F" l6 Q$ j UINT16 RxData;
! E$ |6 e* H J& A* j+ F& v( L //RxData = SciaRegs.SCIRXBUF.all;
& w0 d0 }& h+ T5 Q5 }& w6 a //上一个数据帧应用层未取走,数据丢弃( s) o" j" a. o% n6 p- ]
if ((KeyBoardRxFrame.status == UART_FRAME_RX_END) || (KeyBoardRxFrame.index >= 40))
* L5 k) ]7 P* N {$ h9 B6 j) E4 ], s# V$ G" G
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;- \; V- t* t3 X3 o5 h0 t# S
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
6 D, z" \, [" I5 m. [ KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
! x- f2 I; _- o' l$ v1 A KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
5 Q L4 }+ U: G. s6 R( Z7 \: d }else
$ G0 n( z3 g3 v, R: e0 u. z {
9 A% d# k/ A) a) _# M) @# B KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;# I* j ]; w- g
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;$ A; A- P2 [! N3 x
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;1 {% w0 z3 P1 Q8 } H, A/ L, w
KeyBoardRxFrame.pdata[KeyBoardRxFrame.index++] = SciaRegs.SCIRXBUF.all;
9 T1 Q( _* `8 L( p8 a/ s, E KeyBoardRxFrame.ticker = KeyBoardRxFrame.spacetime;
$ e/ y9 k K' c4 U( s9 p } f" w- |. H4 Q
: `" A) D; Y* x3 @ SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear OveRFlow flag
2 z f* H" r* L* O! Y( d8 @3 t SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag. ^" y4 H# i, ]' P: y
4 c* s e) ^( w0 e6 ]: h' z PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack
8 O/ K# G1 x" b}, S% q& Q! s: J( B/ Y! X
interrupt void SCI1_TXD_isr(void)9 t$ X) r9 H% }8 b
{
0 a2 q. O! i2 p2 N! \ Uint16 i;+ v1 v# I8 M+ a5 K% n* I4 o/ H
Uint16 len;/ [" s: Y2 R- h8 f& M: E
// 发送一帧数据没有完成1 p' z0 X- P$ x R$ R
if(KeyBoardTxFrame.index + 4 < KeyBoardTxFrame.len)
7 M/ ?! o$ |) T e! U5 ? {) @6 E/ @ ^8 |' v# E
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
4 M4 h0 k3 P0 B6 | SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];9 V& } H2 d2 Q! q
SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
1 N1 r- l6 z$ g) Z# {2 p/ }' T SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
7 O* G" q2 Q1 X) K2 y2 j- K; Q v
' o7 ]2 R5 s) C& s6 ~2 B( d; j SciaRegs.SCIFFTX.bit.TXFFINTCLR=1; // Clear SCI Interrupt flag清除后产生中断$ }9 \, T2 ?; g. k
}
2 \! J4 W* e- R( Z else
6 a: k# Y1 L* _' O {7 x# k- P9 u- N
//发送剩下的数据, P8 ] A1 s' W4 B& P
len = KeyBoardTxFrame.len - KeyBoardTxFrame.index;
# R8 J& G: \. S7 j- W0 J& t; q for(i = 0; (len <= 40) && (i < len); i++)
! R7 n" q# O$ | {
D J/ ~0 g5 v+ |! w SciaRegs.SCITXBUF = KeyBoardTxFrame.pdata[KeyBoardTxFrame.index++];
q1 c2 u1 `: R9 x }
3 ~, z' C4 A9 x5 \7 B, Y 2 ?' ~8 O& T' i" u/ F
//一帧数据结束; @( `) n- J, O
if(KeyBoardTxFrame.len)' Y5 w& |4 F- @2 @- q; h- Y+ K2 j3 P7 p
{
( t/ B' s: W! D' N7 V! U KeyBoardTxFrame.status = UART_FRAME_TX_IT_END;
* W2 O6 e5 G, |" j3 l$ ^/ `9 P- i }
4 _3 b8 K t ]: O: g: v$ p }
, j+ G5 u# |) U) T' t* B PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ACK& s* B/ q4 s3 L+ ]
}5 A* x0 y1 k5 f
$ F' K& Z4 s4 y" O2 c4 _( f1 K. M(3)读取不到4个字节的数据3 |8 k' B8 k2 L4 x& e2 U; Z0 W
7 F# I8 N& M$ B
void SCI1_RX_FIFO(UART_FRAME *pFrame)6 u7 Y/ f8 |1 i
{, p6 ^9 y( c# f4 I
Uint16 maxNum = 0;; A- a& H6 {2 U4 V, u' a6 k% q8 s9 Z7 ]
while(SciaRegs.SCIFFRX.bit.RXFFST && maxNum < 4)) t/ e9 L% d V& e: Y
{0 D+ J( F; p2 v7 h5 c8 d) k
pFrame->pdata[pFrame->index++] = SciaRegs.SCIRXBUF.all;
5 @7 l; q7 X, j% c maxNum++;- t& M" v: P3 N
}! Z a" S0 N- w$ Q
}6 n) E$ ]$ R4 B
, L- k% u# }) T% Z(4)在应用程序需要2ms周期查询接收数据是否结束, S- J& l% S, k3 S7 h$ Q% T
static void KeyboardJudgeRxFinish(void)
k# V% M- k" I5 y! _& M{- `) { m5 w4 [8 U& V
//超时或数据长度大于40一帧接收完成8 ^: S" G/ Y, L& j5 q4 K% O% ?: `
if(((KeyBoardRxFrame.ticker <= 0)&&(KeyBoardRxFrame.index > 0)) || KeyBoardRxFrame.index >= 40)' J( I# R, {; a( {( ^
{
4 ?5 s3 D/ a0 y# x& `; ^ SCI1_RX_FIFO(&KeyBoardRxFrame);
Y: ^! M6 Z. v* P1 i9 K2 T6 q/ S$ Q KeyBoardRxFrame.len = KeyBoardRxFrame.index;
! a# e; w) U' ^( K KeyBoardRxFrame.status = UART_FRAME_RX_END;//数据接收完成,应用可以取走数据
2 Y5 w2 A2 D. d5 V. ?! w }
4 X! L$ o, X$ Y4 A4 G% G if(KeyBoardRxFrame.ticker > 0)3 K4 k+ u8 c- Y; }
{1 ?$ Q# y4 y' }& \* B0 z
KeyBoardRxFrame.ticker--;1 r& H, w6 i, r4 C
}
% ], u& F8 s% u! J4 v# w3 q}3 X1 K# g x# C; V- y3 T. d L
. X& U. I6 n- }2 }( k(6)发送
* }, b1 Z c$ Q I. W s3 Mvoid Keyboardrs485TxFrame(void)
5 Q/ h# f( B+ Z5 J( D5 H{% A) ~) E9 L3 y0 U1 j
SCI1SetTxMode();
/ @: \; o" J) A7 w. `: |4 ` //如果当前帧正在发送,又重新请求发送一帧数据,则请求的数据丢弃/ \ r5 c9 Z& F4 @! m \/ D
if(KeyBoardTxFrame.status == UART_FRAME_TX_ING)
; q n, W; l" I! f3 m3 A {
8 j; X, [) O7 \ return ;9 D5 v! H; U, [: Y8 B0 E6 \( F$ u
}
- r* l6 p! n2 {5 D //启动发送第一个字节后,产生中断,接着数据在中断中发送完成
l0 I' t1 y: R+ ~, p3 x KeyBoardTxFrame.index = 0;
* r; Q- R" O. l0 e7 J1 ` SciaRegs.SCIFFTX.bit.TXFFINTCLR=1;//启动发送中断& Q P+ x- ~: D. O: r' k
KeyBoardTxFrame.status = UART_FRAME_TX_ING;
" n' ~2 b- T% P0 D3 Q) C9 q+ e2 O+ q}
, J3 M7 s/ h+ { |
|