1.配置系统下载程序方式
3 P, ~2 l1 p+ y5 k) `2 {
: m% m( X% w: M9 ], L; u# n
3 A# x1 h/ W0 D: k/ ^. I3 y% t5 D) k4 |+ @( k2 Y
2.RCC外部晶振& C3 Q0 P* e; W
# I/ B& w, [5 @% u0 W0 a
% R/ S; `* h3 n' l% F$ D
) j- X, O1 |# K% h8 S- V 3.串口声明
+ X0 V2 [6 ~) N. v. D9 c6 \& E( s: O0 r- ^
1 g! q/ O, A( V5 G$ I: i
6 I) c% I7 A; Y) b: Z6 s1 U' P
- Y* `3 e3 b0 j$ Q! L1 f- Z. Y+ W) b% H! W! n
: Q1 @0 _( M! @" |8 W1 C# b
" ?8 D* w3 a) R% {! G% [4.系统时钟2 a3 J) |3 K- E- `8 G% k5 H
2 L# W8 g' y3 D- [- z1 ]3 d
0 {: a. O$ f: M
. r5 `0 B* \/ [$ Y6 Z5 I8 i" g# K 5.生成文件根据自己需求配置
& ~6 f1 T6 F7 V+ ? R
( x- ^# j- W0 Q& Q" f& R; g, O6 C$ F- x( [' S& P9 P* {
+ L0 G* U- [2 G1 P( }! P
我这设置了所有库,可以选第二个仅需求的
" V4 W: A) u( `" ^( @: l1 L/ J0 s
8 q% K& ]$ _9 T& }# t2 m5 J$ B R) X/ ?( B
4 C" ~0 |1 H6 w! B 还加了其他功能,这里可不参考,DMA要放在串口前# C$ j& e( w6 r1 q9 r' J
7 Y. ~, c8 M L$ k& Z
1 d* Z( ]2 _% P! B j m0 ^9 C+ ?+ f( H$ P+ g
6.生成后修改
* b( j2 ]" q& }, A% j
! ^: \6 R2 S2 a; p Y9 w0 o" x6.1 usart.h
1 {- Z9 O. G0 G# F6 k
# Z9 G- ? A# {, Y- /* USER CODE BEGIN Includes */
7 C( V8 }& p$ W' C/ \ - #include "stdio.h", t3 Q/ k# i3 V4 y
- #include "string.h"* w/ C. D* N6 E( R
- /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */
. e# I; r4 C, p$ M) Y' S - , L5 I `9 ]+ u" a
- #define USART1_DMA_REC_SIE 256
+ Y3 w# ~4 V4 g+ [ - #define USART1_REC_SIE 512" a' W1 {0 w. d: r1 O& K# |( C/ g! A
- #define USART_DMA_SENDING 1//DMA发送 * P! o- Y. I z. L7 v( g. X }
- #define USART_DMA_SENDOVER 0//DMA发送结束
: T% ]2 m ]) d - typedef struct
; |+ d5 [ c0 F8 g. I - {
9 D* K1 P7 c* _4 s; n# T9 n+ v - uint8_t UsartRecFlag:1;//接收标志
! }* Q( }& w/ R7 A/ z _ - uint8_t dmaSend_flag;//发送标志 T: G ]. Y) `! U5 e; b
- uint16_t UsartDMAReclen;//DMA接收长度8 `9 C6 @( d3 O4 h; V' r# P" q: G9 y
- uint16_t UsartReclen;//串口数据缓存长度& H, w+ Q( O/ f* \
- uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据9 o0 V; l2 i0 c4 L9 s
- uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据6 w. ]) ~$ s# u% K% x
- }teUsart1type;3 i% W* v; l. F) |6 {6 K+ ?
- 3 g/ {' M0 _& w8 C
- extern teUsart1type Usart1type;//定义数据0 A' s# E$ N" Y* ]- v2 V' M" Z
' t, z( [- ^! S1 C: M' Y8 J- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
" `' r2 c2 r: l6 j! ^4 w0 | - void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
. D* V$ O0 Z. b8 `' _8 z: O9 ]3 @ - void Analysis_Serial_Data(void);
3 i) E0 M( [5 k, M) G, S - void EnableUsart_IT(void);
7 u- ]5 m8 _) \2 {
- \- W2 Q8 X0 m- /* USER CODE END Private defines */
复制代码
3 e* j! U! d$ D# Z( n4 Q6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
8 x$ D1 l) i& R( v
8 E8 ?* H& C8 @: v- teUsart1type Usart1type;
+ b3 s9 T7 v! d$ T/ f) ^9 g+ M - /*****************************************************************************0 X" _% N; C/ Z
- * 函 数 名 : EnableUsart_IT
6 F" y% o2 v1 T2 H p+ ^ - * 负 责 人 : by* ~7 I9 P( u% ~4 [6 Q6 H: S
- * 创建日期 : 2020年8月26日
: S: [- t- Y0 W" O @0 P: e - * 函数功能 : 串口2初始化函数,空闲与DMA中断
$ w7 t: B5 Q( Z2 o% V. h# Z - * 输入参数 : 无
5 h. z, V$ Z! o6 }2 m1 ]( X4 S - * 输出参数 : 无
" l; c" n- l" K - * 返 回 值 : ( w5 d# L3 w$ B( `4 ]+ F2 y
- * 调用关系 : 5 |6 c" C1 u" V- i# \3 Y
- * 其 它 : # h" f' F5 k% E V
- *****************************************************************************/9 z8 C( ^+ s2 p! f: h
- void EnableUsart_IT(void)5 ^8 T; e' D0 }! L5 t
- {
% X# D0 V9 l, Y; H! ]! Q' H - __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
' t h8 m, k5 W. G - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断1 y6 [# A2 ~9 B; Z7 H: B/ L
- }
7 D9 v( X( X, W& _1 f2 \+ y' }8 o - /*****************************************************************************& R- I5 G& B) I% E. C: [! L$ |. z5 S
- * 函 数 名 : Usart1SendData_DMA
5 a$ N0 z. W2 }# Z/ L - * 负 责 人 : by- ]; k' `* N9 C0 ?1 r8 V
- * 创建日期 : 2020年8月26日
9 s( }6 I8 a4 K4 z - * 函数功能 : 串口2DMA发送函数
( w4 @* E# k' T- f5 y: a7 ` K' m( E - * 输入参数 : 无
% ` T% Q! R* Z# y" ?# t+ t - * 输出参数 : 无( _/ A6 Y, `" K* ?/ M
- * 返 回 值 :
. a0 |) P3 y5 y4 f- B" P - * 调用关系 : 5 y/ l+ G& @7 c( Z% m" F
- * 其 它 :
3 o/ w0 A- k6 b9 M2 t - *****************************************************************************/
$ X6 H: e; v' }7 j" [ - void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length) 0 x* W, c6 C; v# y: S9 n* N9 z
s+ u& b4 W) }0 b" Q$ v3 x% k- { 3 B. @: D2 j& A4 H
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING); % r) B8 L# M+ x
- Usart1type.dmaSend_flag = USART_DMA_SENDING; 8 q* _, Z: e" i5 ?0 a. U, r. a
- HAL_UART_Transmit_DMA(&huart2, pdata, Length); i! i5 i2 n) F
- }
1 Y& f, i- [* n$ Z - /*****************************************************************************4 K: G: d% u" `: q7 C [
- * 函 数 名 : HAL_UART_TxCpltCallback
6 E. F2 c1 C: l ~- m - * 负 责 人 : by
, m- l E/ y7 Z$ u - * 创建日期 : 2020年8月26日
% ~2 n% u1 p& P9 q- t - * 函数功能 : 串口2DMA发送回调函数
- J V' d/ i1 @ - * 输入参数 : 无! X0 S/ E/ C: O `
- * 输出参数 : 无
( D) G/ F9 R! N2 m! B - * 返 回 值 : 6 y" }1 A/ F0 }4 j) t
- * 调用关系 : 7 h2 S+ `& Q$ C, d6 C# }5 e
- * 其 它 : - W' Z% c+ L2 v$ P1 N6 `" N- T
- *****************************************************************************/2 S% _" J7 c1 O3 K
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
: p+ @0 e6 L5 |6 J: K - {
& y& @4 H; c# f- ~/ l - __HAL_DMA_DISABLE(huart->hdmatx);
0 F! T, ]2 e9 b5 i3 k. { - if(huart->Instance == huart2.Instance) ! W0 T) @% T2 N8 E H0 J4 X
- Usart1type.dmaSend_flag = USART_DMA_SENDOVER; : J# [: N/ I& H+ O. b- E0 Y
- }
0 k' j" h2 L. k! T' ~& s8 I1 z - /*****************************************************************************/ p$ T' ]( G7 w" A# T" L
- * 函 数 名 : UsartReceive_IDLE4 J9 w4 s! j: B: h0 q; o
- * 负 责 人 : by$ i. \6 x- x5 \) P0 Q
- * 创建日期 : 2020年8月27日
' u8 u; A: G9 |/ i2 K" W - * 函数功能 : 串口接受空闲中断处理函数8 ?" {+ t2 m' w' ?) ?1 d
- * 输入参数 : UART_HandleTypeDef *huart 串口句柄0 `4 H! a6 k7 E! f
- * 输出参数 : 无- N- h8 K% H# ~1 X) E6 ]
- * 返 回 值 :
* I3 @7 O5 j8 K* T- L3 J7 L$ _ - * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收
7 T6 @' i& g* d& |. G" U: [ - * 其 它 : 0 ^( M d; T% w; D/ _: W) Z/ s
- *****************************************************************************/
: G" r [1 k5 J/ C& r7 ?8 f A - void UsartReceive_IDLE(UART_HandleTypeDef *huart)
3 C6 w3 o6 H- L: { - {
" i Z+ d3 S5 S) G - if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
/ R2 \0 T' l' r9 Q1 }& x) h7 @0 ^ - { H9 K( r$ O3 _ e$ u$ p" x
- if(huart->Instance == huart2.Instance)//判断是否为串口2
. [: H1 p. X; I" l - {3 U3 ~3 F% a7 W- u7 |* ~) J5 u3 e) f
- if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断' X6 q1 V" A1 Q/ ~+ `# F+ l
- {
4 i4 G5 P F! |' `( H" u - __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
+ ?) r! |. b6 h8 f: K. s - HAL_UART_DMAStop(&huart2); //停止本次DMA传输7 k# F* t3 i% q' d
- Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度2 m5 H! L- a+ ?1 }
- if(Usart1type.UsartReclen>0)5 o, J6 }, {& x
- {" f; l; m" k6 ?! i
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen); b) f3 k' p3 a0 k( N6 P
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
# N& d# M. I$ V - } : o) f, }/ f5 b9 J6 R
- else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录" ~0 G- Y% j3 m& l; s0 l3 Z
- {
* n! v% H) K( b' j }9 v! r - Usart1type.UsartReclen=0;, P3 |- g* A$ D9 A9 b# w- N
- }
& h" L2 c: S. x* L3 b! P6 F2 j - else
4 Z+ R, i* S! G. V, d - {
/ z3 E7 y+ _/ s+ @' u& V - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
8 i& [8 F2 J% H1 I, v - Usart1type.UsartReclen=Usart1type.UsartDMAReclen;& ?! Y6 I. X) a. e$ O
- } 6 f& q$ N9 [: h/ P% J
- memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零 5 w6 i( ]$ i1 Q/ z) ]- R! s
- Usart1type.UsartRecFlag=1;//空闲标志位置1
1 `0 `- X0 y+ W! r* l5 @. |* d - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA$ C- X3 w- K8 o7 N- @( E9 ]7 q& W
- } 5 S5 Y2 C7 z3 X& O
- }
) j v% n: x! u& p" Y5 h - }7 b$ M3 U; Z4 _* F$ ?/ F
- }
3 @# b% z {& F4 y/ b - /*****************************************************************************
; x A: ^! S/ r1 R" A4 G! a - * 函 数 名 : Analysis_Serial_Data
, ~ D) n! k1 x& |5 {+ u+ o - * 负 责 人 : by# ^ K# Q5 ]. u+ L
- * 创建日期 : 2020年8月26日( q4 b; \1 b' h) c
- * 函数功能 : 串口接收数据直接打印
- i* s1 [, L, s - * 输入参数 : void 无/ b/ ]! Q' a6 K6 r$ o) I" n1 z# T/ m0 X
- * 输出参数 : 无* Q2 ~7 [3 { Z* J
- * 返 回 值 : void
9 ~. N6 A3 a% X7 _, D3 w - * 调用关系 : ) f, s! }2 K. Y1 m6 U& k, u
- * 其 它 : 4 d7 E4 r9 h# _$ d/ B
- *****************************************************************************/
6 o3 k$ h0 I6 y F% W - void Analysis_Serial_Data(void)
- E( r3 x/ Q7 j0 ^ - {" Y. `0 c" m7 I& u5 y' E
- if(Usart1type.UsartRecFlag)
t( B2 @* C! U+ ]% } - {
8 `- n$ J, f1 U" @ - Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen); , z' K7 U, W! V+ H# G
- Usart1type.UsartRecFlag=0;
4 E8 Y& y) e- ^/ I6 t7 |% }$ @ - Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理 5 i$ T5 c/ u& ]
- }8 l; @" ?' C' E; M& v4 \
- }/ k( H& s6 A {
- /*****************************************************************************6 m2 e( M& T" {% C3 m) t5 d
- * 函 数 名 : fputc/ I+ `2 I7 h1 N8 U$ U* `
- * 负 责 人 : by
% M! ]4 T2 S0 u9 U H" {" Y - * 创建日期 : 2020年8月26日& R- u1 ^; g3 J$ v$ p8 K, H
- * 函数功能 : 串口2 printf重定义& H. D5 Y/ Q9 t# T, `2 H7 I, o
- * 输入参数 : printf(d%/s%/%c,a)) }# b) I9 n9 h1 D4 @0 a2 S
- * 输出参数 : 无- X* H/ ~$ m4 T T( }
- * 返 回 值 : 2 u1 v: ^/ N3 z( Y: ^4 p
- * 调用关系 : 3 g) N. {) B. u
- * 其 它 : 9 W5 b' r: \2 ]
- *****************************************************************************/
2 c0 Q- J J1 G% c7 y% x! Z$ X) Q - #ifdef __GNUC__# _% D. A$ I8 `) V7 A X
/ J" ?2 H" G! | Z3 x8 M4 A- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
/ t& x" ]+ l E. s( i - set to 'Yes') calls __io_putchar() */4 M9 o Z) a' a2 b
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
, E3 y1 n; Q+ R& B2 Y: |# } - #else ^* M5 b* {- N( i9 d! f
- # @) k' d' B& _, h5 z( ^, v
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
" l7 z1 p4 @* F A) W - #endif /* __GNUC__ */
; @1 f- x I# ^4 e - 3 {8 {, X+ L' D* c
- PUTCHAR_PROTOTYPE
5 h& n% X) z6 o- F* b; ? b4 K7 N Y - {0 I, s* U/ K( T5 _; J7 F
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
; s2 E7 H# x- I1 F; W0 T& Y D' l - return ch;
+ Y9 Z8 w+ a+ ]; A- }; R2 o$ _/ } - }
, W! }9 ^8 d5 A# ^( q0 A4 Z, ~ - 8 s. e/ n) a; c5 P( T p6 n! c
- . D7 E4 h# }! _0 P) }7 D$ m
- /* USER CODE END 1 */3 B6 y. O8 R( g% n5 d! W8 x, D
- DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。 X9 j4 ?. e; K4 _. z {
- / i7 ]" e$ c* X$ {5 l, j
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
3 T4 E% ^$ Y& L - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
$ x4 [. W# T3 y3 r6 F" o/ @ g/ ?6 Z1 v! N0 ~9 d
6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */
/ g. S: A& [6 }! |; e ^8 P }8 E - HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
2 r4 J0 j9 a( u - HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/1 j; k9 j2 V0 ` v
- HAL_CAN_Start(&hcan1);/*can初始化*/9 u: U1 S: p$ L1 l; o$ h7 `
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING); 2 j0 }+ B, e+ e1 p/ X4 I
- EnableUsart_IT();/*串口初始化*/6 e( u. L: }3 ]0 }$ f6 c/ b
- CAN_User_Init(&hcan1); 8 }" X7 E7 n; W. v
- /* USER CODE END 2 */
复制代码 . A P2 P% N6 x2 a1 r$ ~ s/ T" g
循环,对应数据输出6 ?; l* ?" {& I6 Z" ^* Z
6 W( d, h. f$ X7 I$ |- @
- /* USER CODE BEGIN WHILE */
5 s! z- u/ m" N - while (1)) E6 f$ H$ P% i, }- g" b
- {
& y% V- u. W. g# x - Analysis_Serial_Data();
8 F" u" P4 p$ K" H" w3 z - /* USER CODE END WHILE */9 P* L& ]+ P8 k$ K6 @
+ c, T" {: F! K6 C3 s4 t% O- /* USER CODE BEGIN 3 */
: |* A% ~: }& L - }
: c; s1 C. g: Z. b - /* USER CODE END 3 */2 c! H" l' x, D, w; V: d( |
- }/ l8 S' X0 Q0 S% w9 ~5 K# G
- 7
复制代码
7 b0 }; t+ a! }) S$ j T" z、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误) I# V, O# x. |; e6 y* i% {; R
2 Y% ]$ s% \# a# p. |3 m4 U) S }
* x. b: O/ g. j: `1 s: h% p% w- D, ~0 v9 o
|