概述; Y" w4 ]5 R5 B3 s1 f+ R
本章STM32CUBEMX配置STM32F103,并且在GD32F303中进行开发,同时通过GD32303C_START开发板内进行验证。" |- S: p) m$ o1 p# j+ ^2 R
本章主要配置串口进行DMA收发。
9 C6 B9 k, ?: _8 d8 [需要GD样片的可以加Q_QUN申请:6_15061293。
6 U5 W, @( g. X$ g8 R% P
9 l0 d& S& x0 Y) O/ A0 ~+ d查阅手册可以得知,PA9、PA10为串口0的输出和输入口。
2 Z/ I0 r, r1 s2 g5 g4 m d! p/ X+ p& q4 a o, q( b, n! {
" k! P/ s. C" P1 R; q1 }- r) B7 e* H0 f) q5 }; S7 |
硬件准备$ `/ U/ t1 v/ `; s1 W; j
这里准备了GD32303C_START开发板进行验证。
0 _* Q# J! Y- [% N. f& X W4 L [, _8 B
- s" v( Q5 L1 _% W
8 y( { q; f' ~3 ?6 T W$ fSTM32CUBEMX配置+ ?/ a: ~. @+ {/ G/ i
q6 O1 \1 z5 O" y
% u) w" X/ A4 M9 d- x
9 S9 ^% ~5 [% k* z- R4 x
勾选中断。
6 D1 O* t' C5 _7 G L7 A5 p) M9 V! a
' n4 H, c% Q1 g- x! E% j' }5 k+ k& I4 F6 S4 f' i
开启DMA读取和接收。$ ^% |, N. ?2 l- E
其中Word = 32bit,Half word = 16bit,Byte = 8bit! B. K' J& e; N- e" M+ q4 @
6 k" J5 R+ L$ c3 A4 h% t) A, h
8 e5 H5 m8 F! {' G
. w) e& r! R' S; x1 G. e F7 v* P& ]
. @" M* T6 K9 Q! l: W7 ]5 m& F2 t" _; m
" }7 X' {( I) l; c. \3 r' M
keil配置$ e |5 G( S+ A7 w. w
microlib 进行了高度优化以使代码变得很小。 它的功能比缺省 C 库少,并且根本不具备某些 ISO C 特性。 某些库函数的运行速度也比较慢,如果要使用printf(),必须开启。
; ?! g$ J5 j) B& E
* ?' m) Y( z8 i! U+ Y
# x. ?0 H6 R- @$ U+ \ k2 X7 Y7 E( V- {3 l
串口重定向* S$ M5 u* A# A: E7 t% H5 c" T$ V0 q
在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。8 F7 K1 X$ }( V7 I
1 T0 _- Z% `5 Y/ I) R
- /* USER CODE BEGIN Includes */
0 P; z# k( W0 T1 Y. `5 [ - #include "stdio.h"0 I, E& U v: r2 O9 i* J: q' x
- /* USER CODE END Includes */
复制代码 # _( ?. ]* m. f
函数声明和串口重定向:
, p2 g1 z: G: P9 G5 h) P& y; b; _2 t5 G7 \
- /* USER CODE BEGIN PFP */; U" O2 b. A8 ]! K
- #ifdef __GNUC__ //串口重定向+ a8 C! H, u1 P1 R
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)+ ? v* x# w8 O8 }( S' l# v
- #else7 K( x. b, W; I: W' C7 J4 N
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)8 C8 C( A" f. p" ^5 y
- #endif ' c; ?+ f7 `* m$ k) T1 Z
- PUTCHAR_PROTOTYPE# V5 {% S$ m+ b$ T
- {0 I' A- H$ K' v l) T
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);, M& T3 _1 e: r5 X1 \
- return ch;
" }; V, c( {) _3 ]8 \ - }
* Y: B: u( h) P3 \# T% q& V - /* USER CODE END PFP */
复制代码
+ v# B' a* ^; ~串口接收发送函数
; M. t% H8 ^3 I' _* V- x一般情况下,串口接收发送函数有如下所示。1 O: e, Y+ J& d- B/ ?
● HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。. }9 i( K. k4 G( D7 {
● HAL_UART_Receive();串口轮询模式发送,使用超时管理机制。3 [% n% u& {4 b: I7 E3 b! k
● HAL_UART_Transmit_IT();串口中断模式发送- |5 f: x" E+ p1 Y) q+ [* G
● HAL_UART_Receive_IT();串口中断模式接收
1 U0 {' O8 Y1 z● HAL_UART_Transmit_DMA();串口DMA模式发送
# K4 t5 z) }" A● HAL_UART_Receive_DMA();串口DMA模式接收
6 E; i, D) _0 J5 f4 X+ y! I$ I. Y+ X3 K! d0 Z9 s& ?) x
HAL_UART_Transmit_DMA()发送' n" D/ Y: u. R/ [/ @* x5 x
测试代码如下。% `8 }( q" j- A+ R0 @
定义需要发送的数据。" J- q9 f6 |) I7 M
$ L' w% P8 r9 v5 G- m+ H- /* USER CODE BEGIN PV */9 A6 }, G3 l5 g4 ]7 ?
- uint8_t TxData[] = "\r\n**** Hello,World!' ***\r\n";
/ P( s- g0 w9 |' O; a - /* USER CODE END PV */
复制代码
0 h3 ^- q7 Q: P! _3 h" }/ I! yHAL_UART_Transmit_DMA()发送代码。
/ @+ |% s' s7 y2 Y, t3 q, j9 @
Y- c u8 z% Q- X$ O4 U, o+ u- /* USER CODE BEGIN WHILE */% @$ Y5 s ^3 f' p- s
- while (1)6 v0 X( V( H3 a4 x( T
- {
8 P% |0 l) Q0 o" o. l' h( n, r - /* USER CODE END WHILE */9 ~5 b, f+ t. C+ r; n% v
- ' P( S2 R' G$ `1 o8 j
- /* USER CODE BEGIN 3 */
) C% p8 q8 i8 m% r- u% L - HAL_UART_Transmit_DMA(&huart1, (uint8_t *)TxData, sizeof(TxData)-1);
: _1 L2 r; I% }9 Z! p7 b - HAL_Delay(1000);
1 b' p$ S4 i8 e# E- { - }3 t9 x0 q" k8 t0 I
- /* USER CODE END 3 */
复制代码
3 C! y3 l# \! a5 Y+ [9 ~/ p3 t; ^DMA有normal和circular两种模式。
, a. E& \. Z7 c$ F: E; hNormal表单次传输,传输一次后终止传输,所以需要传输几次就需要开启几次,Circular表示循环传输,传输完成后又重新开始继续传输,开启一次后会一直传输。2 d0 n) C( X' y2 W: I- P: X
normal传输打印如下所示,传输完成就关闭。
- ^7 }, ]% R. Q/ i9 e
' O4 E4 n; e* N1 b
7 u) U/ V% c4 B6 e3 v
5 m, h; x6 b: a$ j8 z2 C4 ^circular传输打印如下所示,一直传输,不会停止。
7 Y8 D) C4 ~8 x7 \' ~/ l6 O) u7 o# ] r& \1 p3 E
+ i+ f, \! [0 D) C3 P5 m3 A, d4 D! {7 N/ N
HAL_UART_Receive_DMA()发送
. c/ K8 W& z. Y! B' i) n测试代码如下。
" P1 ~4 H/ d, C1 C4 c定义需要接受存放数组。
' V( f- U* I. K, Q) `+ ^
9 w5 |2 W6 f7 r3 {4 W8 \/ _- /* USER CODE BEGIN PV */
" ]" b+ X+ c4 m, P - uint8_t RxData[255];$ s: P6 H/ n7 @0 O1 v7 y2 ~" S
- /* USER CODE END PV */5 {- {+ A0 M: C" I
复制代码 ; Z. T! g+ Z/ Q$ C* p3 f. f
开启HAL_UART_Receive_DMA()接受代码。
" o" X2 _5 q, ^: o: @1 p8 d4 ?! Y; s! L" \* W( }
- /* USER CODE BEGIN 2 */# Y$ O8 ^6 U0 b9 Y% e; G, p
- HAL_UART_Receive_DMA(&huart1, RxData, 10); // 这里加这个函数,接收数据
; S& j" [6 n- g2 D) S0 K8 K - /* USER CODE END 2 */
复制代码
& d0 k& J' f9 I! x. G' Q' h重写读取回调函数,将接受的数据发送出去在开启接收。+ {! g8 [ k& u. w) F2 B. X
6 _2 O! m. v: G# F- /* USER CODE BEGIN 4 */
1 {/ t& n* E; x- S9 c5 r5 ] - void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
" l3 o8 w* Q# A1 x - {
6 p) \4 S0 S7 q0 G& p - ) W! t, H1 Y/ H* G% W! f6 b2 ]9 A
- HAL_UART_Transmit(&huart1, (uint8_t *)"text:", 5,0xffff);//轮询发送,不然可能发送不出去
* T6 G% I, Y3 T! A$ q# v - HAL_UART_Transmit_DMA(&huart1, (uint8_t *)RxData, 10);//发送接受的数据
! \2 U/ ]1 N3 p( r5 l( W - HAL_UART_Receive_DMA(&huart1, RxData, 10); // 这里加这个函数,接收数据
0 _6 ]$ b5 [7 V - }
- K# v& [1 D9 W1 X - 6 L7 W" p# P$ G
- /* USER CODE END 4 */
复制代码
8 q& x0 O% j$ I* d2 Z5 ^DMA有normal和circular两种模式。
* N3 d) I& Q2 E9 L0 t) }& a# gNormal表单次接收,接收一次后终止接收,所以需要接收几次就需要开启几次,Circular表示循环接收,接收完成后又重新头开始继续接收,开启一次后会一直接收。' F; ^; a9 b1 i1 ^7 ?5 J% J( c
normal传输打印如下所示,传输完成就关闭。
" ^' P' m: @4 ~3 M$ u6 `# Z! m演示效果如下所示。1 r" x) c ~ t8 Z$ d, \# |
6 r9 N. G% d. y. D0 k3 z9 [5 D1 B; V
8 k5 n6 k q5 |+ L2 T
5 }' t; \ y: G: E% |) s/ @7 Kcircular接收打印如下所示,当发送数据大于接收长度时候,会进行循环接收。
# q) T4 p3 }* h1 W7 O K+ R4 K7 y
0 r% ~+ H f/ M' g# K
————————————————
/ }7 W0 F. W' N版权声明:记帖
4 k( E8 m+ D6 _: K+ f( s; M% u' O, z" T, {9 x
# O( @- x" s r' f" m |