生成例程
9 s/ r. P& L/ M0 B5 g使用STM32CUBEMX生成例程,这里使用NUCLEO-F103RB开发板
$ `* n7 h$ E! M; s6 V5 @6 B" I6 O0 \# L B* V6 m
- C* \8 |( e$ }& C. c q+ n
* z$ W6 |: K) R* i& w
查看原理图,PA2和PA3设置为开发板的串口。) ~0 J4 B: w# U9 L( k5 i. S# N# ]4 e' d% Y
. I! m+ y4 t' g& U. a3 L
: I$ v- O3 x3 I0 \3 J0 S/ [
配置串口。
& r& h5 q7 Y; L: a, E' M- p, _8 t0 c5 Y9 M& n5 D4 ]
+ D& ~( f8 ?: g
) e. Z7 G8 ?6 i. H% y0 C
开启中断。
: s$ Q5 w$ f& A* t4 f* v! V. e$ {- Y5 G! z
5 }5 i% @. d5 k, G& D
0 F7 N+ d n' W5 G$ f开启DMA读取和接收。7 _$ H) ]+ u- i, u8 {- L
其中Word = 32bit,Half word = 16bit,Byte = 8bit5 c9 K9 f4 g5 x
, c0 h7 J. A% l) t0 i
8 G* o1 E [- S0 Z9 d2 y/ I9 N7 Z
8 l- ]/ N! b$ y. z" QSTM32CUBEIDE配置
; e7 f/ @3 y3 Y1 _! a' C: G4 K% p5 M' e6 X
~, `; q4 h3 D
7 g J2 D$ D, P" t: X4 ?9 d
若需要打印浮点型,需要勾选下面的选项。
$ W# I9 w8 a' {( x& m/ |1 k6 G6 W* l
5 Q/ E* x' ?# p) A1 z& @; o! R
串口重定向# q1 H. G; x6 I
在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
1 C& @9 U/ w) T' w) s5 U, |, J( ^( f2 c; U8 h& P
- /* USER CODE BEGIN Includes */6 h. Y, b; R9 ]! {4 u
- #include "stdio.h". Z" {5 s+ w) i R
- /* USER CODE END Includes */
复制代码 8 Q6 V B( B0 D' |
函数声明和串口重定向:
5 w5 ]; Z9 U4 G4 J" E/ v" ^, y5 y( o) B: S. K
- /* USER CODE BEGIN PFP */* f8 \. M* m. [; [
- #ifdef __GNUC__ //串口重定向 N4 h; p4 L: t0 \+ H- c% I/ y+ r
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
" K0 t8 I6 c' H% a9 O# n6 i - #else) I. H' e3 V/ d" g) \
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
P9 Y- g3 m# y& W/ `, R - #endif 6 P8 ]# P2 n1 W }& C9 N# }
- PUTCHAR_PROTOTYPE6 \& q2 z' v1 x8 i. f
- {6 d. C0 v. q3 I7 ^
- HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1, 0xFFFF);) C6 g7 r$ W' H* K+ y: z
- return ch;
" ~$ D( O; f# j6 U: _ - }) I& Z- w V! ^( G% G+ b) U) y! {
- /* USER CODE END PFP */
复制代码 6 {4 [$ E, T5 H9 T& K$ @" z6 r
串口发送接收函数
. m8 A. d2 W6 ^. m7 O( b% }一般情况下,串口发送接收函数有如下所示。
1 g& x8 [6 P; {6 K● HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。2 g4 Q2 @5 }4 E& S
● HAL_UART_Receive();串口轮询模式接收,使用超时管理机制。
. L/ o% x0 A ~: U5 M● HAL_UART_Transmit_IT();串口中断模式发送% C/ |. l( E2 P
● HAL_UART_Receive_IT();串口中断模式接收, v( C6 |/ ^& K+ s) l& p% d/ b
● HAL_UART_Transmit_DMA();串口DMA模式发送3 O% ~% x3 I% q1 H% N' \
● HAL_UART_Receive_DMA();串口DMA模式接收
* L" K |1 I3 m$ |/ k
( s# O8 b+ L% X; L- aHAL_UART_Transmit_DMA()发送
% b8 Y: L' k6 j# w4 y测试代码如下。
0 ]% Y+ w1 d; s9 f: H8 _定义需要发送的数据。& z8 r% q8 _/ K% F
8 D* ], m) O2 \9 U0 g- }) K& |# m
- /* USER CODE BEGIN PV */
* S4 j( x) E$ y6 y: q9 F - uint8_t TxData[] = "\r\n**** Hello,World!' ***\r\n";
) V l3 I9 {6 F3 h) c# h$ Y - /* USER CODE END PV */
复制代码
2 W8 r7 d. a2 q wHAL_UART_Transmit_DMA()发送代码。1 [: e7 p r; Z/ U* E
x+ e% [8 L) n F
- /* USER CODE BEGIN WHILE *// b+ I1 E7 X0 d
- while (1) @) r P& o' n% N7 R1 f8 ~
- {2 |; p' D. B2 R9 g+ A
- /* USER CODE END WHILE */
$ ~: R) `, X1 Q; Z5 p - + u3 \0 N6 b9 ^' ?/ @# L, f, ]
- /* USER CODE BEGIN 3 */
1 y6 h+ p& w t( M - HAL_UART_Transmit_DMA(&huart2, (uint8_t *)TxData, sizeof(TxData)-1);
: ?4 b5 j) S; l ^2 K9 D. L - HAL_Delay(1000);
0 z6 d+ b+ d( K# C - }
4 b8 Y6 {" @: W$ r7 N9 w; Z& k4 J - /* USER CODE END 3 */
复制代码 & p9 R2 k4 [+ t( q, e& z3 S
DMA有normal和circular两种模式。
+ c D! c" w$ ~4 @% v3 mNormal表单次传输,传输一次后终止传输,所以需要传输几次就需要开启几次,Circular表示循环传输,传输完成后又重新开始继续传输,开启一次后会一直传输。. q; k! f$ ?/ Y* g6 x6 N# I2 L
normal传输打印如下所示,传输完成就关闭。* P" b0 Y6 m6 T* s6 s
- C! b! f7 w9 Z* I: O( x$ z0 H
8 A9 `6 V) R9 J0 D& i/ H z0 h; R! R/ l
circular传输打印如下所示,一直传输,不会停止。' {6 q* |! V+ N: B
3 S/ x: t) d; s6 i8 [
" r4 |0 H4 g$ }% L5 |: L' Z7 |2 ]
3 F% u5 f2 p6 e. F5 N) g( d: F/ d) e5 ^; S2 p' r4 s; h
HAL_UART_Receive_DMA()发送
9 b7 p; K+ o: j测试代码如下。
* J- }% O7 p) b定义需要接受存放数组。% M6 ]" c! b! ]1 i/ a
/ ^ v( _0 n7 c* z" Y ^- /* USER CODE BEGIN PV */( b5 k0 M$ [9 H# F3 T
- uint8_t RxData[255];' j3 h5 V/ g# @0 E* f+ o4 a
- /* USER CODE END PV */
复制代码
' D" {; A B# s r9 n6 E5 ~开启HAL_UART_Receive_DMA()接受代码。
% C' x% f( A/ L$ h1 U0 P8 Z, j: R. B6 B2 A# f3 T6 L, j7 s
- /* USER CODE BEGIN 2 */
6 v9 v+ D$ o3 V" \5 | - HAL_UART_Receive_DMA(&huart2, RxData, 10); // 这里加这个函数,接收数据
6 ?& `* }: T2 b% Z) z: G# M# X7 D$ L - /* USER CODE END 2 */
复制代码
) ^" J' c' E |3 | @重写读取回调函数,将接受的数据发送出去在开启接收。" p+ T% F9 T$ k' {; Y: g( w3 G
) f7 v: v! g7 x6 c! ~- /* USER CODE BEGIN 4 */! o3 C+ o5 R% Q7 T
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)# z5 y+ u4 K* G2 r; k& \
- {
( d. T8 x! l4 ?6 }- f# @. X7 v
/ H' V9 `- j N- HAL_UART_Transmit(&huart2, (uint8_t *)"text:", 5,0xffff);//轮询发送,不然可能发送不出去. [# }6 p; w% i K% d& U# x2 Y# C
- HAL_UART_Transmit_DMA(&huart2, (uint8_t *)RxData, 10);//发送接受的数据
) m2 t' L) L9 ?) d& V - HAL_UART_Receive_DMA(&huart2, RxData, 10); // 这里加这个函数,接收数据
$ M! F& l! G: F, }; K - }
1 k7 M0 _0 H2 [( i* S+ @& R - ! m* q6 V4 R' |9 a
- /* USER CODE END 4 */
复制代码 - y3 S2 ?# R! \' o% x. c
DMA有normal和circular两种模式。9 ^3 ?! S$ r, {5 i8 H& c8 d
Normal表单次接收,接收一次后终止接收,所以需要接收几次就需要开启几次,Circular表示循环接收,接收完成后又重新头开始继续接收,开启一次后会一直接收。
5 T. n: V7 y b0 snormal传输打印如下所示,传输完成就关闭。8 f$ ^* r5 w0 z! c
演示效果如下所示。
$ A' @$ z+ V6 Z9 _0 s, g2 w F' B3 a& ?
7 k+ x2 h4 j2 c' E5 @ Q% \- }) F! E9 Z9 g* ?7 U# {
circular接收打印如下所示,当发送数据大于接收长度时候,会进行循环接收。
5 M& S% l0 S2 x1 T
4 Y7 c! X6 G( ^9 I6 v0 k0 ?* f
0 Q* B# q5 S [1 ^, F8 T7 f
% a: x! L: \: p5 T" w5 }/ q- K; Y
) l$ ]& B% d; D) J/ f% y
; O" @8 C* Q/ [3 s3 \* L |