生成例程& A6 J6 z* k6 {2 d( Y: T% K
使用STM32CUBEMX生成例程,这里使用NUCLEO-F103RB开发板
( \) o) ^' o" v( r, @: ~2 Q8 v5 g& N" J0 l" Z
; _: n y1 _2 l/ S$ q( ^. v, e# R: n% E4 S3 V3 `
查看原理图,PA2和PA3设置为开发板的串口。) D1 A: t( O! A5 _2 R3 {. \7 e
: X, c- \$ o3 x& W7 r. ~8 x- o$ Q7 W$ G1 g# _2 p/ H
配置串口。$ [" B2 F! ^ w
# \7 \* v. ?% T! J. \
( ~9 l7 b) r5 w; W
* _& u% p% w( t2 P. J) R( z9 A开启中断。8 t9 l& k' N. W& m
# j% [; x: s+ a: G& Y+ |/ w
9 {% t- w! t, n( }6 y, F0 S& P5 ]! ^" z% g% u! }* _
开启DMA读取和接收。6 w9 W- ]$ i1 T
其中Word = 32bit,Half word = 16bit,Byte = 8bit
- h/ ?% [& A N" R5 r; D5 Z
9 [6 n* e0 X9 N$ ~# Z
" n' V+ a2 h- _+ Y
6 J8 ?, ]2 S3 A o' pSTM32CUBEIDE配置7 \7 a- R) K6 Z, g6 I( x& D
. }* x8 }1 n) A9 q' }
4 Q, k) i9 ^$ Q2 p2 f: s
( \/ c4 C+ f! Y若需要打印浮点型,需要勾选下面的选项。9 T4 q/ a: @6 D; j. T
1 L1 `' ]2 m# h z& {
1 A$ W3 B# g' |+ a' Z6 J
6 R7 ~" N6 i0 a' {* z/ R& O& v
串口重定向
/ ~8 y; i" P$ A0 G6 A+ R3 D' U在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
* n' }2 ?) A$ |$ t8 Z2 s* c# _9 T7 ~1 W- o' J' j/ o0 e: R6 X
- /* USER CODE BEGIN Includes */
' o! f6 M8 h/ u9 |$ a5 B - #include "stdio.h"
5 ^) [: |) [/ U( r$ q - /* USER CODE END Includes */
复制代码
; K; C* F0 n" m( W8 x& }/ s& {函数声明和串口重定向:; J! }/ U$ r4 v- H! f! ]
9 k* U5 y( A4 G& v- /* USER CODE BEGIN PFP */& n2 O5 @3 D( @- V& Z9 Y
- #ifdef __GNUC__ //串口重定向0 E% C& U# o! u& F& g4 p, j7 A
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
2 s# J% X1 T% O9 t% Z - #else I) y" m) a3 {# y( l
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)5 x3 ~; s9 F W1 y# L' T
- #endif - u5 ?. ~ |- o) t! O4 @" U3 h
- PUTCHAR_PROTOTYPE, Q, a ~9 ~' n
- {
/ R" y% a- m! o- h1 R - HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1, 0xFFFF);' r. H( b t( T% B: G
- return ch;
8 d1 K( G- l) I- a) I- a - }# f% g: w6 S! o1 _: t( {
- /* USER CODE END PFP */
复制代码 3 R, H d6 n7 f: V* s% F5 B7 e
串口发送接收函数0 } b- ~9 N. \7 U5 r/ C
一般情况下,串口发送接收函数有如下所示。0 \7 N; {: h$ v
● HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。
2 n: T8 v* P- I6 h. u● HAL_UART_Receive();串口轮询模式接收,使用超时管理机制。 ?( x" z) Z8 c2 p' n
● HAL_UART_Transmit_IT();串口中断模式发送, G# }5 U* Y. x& q
● HAL_UART_Receive_IT();串口中断模式接收
5 s( g R1 ], F, c( r1 {# P● HAL_UART_Transmit_DMA();串口DMA模式发送
. m7 \7 c4 M, d Z● HAL_UART_Receive_DMA();串口DMA模式接收
( t2 A7 G) t( ^! S$ `
. L" T2 j" y/ @/ B6 A" IHAL_UART_Transmit_DMA()发送
. X: H, H) }( P8 s0 Z) x) ~8 r$ w4 N测试代码如下。8 G4 s& u& z5 P8 S; J
定义需要发送的数据。
6 D- j5 g) m1 y
6 u6 e& v3 b% `1 n" X- /* USER CODE BEGIN PV */
4 ^+ D' R- i; o' l; U - uint8_t TxData[] = "\r\n**** Hello,World!' ***\r\n";8 }" N. ^5 x [4 d G& Q- h1 n
- /* USER CODE END PV */
复制代码
/ v+ c& P) N5 L1 e8 s( ~HAL_UART_Transmit_DMA()发送代码。
: ?( ~: G- d5 p& C* d& s4 q- n+ N1 O! a0 i3 s1 l
- /* USER CODE BEGIN WHILE */
`. ] s8 L7 @7 O/ f! L - while (1)
- e3 ~, M, R9 i1 |! U6 k - {8 [: E# f; I" d# A( s. J' P) M8 ^0 B! ~
- /* USER CODE END WHILE */1 s6 Y1 S( j) e/ n0 Q
- 2 _* ~4 J) r: F/ x2 {- q
- /* USER CODE BEGIN 3 */
8 l( x% f `4 W8 G) Y. v, @ - HAL_UART_Transmit_DMA(&huart2, (uint8_t *)TxData, sizeof(TxData)-1);
3 n5 K% Q* c2 ?2 S! F - HAL_Delay(1000);
0 p! q3 H: n: W2 S - }
' Z! A8 B2 M& S9 B - /* USER CODE END 3 */
复制代码 ) D' g, i q8 Y9 w8 _8 T
DMA有normal和circular两种模式。7 n9 R! G1 d3 v7 z/ x" [
Normal表单次传输,传输一次后终止传输,所以需要传输几次就需要开启几次,Circular表示循环传输,传输完成后又重新开始继续传输,开启一次后会一直传输。
0 Y( u. O8 v7 t) u, d. p) gnormal传输打印如下所示,传输完成就关闭。
/ u( u+ ^0 J9 i9 p0 H) a% T% ]% b0 d3 ?2 P
& B [2 `7 u& S. `
H% \; d9 i6 V, A6 V: dcircular传输打印如下所示,一直传输,不会停止。
, `" z6 S) v) Q* z4 E8 \9 S% s
0 }, c* z* G7 H5 v+ h0 v! ?
; g0 U6 U; Z# {" D
9 K0 g+ L7 N" h3 F7 p/ O
4 m& U* H5 f- P6 [HAL_UART_Receive_DMA()发送% A7 K( @- Y' I6 i# e
测试代码如下。% {+ W8 t2 G$ K2 O: F
定义需要接受存放数组。# o9 s$ b+ \5 r: ^6 T
/ a& N$ p7 ]' m) A. [ K& P& g- /* USER CODE BEGIN PV */. Z9 T6 z6 A8 a. S( G1 H$ D' K* e
- uint8_t RxData[255];
: ]* q1 k. ]2 X - /* USER CODE END PV */
复制代码 3 q3 H/ u6 K0 m/ `. I! B- B) D
开启HAL_UART_Receive_DMA()接受代码。
( x( C# h: {: o) X9 H3 w# ~: c8 M
1 a4 M! I. ^+ t+ k+ M- /* USER CODE BEGIN 2 */0 k% ` O) a' @
- HAL_UART_Receive_DMA(&huart2, RxData, 10); // 这里加这个函数,接收数据: R8 N1 I; l& Q X2 |3 x x2 X
- /* USER CODE END 2 */
复制代码
* {' z! C C* W8 G) p1 k e; M: l重写读取回调函数,将接受的数据发送出去在开启接收。8 W" H. Z% e2 p! z
& l7 p! b+ v" i
- /* USER CODE BEGIN 4 */
: K0 z, ] y( d - void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
. o7 k, k) s7 _( j$ X2 D - {
5 n7 x" O4 ]: d
* h7 ]4 C$ h5 t6 g, j* T% P- HAL_UART_Transmit(&huart2, (uint8_t *)"text:", 5,0xffff);//轮询发送,不然可能发送不出去, w H% H! F H
- HAL_UART_Transmit_DMA(&huart2, (uint8_t *)RxData, 10);//发送接受的数据2 Z+ J! r* j' [; l# {7 V9 E3 j
- HAL_UART_Receive_DMA(&huart2, RxData, 10); // 这里加这个函数,接收数据
( j1 u. {$ k, T. j# B* t - }# V' ?1 z" c4 [
y6 N+ d; s1 i& ?3 R5 T- /* USER CODE END 4 */
复制代码
! W; F7 D2 S& o% o- G3 p. i2 Q" NDMA有normal和circular两种模式。
* S8 K1 a% G9 P& ^Normal表单次接收,接收一次后终止接收,所以需要接收几次就需要开启几次,Circular表示循环接收,接收完成后又重新头开始继续接收,开启一次后会一直接收。
/ N5 ?: M0 `' H0 onormal传输打印如下所示,传输完成就关闭。
( p" a3 a- y& R$ r; U1 @% k/ t演示效果如下所示。
8 g [1 Q, C/ z, B9 v4 s1 [& F( u8 F: ~0 `% h8 W+ d
& w: x( R: N8 O, \
+ e: J/ q- Y- C# b8 a4 u" l
circular接收打印如下所示,当发送数据大于接收长度时候,会进行循环接收。
4 ?0 Q: |9 [* r1 ? W; \) Q$ G
; J0 {* d7 V5 U0 Y( A
, _3 x+ c0 r% M" F
3 f' z" W' `" e, p2 r1 Y; S
+ M3 `2 D8 B4 r0 s) d- |' E. H K6 m
|