当DMA配置成循环接收后,DMA会自动将来自串口的数据循环写到设定的缓冲区中。通过定时查询缓冲区来取出数据。( ~6 G( K* l% _% l1 M# n
对于不定长数据可以通过检查包头和包长度判断是否接收一包完整数据。9 r# h \. K1 O' l) m
该方案不需要使用空闲中断。不会丢失数据。1 H& d/ r/ N, p" u. _: U3 y
如果偶尔数据被覆盖,可以尝试扩大缓冲区。如果经常有数据被覆盖,要么是系统设计不合理。要么是处理器性能不足。/ E% L0 k, l" n3 J6 H
一下使用stm32L476 nucleo-64板* r- T5 U- }' K4 h; D3 h5 t
下面是串口配置; s: w0 B6 L# g
3 B9 r8 N* W8 s4 c E; C- v& K1 o, e( }& C+ h% v, ^
DMA的配置
0 M* h! ^8 I' O# s9 Y
) F$ s/ o9 d# P
中断配置:为了使用发送完成回调,需要使能串口中断。 A+ N# Y2 ?9 I0 d7 A% `$ O8 Y" ?" _
l1 q3 E. w. H( _, J3 {* H C' ]
3 R. e9 o8 F+ n2 ECubeMX的详细使用方法参见论坛中的入门贴。我就不多废话了。& C$ j8 F( r( ]/ N
1 f: ^# j3 H+ d% s7 g, u& k核心代码:用于从环形缓冲区中提取数据。
5 D) V4 y3 R" B! [! Y- ~/ a- uint32_t ringBufPop(uint8_t *buf,uint32_t len,struct ringBufHandlerType *hringBuf,DMA_HandleTypeDef *hdma)
$ ^: a4 O/ _; r - {
& Z/ I2 Q' v" {! X+ x - uint32_t retval;) Q+ U$ K9 `5 P# x! k
- //计算数据量
+ Q, T* U4 I6 o" ~! X# `& J. {7 R - retval=hringBuf->bufSize - __HAL_DMA_GET_COUNTER(hdma);% p5 a v" w, _7 B& J4 A5 U" B
- if(retval<hringBuf->dataPopPtr){: h! l: y. Y0 b* v! h8 D
- retval=retval+hringBuf->bufSize-hringBuf->dataPopPtr;
0 t- J: y5 @6 D2 Q T$ f. O- d4 m: F3 D9 h - }else{# Y V! y) j* d; ^, L3 ] a5 Z
- retval-=hringBuf->dataPopPtr;" e" y) T( |) f( M) n% X }
- }
* Z. d( z- V5 T1 m1 t - len=len>retval?retval:len;
4 z& a& b' e8 n9 C - retval=len;& Y6 r$ @4 V8 p7 i7 p
- while(len>0){
% g! R* U8 x& E9 T - *buf++=hringBuf->pBuf[hringBuf->dataPopPtr];
' w& {2 s3 [, H- W$ _5 m- I* w/ V - hringBuf->dataPopPtr=(hringBuf->dataPopPtr+1)%hringBuf->bufSize;. `& e0 r+ @! l
- len--;
$ W2 {- w+ O5 K+ S; z - }
0 R+ W( C. i( m0 n) | o$ b7 O% x - return retval;/ p; d' H" Y7 V5 ^! ]
- }
复制代码 这是仿照HAL库写的控制句柄! b1 K% u+ W4 `8 H. v
- struct ringBufHandlerType{! L( p/ R: f3 Y& q {1 _
- uint32_t bufSize;
8 l# k7 i2 F5 f3 i: o4 v! b" ] - uint32_t dataPopPtr;; s6 z: E7 L- \1 n+ W' o
- uint8_t* pBuf; i' m9 c0 q3 t# R" M5 X
- };
复制代码
- q- X7 b# D( N x% a9 Q" w9 o, P; x9 C r8 y
) ^; o$ f9 r1 K$ c5 {
1 s L) X/ l9 a3 |, V上测试工程:
DMARingBuf.zip
(6.39 MB, 下载次数: 476)
|
通过空闲中断,和包头包尾判断完成
原来知道包头和包长度了,能否做到不知道包长度的判读接收完成的啊
双缓冲区需要切换缓冲区。环形缓冲不需要。
环形缓冲区处理比双缓冲复杂。
谢谢支持
可以试试。有啥问题可以反馈过来
好的 谢谢指导