硬件准备
5 }: k+ A2 V& l+ T# F& X这里准备了GD32303C_START开发板进行验证。+ b2 C* X m& v# I* i2 G/ Y# P
1 N; J1 }& a5 W! O
3 K: S& p5 L [
' G5 [2 r4 ~, f6 aSTM32CUBEMX配置9 z3 o; u, i* L) w! L
1 }+ \/ Y `, [' [& I
# n% z- i( V. y4 t, a* k+ g) N. w P& o: ]! I% _2 B
勾选中断。" B* p+ `; T d
, A- w% j: `/ j+ x: G
+ t& ?- [! \, O2 ~6 t. S
开启DMA读取和接收。9 X) F" I! Z) A
其中Word = 32bit,Half word = 16bit,Byte = 8bit
4 g: C0 Y( n. ]& U$ P M7 k7 d
8 l6 e2 I( u Q5 b' P5 `
8 R% g u' j0 E4 o
0 b/ @ H* u5 \: C
' u3 y0 K+ ?' |; i3 y/ p
* P" c6 `! n) h0 _9 ?0 \- t; ~
keil配置
" c1 @5 ^& C8 tmicrolib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。 某些库函数的运行速度也比较慢,如果要使用printf(),必须开启。
4 ]4 |& O7 ?5 [# I3 y7 m- i& H) B2 j1 V% [/ c8 B
$ T6 |" c9 M& x. w
& X5 ?9 e' r ]! V; K k8 P串口重定向5 q# K/ X. q* I) t; J7 k: m& I
在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
+ h. X! g) k7 M" P& f j
: ~5 D! `% h, b: g- /* USER CODE BEGIN Includes */
9 I3 I- g! f d - #include "stdio.h"8 x+ [; ^( L$ I8 Y/ u+ Y/ V7 o( q: e
- /* USER CODE END Includes */
复制代码
# d% S' p3 k# z函数声明和串口重定向:
( u/ \; L/ E( h7 `, A' d% S% e* M/ p4 m3 J* ~% @' k
- /* USER CODE BEGIN PFP */
0 K- b5 ?& a" p& }+ j - #ifdef __GNUC__ //串口重定向% h. h1 ]) J* S, Q) I
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch): N' g2 c. m% B+ y ]3 E
- #else" l# a) m d" A3 q5 o: _
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)5 o# v$ `/ m: x! y
- #endif " K' ]6 @/ p7 n
- PUTCHAR_PROTOTYPE4 E2 o- h5 L; k1 O
- {
( A; u$ c& a* v1 H2 T - HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);9 R, B6 }' e3 J0 u
- return ch;
* E9 H# P2 w, { g# i I/ H" Z+ S3 ` - }
b2 I( q2 Z3 v _* J - /* USER CODE END PFP */
复制代码 2 u; v0 h4 h+ y$ {3 i0 ?
串口接收发送函数5 M" w2 K+ Q7 G7 q( P; P
一般情况下,串口接收发送函数有如下所示。
, x% P/ m; O7 E& K$ w. S: D* Y% j● HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。
, N* A$ ^" e) q9 b● HAL_UART_Receive();串口轮询模式发送,使用超时管理机制。
! w( A. J) ]3 m, E0 Q● HAL_UART_Transmit_IT();串口中断模式发送
+ W5 o* S z, [8 W! e● HAL_UART_Receive_IT();串口中断模式接收
4 }8 ]% F) m& k● HAL_UART_Transmit_DMA();串口DMA模式发送
. z/ p5 j1 x8 V0 f, ]7 Z- J% y● HAL_UART_Receive_DMA();串口DMA模式接收8 \8 r" p8 c$ H
: i( j# Q* w% t! ~0 HHAL_UART_Transmit_DMA()发送- _. K- Y$ m& M/ t
测试代码如下。
! N9 T2 L" O. S4 k' p. k3 q6 _定义需要发送的数据。
6 W9 H) x# V2 _7 x( T4 I, h" o
B1 h) K0 ^1 q- J! a$ f5 t; t- /* USER CODE BEGIN PV */
: y" {8 L0 y! V& ]5 w8 m - uint8_t TxData[] = "\r\n**** Hello,World!' ***\r\n";1 n' h+ ^4 u; q) Z9 ~
- /* USER CODE END PV */
复制代码 ) `/ {7 d+ X; f: ^
HAL_UART_Transmit_DMA()发送代码。, Q- x6 o4 L0 l
* @2 o8 c/ e2 N; F8 \. [
- /* USER CODE BEGIN WHILE */2 ?2 e5 e: X& X, ^% U. \
- while (1)6 P: P3 c+ f' N$ V9 i, Y' U
- {
4 E/ t4 o; h2 x f/ p" d - /* USER CODE END WHILE */% l8 g& s6 @$ b7 I
- ( L- V1 i8 K6 b4 n1 u" ^4 h: O# ?
- /* USER CODE BEGIN 3 */
4 ~8 M( T6 a5 Q( T# p; f5 Z/ U9 Y - HAL_UART_Transmit_DMA(&huart1, (uint8_t *)TxData, sizeof(TxData)-1);" |& r$ a5 O# A+ r! @ }9 m3 P
- HAL_Delay(1000);
: ] b. d5 o9 c9 y: G8 v, h- W7 | - }
2 W2 \/ ]* W: i. P9 i" b - /* USER CODE END 3 */
复制代码
4 {# y1 l9 R) c0 T' S7 }DMA有normal和circular两种模式。/ x# x4 l) |8 Q, K' e
Normal表单次传输,传输一次后终止传输,所以需要传输几次就需要开启几次,Circular表示循环传输,传输完成后又重新开始继续传输,开启一次后会一直传输。" Y" ?4 J0 i$ x8 ^9 e5 l
normal传输打印如下所示,传输完成就关闭。
6 W% C2 v+ p& W9 m. u& N
, ]3 A4 q8 K2 z5 C& P. F
, }: e+ [( l$ X& J+ A7 W
& y: j; Q+ m, E& E% kcircular传输打印如下所示,一直传输,不会停止。
$ {* n$ f L8 {( A j% [' q% \( D& F
/ o* N6 F& y" V" V' ~
7 T" Q8 i/ n; _4 s* L' DHAL_UART_Receive_DMA()发送; g6 P* ?$ `- v, x" c* y2 ]$ k
测试代码如下。
8 F' t2 n: W8 Y c7 y( R9 ~, t定义需要接受存放数组。& g: i4 u' v/ q% f% `( w
/ a; H7 x1 K' k2 ?9 ~; w) @0 p7 e( N
- /* USER CODE BEGIN PV */$ ], I$ R j6 q& ?5 N6 X8 U
- uint8_t RxData[255];1 ^' e8 E/ E3 m# t/ W! L! [: p
- /* USER CODE END PV */
复制代码 1 R% ]2 @. a0 x& J/ {6 q
开启HAL_UART_Receive_DMA()接受代码。. x8 W. O. u$ C
+ V% l+ M. M2 C0 d% r; G1 A' W$ C
- /* USER CODE BEGIN 2 */8 W3 C" p& d& V, m2 [
- HAL_UART_Receive_DMA(&huart1, RxData, 10); // 这里加这个函数,接收数据
6 t( F8 T# N# G) Y2 w" ^ - /* USER CODE END 2 */
复制代码
: _2 K' A J4 f8 @% B* n. ]( P重写读取回调函数,将接受的数据发送出去在开启接收。8 \& R, m2 `- p# @0 @( S
8 W' a5 j8 _: w
- /* USER CODE BEGIN 4 */
, W% t6 [1 H, L- ? - void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)3 ~- |' O) h$ `
- {/ L; i: |; [6 c& ?7 }$ z
, L3 c* f$ t- G3 Y: b- HAL_UART_Transmit(&huart1, (uint8_t *)"text:", 5,0xffff);//轮询发送,不然可能发送不出去
! i1 w. R I/ f F - HAL_UART_Transmit_DMA(&huart1, (uint8_t *)RxData, 10);//发送接受的数据
/ @: l! F5 A" n) W: |$ u - HAL_UART_Receive_DMA(&huart1, RxData, 10); // 这里加这个函数,接收数据
: ` T" _# I- T" w6 c; J. N, K) i' K - }! G4 ]: P! z8 |0 G
- + c; [( r) ]* ]
- /* USER CODE END 4 */
复制代码
3 u; `1 B3 B" ]' p$ ]1 f) QDMA有normal和circular两种模式。. X+ R! Q, j) S; ]' y& p
Normal表单次接收,接收一次后终止接收,所以需要接收几次就需要开启几次,Circular表示循环接收,接收完成后又重新头开始继续接收,开启一次后会一直接收。
. V+ g/ ]; ^7 F# [' n- |normal传输打印如下所示,传输完成就关闭。9 H' P; e. Q: g9 D$ K
演示效果如下所示。
5 X! f9 s+ _9 j8 N! K% |
& M* i& J1 c5 k' o! q5 T' y
$ `/ `3 z* u' R7 n) d7 ]
* G* O: y5 B. F+ X
circular接收打印如下所示,当发送数据大于接收长度时候,会进行循环接收。
9 l- o C+ ^3 {2 I$ P
0 `7 @5 I& z1 U' ^% f, j2 k
9 O* W1 J8 f t
& w. m4 K6 x' V- f& w& b% L+ \* e2 w4 {
|