1.配置系统下载程序方式
% |/ Q' x! d; Z7 j! J
) [3 A" z8 a: X+ W! A! C% ?2 I6 M, z! w/ c
3 k A0 |: n* U! S5 O# e3 g( ? 2.RCC外部晶振
: d0 M" s. B4 M, G
+ p+ f' \ V2 l$ G& Z2 _9 q! _) K4 o
+ q* E; H/ c* o5 X" e1 w
3.串口声明( _* s! A% o$ E
; \5 w8 y4 v, H5 h* @; }2 g6 n+ e3 g' p c* S# G
; m. [( F8 R( q' k+ a: V) y' W, J6 U) i9 S+ n
! k& o [' `3 \* |' h3 l$ I- E g7 r' H) |& Z) g
- x O' M( a8 Z0 i: a
4.系统时钟+ o% ]& C, J! m( R" X) z
1 }3 h% ~5 W4 [: b
' K( ]+ p! w6 U" S% J6 j
; Z, q0 }8 ~, v$ v8 d0 r+ ?/ v; C 5.生成文件根据自己需求配置
, C' {5 [8 a3 I) |; i, E0 O* ^ w& B0 q9 _" L) S2 M4 M
; c2 g- B9 k9 V- c
! y( }4 S) A1 U4 J2 h
我这设置了所有库,可以选第二个仅需求的7 e1 k6 ?: m. C) \4 T0 h
f5 i+ H) \: ^) y
% B! ~" B. \: g# N4 e
; x3 z; Q" J8 z' {7 z# |; d 还加了其他功能,这里可不参考,DMA要放在串口前/ z( \* C X1 H+ M
( C6 `& J' g1 h. Y. n# y0 n( R5 F) p- A; `& ~* l! {( |8 G& t5 z
- ]0 w% z# F, E
6.生成后修改4 }; G2 F: [1 S; l
+ H" B; N0 [$ o7 x7 T" @
6.1 usart.h
7 ~2 m# h4 K0 ]; k/ D5 [3 X+ E
2 S! L1 D5 R- j$ E# h: {- /* USER CODE BEGIN Includes */
7 K; ?5 C2 o2 d# J) a$ C - #include "stdio.h": ]! h0 V0 g8 f# C- d% E
- #include "string.h"
( j0 T" C. b0 B$ R Y4 D - /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */
5 t* H& O. y" K/ t
; e0 @* f7 Z7 a6 M+ E1 a- #define USART1_DMA_REC_SIE 256- A* B/ B! t: W
- #define USART1_REC_SIE 512$ W$ x" R5 N; C5 f1 c
- #define USART_DMA_SENDING 1//DMA发送
5 s% N2 T' C' ~' m: r/ y! i - #define USART_DMA_SENDOVER 0//DMA发送结束
+ b/ r6 L( v* b, o1 J - typedef struct- x- j* ?- a0 n
- {
9 {5 @- _* t% [5 p$ s! ]( @ - uint8_t UsartRecFlag:1;//接收标志
7 V3 m9 D+ A9 I% s9 h: M - uint8_t dmaSend_flag;//发送标志
) f1 T0 q2 n& ^) T! [ - uint16_t UsartDMAReclen;//DMA接收长度3 }- S7 U" n8 [. o5 S; ] _+ k
- uint16_t UsartReclen;//串口数据缓存长度
Z7 D2 D1 o; {: Y, n0 z1 X9 k - uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
! k! G" X( y' Q - uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
5 L) m: b: i+ V9 H o7 K# y - }teUsart1type;! \; c: a `5 Z" K& I( n! d1 `
- ! b2 ^1 {5 u/ F
- extern teUsart1type Usart1type;//定义数据
R6 }5 a3 V, E. X
, L. U/ G( Y$ P1 |- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
6 g. T9 j& D0 U# O) d, U - void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);* U& A6 G0 }9 P C, F' z
- void Analysis_Serial_Data(void);1 z) e! \ f) s1 \8 w5 N* x
- void EnableUsart_IT(void);9 Q1 I2 t0 _% k& R1 [! Q0 D4 a& S( p
: `* N9 ^1 G+ t. \; q: q! t- /* USER CODE END Private defines */
复制代码
2 f* y% C4 g' G, i6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。( r. V. W3 {( c: ]: Q
* M3 P2 a+ v5 }
- teUsart1type Usart1type;
+ z4 A* p( q& O# o0 q3 L. ]- b0 x, e - /*****************************************************************************
, h1 }$ u- h8 j8 p% g- M9 S: v; ] - * 函 数 名 : EnableUsart_IT W) Z0 t" [+ O- s! X& d4 b3 W
- * 负 责 人 : by
/ f3 Y- ~: p9 Q7 } - * 创建日期 : 2020年8月26日
) _5 r/ P$ {6 S( d7 q - * 函数功能 : 串口2初始化函数,空闲与DMA中断
7 E4 ]5 y1 G9 U' R; Q2 s - * 输入参数 : 无
3 F( {+ n" \: T3 } - * 输出参数 : 无
* X( F9 a3 O2 t7 U) W - * 返 回 值 : # R' a6 Z- |% @0 d/ q' M) c) ^
- * 调用关系 :
' R% B" z/ ?5 W" L! m9 p" Y - * 其 它 : 3 a9 u) S$ R F5 o! G5 t
- *****************************************************************************/
. L) m7 {; ^- O$ F1 W& F - void EnableUsart_IT(void)9 {6 s0 \$ s8 `# ^' g+ X. O0 w
- {
; [ v0 l4 g3 ^% n1 N - __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断2 }" j, J, R: @+ D8 B1 I2 f
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断8 D2 c% X$ F7 O
- }
7 R7 _4 X- C, R) M; F9 O, q - /*****************************************************************************
7 Q' N7 J8 R+ i1 J [9 F - * 函 数 名 : Usart1SendData_DMA
' G5 y" S# }( S; y/ L - * 负 责 人 : by2 w. \: E$ e5 r6 K1 _3 E# L
- * 创建日期 : 2020年8月26日
J# d8 {1 v8 x- i- ` - * 函数功能 : 串口2DMA发送函数
; i y- V0 |7 w6 i5 j) m# ~ @ - * 输入参数 : 无. h9 p2 s6 ?% { R! f# }, x* V
- * 输出参数 : 无, z* ^8 q) f/ Z, i# f6 i
- * 返 回 值 : 1 i3 B8 o! i- _/ a/ w$ X- R4 C$ l0 ^
- * 调用关系 :
/ V4 z. A& Y1 p1 a/ q6 k - * 其 它 :
# f7 V+ A2 p W4 U" T - *****************************************************************************/
W3 [( F7 C' |/ v4 l& Z - void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length) # D) ~5 T0 i. m. z1 z' B5 b
- ( {# B8 i* r$ P% F" n( ]4 Z
- {
/ I @7 m. E$ j0 a - //while(Usart1type.dmaSend_flag == USART_DMA_SENDING); 7 K8 U) k/ B( ?
- Usart1type.dmaSend_flag = USART_DMA_SENDING; . K# |7 L: Y( k2 v) J; K( X
- HAL_UART_Transmit_DMA(&huart2, pdata, Length); 9 O# i! W% a3 I4 c$ [5 c5 y, g
- } * q0 }* }/ S$ X0 }: }* j1 O
- /*****************************************************************************; B/ }% {( o1 y/ x2 g
- * 函 数 名 : HAL_UART_TxCpltCallback6 M, i T* {! T
- * 负 责 人 : by
8 ]# K! y* \& U; C" M& U - * 创建日期 : 2020年8月26日
. ]3 D M+ i( s7 b - * 函数功能 : 串口2DMA发送回调函数
6 I8 j* u2 _9 \) ~4 { - * 输入参数 : 无
# }# v" e! o" d# U7 B( j - * 输出参数 : 无
. Q/ E% l1 ^5 {* t' [8 O, ~ - * 返 回 值 : 2 t4 |" p3 o) E- L7 u
- * 调用关系 : 0 f- C2 Z! J8 \1 @4 F5 A! ^# N
- * 其 它 : # z; ^4 l2 l8 c B B
- *****************************************************************************/
4 C! u! N4 {2 i4 H - void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
" ~8 [; \" V i9 d) ] p! Z - { % n# \1 b3 |5 f$ T( M% r
- __HAL_DMA_DISABLE(huart->hdmatx); 6 W. g) B; j K) N$ c
- if(huart->Instance == huart2.Instance)
8 J; k8 I7 f! r( F4 ^! k - Usart1type.dmaSend_flag = USART_DMA_SENDOVER;
) R. p1 B E, f" P - }
( M# R6 ]# I7 R# _3 T - /*****************************************************************************
3 R0 i6 c! X, Q: T - * 函 数 名 : UsartReceive_IDLE
3 r* k# L0 r* C% h" y - * 负 责 人 : by
" D. S: Y, v n8 g8 u# O0 x/ O - * 创建日期 : 2020年8月27日6 X3 | W9 k& e& ?6 e- G R
- * 函数功能 : 串口接受空闲中断处理函数
7 X+ U' I( q8 q/ |/ U4 P - * 输入参数 : UART_HandleTypeDef *huart 串口句柄0 p' N2 D8 d, {0 p
- * 输出参数 : 无+ \5 m" f' `$ K9 I0 Y
- * 返 回 值 : - b# R6 X X* V: v- h* I5 |
- * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收 ; Z5 P1 k! z/ z8 l7 F& U! c$ d7 d
- * 其 它 :
0 \$ p/ D" ~" B/ @% a [ - *****************************************************************************/
" F& q- h; R; y - void UsartReceive_IDLE(UART_HandleTypeDef *huart) d& L' \# `1 X& t4 ~) }
- {
& V' h! ^' q. D1 D7 Z2 W! \0 J - if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))/ [, e7 C& q$ S' i+ B
- { 9 H. q; p8 b: Q! ^( D
- if(huart->Instance == huart2.Instance)//判断是否为串口2! `, g1 w; R0 O: X
- {* f4 e; r$ i, ]* F7 N# @
- if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断& n0 V8 M9 _2 M$ I0 ~# R
- {
7 y& H0 w4 s& d* f - __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
6 ?& J7 r& r6 u! T5 ^: H N - HAL_UART_DMAStop(&huart2); //停止本次DMA传输
. v5 L4 |4 B/ S7 e. n! t - Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度
( p, W3 F9 h% `! s( N - if(Usart1type.UsartReclen>0)( Q( t/ q3 N' R" Z4 U
- {
e" X, U: i. x8 d! e2 }) ? - memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);# z' F: T7 E q5 p: s
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
6 M+ ^$ X5 j# X2 t2 R - }
2 ]6 x4 |4 i( D {0 D - else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录5 s4 L& g4 A4 Y4 N
- {( m! J; Y) d. @- {! v. E2 L) v
- Usart1type.UsartReclen=0;
6 s2 F8 V. o( a - }
# M1 d" j/ v! I - else+ d" _% G v- ^' C: ?
- {
6 l* U, I3 j8 ] - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);0 M# B) g8 J: s& x4 s) `
- Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
3 w8 \: {% g8 c. \$ Y/ x - }
: \8 C% {; i$ V. ?* C5 Z5 }+ [$ {& d - memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零 4 ?; v9 \+ T2 F
- Usart1type.UsartRecFlag=1;//空闲标志位置1; d" Y4 {& A' M- Q6 f
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
' G8 P& \; f2 F' C$ o5 A - }
! W$ ~ X: ~- h8 _1 ]3 N4 j - }5 w0 P& q' W8 z& X, r
- }& u, Q( s1 H4 A9 _: Y
- }( T S Q. }. |. y
- /*****************************************************************************
5 y ]; A% R( @ - * 函 数 名 : Analysis_Serial_Data
9 J/ I7 v2 l6 B: T - * 负 责 人 : by
% N: f6 T$ ~8 O1 F/ e2 ? - * 创建日期 : 2020年8月26日
* S$ z- i a' c - * 函数功能 : 串口接收数据直接打印 L2 s% |" i3 |3 y7 D8 N5 F# _- a+ t
- * 输入参数 : void 无
! o- i/ j: ?6 y6 [% } - * 输出参数 : 无$ t" I, I' h/ @5 Q) X
- * 返 回 值 : void
# A( G" U( S7 K( ?& Q4 x - * 调用关系 : , z3 p9 U! c. l0 m
- * 其 它 :
3 k0 V8 d f ^5 J: o/ g6 r0 V4 g' g - *****************************************************************************/
/ k6 y9 S% b# H0 }, N - void Analysis_Serial_Data(void)
4 c8 L& Z' f( M* |# Z/ Z$ I% _ - {$ X8 U" o4 ~, i1 J
- if(Usart1type.UsartRecFlag)8 ?( E7 b# B: e
- {
% d/ a/ H6 _2 T0 m2 E$ r - Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen); \0 u0 ?) k6 d9 R5 n) m0 a
- Usart1type.UsartRecFlag=0;
. Q6 \/ @4 m) d - Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理 % [( h3 U: C9 k) F" L
- }0 ]; R D, {6 x6 @( D
- }
$ a L$ `1 W' w. @$ |; a& ? - /*****************************************************************************
! N5 _7 O$ f& Z& t - * 函 数 名 : fputc
: c* y9 {. I0 b4 Q) X! J. x: z- y - * 负 责 人 : by8 |) p- D3 U. N/ {. K
- * 创建日期 : 2020年8月26日
( C- {$ }6 `& R& c- d - * 函数功能 : 串口2 printf重定义
* y* ]# V e. u; k' a - * 输入参数 : printf(d%/s%/%c,a)
1 i& j6 X/ T# z) w2 r s% b" ] - * 输出参数 : 无 r0 d4 v8 W; ^7 Z9 O9 B3 g7 v- c
- * 返 回 值 :
# S' P% o, a7 R9 _7 G - * 调用关系 : ! D8 N4 t$ ], H
- * 其 它 : 5 {! r" T; b" M, d5 }6 k1 }
- *****************************************************************************/, M. ?6 C! z) M8 @: |+ I; W: g- i
- #ifdef __GNUC__+ E; j" }6 h( T2 ?! y7 t0 A
2 g) F% c- Y! G- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
8 \# r S& [% C7 {. ?; | Q& U - set to 'Yes') calls __io_putchar() */
4 k+ ^+ z% D* J; O( N' B' M9 t - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
8 E3 d5 n) N4 t: @ - #else
+ c! k" g3 V3 e
9 m5 Y0 k- D& A9 A) ~- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
' c9 g9 o9 Q" {2 a8 K3 N6 c - #endif /* __GNUC__ */$ J" v- ^$ q8 m3 X6 a- T- ~
- ; k+ ~: L$ U8 Y
- PUTCHAR_PROTOTYPE
4 W8 \; I. K0 b - {, B" p! R& I6 h" I
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);' j' X- t- _1 T: I: f" r# K
- return ch;( j8 n% l: V! [' f {) z- K
- }
+ j4 q) q) H0 A4 m; ]9 {8 c: e
7 E1 w' V" L# ^ U2 T0 ^/ g- 4 e3 t! |; j; Y3 J, m/ Z
- /* USER CODE END 1 */
0 W4 g0 I& e2 _. O* P; L0 Z% w" @8 I - DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。" _0 P7 X$ q, G/ `# B" S: o
- 8 V; ~+ W. G5 ]/ P: `9 H/ G2 _
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
/ S; b3 q" W$ ^! P - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码 - f7 }* s% f6 |2 N. `
6 b. q9 }) x4 {/ I. c
6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */6 f, J: q3 I0 B% t1 O7 N# M
- HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
1 P. E r+ D0 ? I3 e m - HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/0 }9 ]# c% ~# c9 W; ^! G6 X+ {- s9 C
- HAL_CAN_Start(&hcan1);/*can初始化*/; i% e7 ? b! a8 }" P7 I. P
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
7 t2 [! I+ @3 }" \8 k - EnableUsart_IT();/*串口初始化*/
! z' o1 H$ u7 [5 ?" D+ y0 m - CAN_User_Init(&hcan1);
+ u" K0 O! N% `3 R: p) N# f6 ?4 h - /* USER CODE END 2 */
复制代码
+ z- S1 @, P6 ~2 v 循环,对应数据输出& u$ r( N, @. Y) N( {9 F9 @
. ^1 a* l: o* d' Q$ @' J' Z- /* USER CODE BEGIN WHILE */
4 [& d2 w; `5 o; H; _7 X. } - while (1)
6 Q% Y/ [, N/ M1 J x - {
& u0 ^3 i' R3 `( _5 j/ u7 f - Analysis_Serial_Data();
3 e2 v" }9 q; o) T2 g - /* USER CODE END WHILE */
+ ]7 J7 x3 d. H% h) k# |- |( [1 C- ` - & O6 y5 n; i% l2 y: N
- /* USER CODE BEGIN 3 */
5 Z S, c3 d) C% z: \: ` - }" v% x! [8 R8 m$ Q
- /* USER CODE END 3 */
6 x7 x0 w% `/ c/ x" B3 @! [ - }
% ~# }0 j$ o9 d# P - 7
复制代码
E5 }3 p1 u0 H" g0 I$ M" C" ?、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误# h2 v1 d- p% y
- j. \0 n3 h/ ^
5 _* H+ }- t* }; l: b% P1 q7 k$ O5 k% H( Q
% F. s) S5 _. I2 N# B) T3 x |