1.配置系统下载程序方式
# s% ^ M. Q% X# i! i" _. l* _+ D, c5 t
6 H5 \- }3 k0 O; s' d
$ j1 j' k9 ]& L8 }( [5 s
2.RCC外部晶振- _7 Z) ]& l) Z
% J) G U4 o- B. A/ \6 Q" G ^7 ?9 j
. d7 I3 t+ i9 ^ z
/ E9 F) D+ A8 R. t* Q" A
3.串口声明
. }. l0 f& u- Y# `/ m. A/ n. P) B7 W/ g. \& t' t ^8 M
3 w( _& S; P3 F
" L8 a/ \( T$ L% w& w+ K1 R A e+ e9 m/ C7 h0 W# w4 T% G% I6 x) w
( z" L. K) x( a% r6 F) y: w, x" z {; f! v+ j
& _. y8 X5 a) P5 |4.系统时钟
" R1 E/ U9 `- W/ D( V3 l% n8 F) \& _) B) @
4 q8 L/ q$ f& {0 D
% w" P7 V6 m( v$ s
5.生成文件根据自己需求配置9 J9 o; {( g' v
' P3 F! a7 F2 ^: a" H, O g+ U5 ?& x2 l6 E* r! |% l$ O
* t+ g- j: M, B) S, F# d$ V
我这设置了所有库,可以选第二个仅需求的0 _, Z* o3 y x. i2 V* s7 n
/ o' w! p8 O5 f( W6 s. o) m% v; I3 e* D c! R; l k0 T) o; e9 o1 ~. c
+ {6 n' t0 S: Y$ ` 还加了其他功能,这里可不参考,DMA要放在串口前
' T7 G/ Y. t! h
2 ?1 l0 t+ d$ j/ c
' e O) }* u% Y. M. k: _8 \* A5 J8 z- N; r j- f1 s
6.生成后修改* _5 A6 ]* ^, h$ x2 q% t$ Q
7 _7 Y1 O# H P; B+ S8 S
6.1 usart.h
4 @; ^6 H+ `8 n& h4 C; r; b, x7 `; C& S7 g- S% P4 R6 E8 T ?
- /* USER CODE BEGIN Includes */* U3 j7 s: _& Z" j& B j
- #include "stdio.h"
/ d* Q1 j: g" ?7 v6 b4 b) f7 N. ~ - #include "string.h"
. E6 w- O; j6 Q6 I - /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines *// {# D6 B8 @5 @: C, a7 e/ ^) G. R
! e# K4 i% z& i& o- #define USART1_DMA_REC_SIE 256; _) V* ]7 m. ^3 c
- #define USART1_REC_SIE 512
9 w8 M! D; f1 P& Y' X9 T. R, M - #define USART_DMA_SENDING 1//DMA发送
( O! j6 W) K1 d' X& m8 M4 z: D. b - #define USART_DMA_SENDOVER 0//DMA发送结束
: F) B: h. R& `% L7 c9 s - typedef struct5 |& y6 k+ n% v& m% k
- {& m, ^# H' S& g/ b
- uint8_t UsartRecFlag:1;//接收标志
& L$ t2 M' v) x3 m0 n - uint8_t dmaSend_flag;//发送标志
. b# `& @' U, Q- ?, G* K* d - uint16_t UsartDMAReclen;//DMA接收长度
0 `! M0 U- o% i! L; T/ F0 t - uint16_t UsartReclen;//串口数据缓存长度
( S/ d: {# n. L8 G. W2 n$ z - uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
. ^' D7 i( G) v - uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据' s/ y2 e7 R' t, C, I' e
- }teUsart1type;
3 w1 n4 ^7 V, N
# B9 Q8 r- H, c* j- extern teUsart1type Usart1type;//定义数据
$ Q: m6 C* P8 L& \' l9 B - . Q$ c. j+ C# e. E
- void UsartReceive_IDLE(UART_HandleTypeDef *huart);( l. C- l6 z3 F' b
- void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);/ B; v6 p& {8 d! I! ^/ J4 n
- void Analysis_Serial_Data(void);
8 {2 M7 m8 A z - void EnableUsart_IT(void); m( v6 j: ?: V8 [( G
! ~3 b$ a9 s: o! M. p- /* USER CODE END Private defines */
复制代码
; V: h6 [6 n: J9 t* t7 @5 O4 z+ D: B6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。$ E4 n' i" k1 j* x
# N/ t2 c2 P4 E
- teUsart1type Usart1type;, h* o: C: y4 u: A3 D
- /*****************************************************************************% j0 T5 T4 d" x( k
- * 函 数 名 : EnableUsart_IT
" f1 q" ~8 V4 g4 L* M! y6 K - * 负 责 人 : by2 f. L) U' }: ]' ?: |: ^
- * 创建日期 : 2020年8月26日3 P( n! {% V& |; D0 `
- * 函数功能 : 串口2初始化函数,空闲与DMA中断
4 W# k" x9 w" d; y, d - * 输入参数 : 无! k' ]1 |+ o1 U7 A2 Y
- * 输出参数 : 无
. M( ?2 }% c e8 @! l5 J. ^" S& p - * 返 回 值 : 1 w" F- I! u, {. p/ S
- * 调用关系 : # N/ C* Y6 G/ n, D5 X& s8 n; Q4 n, k( J
- * 其 它 :
8 i6 x* \. r: ] - *****************************************************************************/
; w0 a2 h, K# i - void EnableUsart_IT(void)0 W. q& ?! N5 X: ]2 X6 G
- {
; p! U( T0 h, o - __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断8 G- Y+ g a* l' } b% K
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
! w1 a. a* f) [) A4 K - }
( ^. B8 q+ J; f$ B1 m. w - /*****************************************************************************
" N8 [9 L4 z+ h/ e) d+ O - * 函 数 名 : Usart1SendData_DMA
8 w0 u" B" K7 Q; C9 T; a - * 负 责 人 : by
' I! ~) @. O: e3 G' i+ ]" U' H8 [ - * 创建日期 : 2020年8月26日
$ ^4 L6 \8 l" p M - * 函数功能 : 串口2DMA发送函数' u/ @" t; A$ |- T8 w4 T
- * 输入参数 : 无
$ \, Y1 J0 k; [ - * 输出参数 : 无
& K' N* C* R6 |5 w/ Y! D Z - * 返 回 值 :
7 s3 w7 Y7 q% [& e - * 调用关系 : : w2 M$ w" p# I7 x5 ?
- * 其 它 : # D6 l3 z! J1 p9 \/ O
- *****************************************************************************/* K$ G! Z7 r& E: V2 x
- void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
7 k: s2 {" `' U9 B5 R( ^' w
1 i- S2 @% B0 \4 c. [: i+ l- {
$ r' @3 o, @1 d4 P - //while(Usart1type.dmaSend_flag == USART_DMA_SENDING); ( t, t( Z D4 n# ^: A2 D+ m
- Usart1type.dmaSend_flag = USART_DMA_SENDING;
# C, U) }7 }* U* a* z, s - HAL_UART_Transmit_DMA(&huart2, pdata, Length);
\/ P5 t' b3 R8 L3 R - }
$ |8 F! B9 N/ A5 \1 ~6 }6 { - /*****************************************************************************+ j r- s, R! h2 ~/ R
- * 函 数 名 : HAL_UART_TxCpltCallback4 G8 O- [* A% J* [% {0 W$ `. M
- * 负 责 人 : by5 q/ u) |. i- v7 O8 N& o: e) c: ]% N
- * 创建日期 : 2020年8月26日 l; E$ r4 w5 _9 I
- * 函数功能 : 串口2DMA发送回调函数, d! ?% K' ~5 E: _. v# g( G
- * 输入参数 : 无
0 o. |7 V" G& P h" a - * 输出参数 : 无' b# f5 U" z$ |5 P7 I
- * 返 回 值 :
/ i- W" E" M" i9 F( L+ Q - * 调用关系 : $ s) Y' P6 M% ~ p7 C+ U
- * 其 它 : " }9 Q- I1 H( _3 V
- *****************************************************************************/3 `* @# W! k' c, \
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
, _. B$ b7 e4 X1 a! _. c; Z - {
, [4 i8 S" U( K% S) e, \ - __HAL_DMA_DISABLE(huart->hdmatx);
2 j R# r7 L% H/ n - if(huart->Instance == huart2.Instance) " f( p" T+ x+ ~ u$ R. ?5 V
- Usart1type.dmaSend_flag = USART_DMA_SENDOVER;
7 |: U S0 _6 `- Q. N% R - }
; M2 J' _( L( L& M - /*****************************************************************************+ f' l+ {( }; V# w: t8 ?
- * 函 数 名 : UsartReceive_IDLE
+ c! b0 \- E" \ s& p( Q - * 负 责 人 : by9 J6 l4 ?2 j1 @8 R
- * 创建日期 : 2020年8月27日; ~ Q2 [2 ~- N- Q6 a. Q; n+ A
- * 函数功能 : 串口接受空闲中断处理函数, \# z$ v% h V4 ]
- * 输入参数 : UART_HandleTypeDef *huart 串口句柄, V9 z% a6 p" _0 Y1 }
- * 输出参数 : 无; a( E7 I5 f* @1 m8 B, \
- * 返 回 值 :
0 Q0 C4 W x+ _ U3 g. g8 s: M* N - * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收 8 s7 B5 x' \* p/ }# g0 D
- * 其 它 :
% @4 n y/ D. @, g' J - *****************************************************************************/
@9 Q7 a" P0 F7 w3 y* U+ j" @; x: s3 j - void UsartReceive_IDLE(UART_HandleTypeDef *huart)
" ?. e( J, {5 P3 U0 n - {
$ z: X4 E8 d1 [* Q% D - if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
0 I: h' S; X2 T: d: p. s - { # A; r- U6 d" Y$ m. i0 ~+ p: L, ~/ S
- if(huart->Instance == huart2.Instance)//判断是否为串口2
3 K7 m) h. o$ U0 L- E5 g7 K* x - {0 j/ C" p1 q: b$ G+ S- w v
- if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断
$ o2 c& W H/ ]" b! } - {
$ }( l6 ]' g: R1 n - __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断. s% v. U7 ]7 A; }% _5 a3 b
- HAL_UART_DMAStop(&huart2); //停止本次DMA传输
( s1 U7 [% z$ P - Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度& X" \6 m2 }) Q! ?- H, f
- if(Usart1type.UsartReclen>0)
4 H8 Q7 E- A' l - {& [& q- _5 S4 x/ f$ I% ^
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);- z; R2 a8 o2 ]( T( ^1 S
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;8 |- o H! A( o' @2 Z8 Z* R. z
- } - C/ T. h3 \' r9 I1 C& |. y
- else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
3 S; \; n* N/ j. [- P/ F - {! [& t' o0 Q! W
- Usart1type.UsartReclen=0;) C( q& B" @$ F l2 \$ f
- }2 s! r6 m7 {7 R6 T ]6 f7 _, w
- else
) Y+ m# s7 t3 N, C+ r - {
2 n+ |; _$ G! s, x, w1 D. y( ~9 { - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
1 z6 T# P# ^! m: [9 T - Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
- s, ?, k' T- X8 V6 Y% L+ X5 l - }
4 D, h9 {# m3 @2 A" z. e - memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零 & o9 j" B% R+ \- m6 V; a G8 ]
- Usart1type.UsartRecFlag=1;//空闲标志位置12 l2 I |3 l8 w9 }7 T6 S$ p" b
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA" [) Y, d/ M( O9 y
- } + v5 C! Z9 [, Y0 @3 h8 L3 w) ]- u8 m
- }
0 r: p/ ~" d7 L% ]* [+ L- K q9 }( S - }" R8 Z9 ?0 W" f* i, o a' @/ ], l
- }+ Q# T+ v# P( b% G
- /****************************************************************************** l$ C! W4 K2 Q, c+ Z4 K$ v4 U" k
- * 函 数 名 : Analysis_Serial_Data
@ J" A6 c, \0 T9 g' y - * 负 责 人 : by" s/ h, C; e5 ]! ?7 S- z0 U0 L. q! }
- * 创建日期 : 2020年8月26日$ X2 m& ]! f6 L A4 j2 p) W. B! X
- * 函数功能 : 串口接收数据直接打印6 H; j( | B+ Q4 D* A0 y. t
- * 输入参数 : void 无
! B- g. d1 S& _8 [ - * 输出参数 : 无
" v- a$ d! @% C& ?# t# Y - * 返 回 值 : void' j5 m1 U: ?- ^# X9 v
- * 调用关系 :
: ^: I$ F. \2 Q0 [8 Z; j - * 其 它 :
: B" K, X: B' w j% D( k - *****************************************************************************/; `( f5 L. ~8 O# c4 @% s# ]
- void Analysis_Serial_Data(void)- ~3 g( J/ p2 a) H. i& d% ?
- {
" u6 O( I8 a$ D" i4 m( W0 J - if(Usart1type.UsartRecFlag)
# O4 K- }1 ^, d8 r) }% f$ X' v - {
, Y2 I/ Z j: o8 y7 o- q6 O6 |( ~! g - Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
1 f0 U) p4 j) t3 L' w: K+ r0 ] - Usart1type.UsartRecFlag=0;& p9 Y, ~( G% m5 B* E- m
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理
: K) ?+ B9 g4 { - }
: R8 M$ f j6 r' m - }
8 B/ `# y* l9 r. x5 C! h/ m% d4 @' S; V+ s - /*****************************************************************************
+ p, U! U: O& J/ H3 P& i" x0 [+ f - * 函 数 名 : fputc3 S; _" I7 e6 w6 h
- * 负 责 人 : by5 j! G2 s0 n g
- * 创建日期 : 2020年8月26日
3 t- A+ o2 l7 e' k- S, U9 N7 F - * 函数功能 : 串口2 printf重定义
+ }9 Z* b, n" g% F" p - * 输入参数 : printf(d%/s%/%c,a)
- x! s' I2 V* h9 X - * 输出参数 : 无
$ W4 E1 O/ M: x2 Y - * 返 回 值 :
$ |" L* E& ]# D, V3 D6 p: \ - * 调用关系 :
1 p2 h" B7 B T2 ~: @ - * 其 它 : 8 X6 Z. L' Z6 a0 ^
- *****************************************************************************/) B! ~8 M/ b5 t3 d" k3 ?$ z9 \4 l
- #ifdef __GNUC__ m) U- ?6 u8 b* E2 S
- , b9 L" i" O2 c
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
% l$ [: x0 v: ?0 q - set to 'Yes') calls __io_putchar() */ L5 W0 x7 W) v8 s- \$ ]
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch). A; Y: b: h/ a
- #else
8 F2 @4 s2 N4 f, `
: w6 e2 c2 d& l8 e+ v& T4 C- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)! q/ @( G6 T; y! j0 ?/ p
- #endif /* __GNUC__ */! b; D9 m, Y5 v+ ?+ F# \ V! b \
- & y( \' G+ W. z) A) \; P- f. @
- PUTCHAR_PROTOTYPE
$ D P" Y; ^9 u; R- @2 M' W - {3 V m% W6 P% ]1 L. }; K. t) E) W
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);; X) I* O! `2 Y3 H0 b: I% C
- return ch;+ E3 j8 i6 }7 `; K- K
- }( u. ^, r2 f3 x# U% J
6 o* [& Q" `! g; L6 c
3 k3 i% p( Y4 k- /* USER CODE END 1 */
0 C2 u# S6 i3 b8 R) E - DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。
0 ]/ c/ W: ?$ v8 N1 b% e' V2 R
) e5 c$ Q9 S% F3 A. Z- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
0 Q# i" E- |1 U1 ? - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
* K7 a( S5 H! R0 R; X- G
1 K2 P% \% y$ k+ n: Y& E z" F- w6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */
" h% X& S+ H& S, Y p, P) k' V/ v - HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/1 G; ~& ~1 m# B- H7 w, Q+ |
- HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/; S, T2 j c7 v
- HAL_CAN_Start(&hcan1);/*can初始化*/
# ]: K# n+ R- i N5 e* ] - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING); 2 q. _7 A% t5 ~2 b
- EnableUsart_IT();/*串口初始化*/6 [! X; D; S4 k; k$ G$ o% w
- CAN_User_Init(&hcan1);
4 i) _" A0 p0 l, g - /* USER CODE END 2 */
复制代码
& O) @4 _8 b- F# k( u 循环,对应数据输出: L8 L7 |; X( v$ g7 O5 |
8 J! n6 l. c( t, Z) m' K& H. j- _( }
- /* USER CODE BEGIN WHILE */
5 u! `: w$ A2 p) M/ N1 r - while (1)! K5 T9 D# v& m* q& M2 V5 e
- {
. a8 q! r6 B* O& ~; z - Analysis_Serial_Data();+ o" A; e0 U1 d$ {! x# k
- /* USER CODE END WHILE */0 |$ M* ?. l: P
; c! f1 B- {" W: Q3 Y6 F2 u- /* USER CODE BEGIN 3 */
7 R9 V- k* Q. O7 ? - }& A! y- l9 K# x& f. i
- /* USER CODE END 3 */: `' ~: }+ W& e. J3 k
- }
8 K6 J, h8 [# K - 7
复制代码
8 t) r' n1 a. h、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误& p$ w( q8 e% W# ^* t# i
5 }) U! E6 _5 f6 M1 t
: h7 y* F4 {# r z) u( E1 A3 f! Y& F# A1 i2 t
5 I! {4 Y2 {9 b8 p8 I" l, l
|