1.配置系统下载程序方式
4 |: k( r+ C, T7 w7 G5 Y" t; O5 `$ O* o4 q
- J% w; h+ E5 D5 F& l; b F! z* V" R/ M# a' K' V
2.RCC外部晶振; y9 U- ?9 |# c# l; Z" i* I6 P
8 `6 Q6 w! B6 _. ?" E# E
" U0 b+ H5 }$ D! p
7 n3 c* U2 y6 l4 V 3.串口声明
7 R" {: [! O$ I* H& g; D
# _ E, [9 b8 C) ?# U& G ~; r
6 j6 X8 Q5 W& R; Z) c/ z. n& A9 g- h
2 C# t. z' l" v% q+ s7 b! z# L/ C0 }
% R/ S# M4 p! n; }: N
% a+ ^5 V" Z; m* ]# q v, t4 E' ^) j6 D4 d* p- H/ |+ P z8 o0 m
4.系统时钟6 i% s5 l+ }' a. m# S6 u
) e1 t% c9 Z! v! L! K: Q
7 u) L0 c! m3 y9 p1 i- ^& ^7 i
- g6 k- Q" K( v: L- h8 [ 5.生成文件根据自己需求配置
% l" Z' }9 t' C8 u( @7 l
* `4 V2 z! c9 B1 R y
1 v2 N7 z2 K* M& V2 I
& F& E# I) G9 R 我这设置了所有库,可以选第二个仅需求的
# `6 u; `* y& c
- B/ l& G' R$ m5 K1 t; y/ [; K f5 U
% K# i J8 J. v' X/ x4 I
还加了其他功能,这里可不参考,DMA要放在串口前' _7 Y$ u7 ^2 _, K& c
- x, g2 X* O9 {- w3 O, X* X
: V H: [* Y- v6 T2 h2 e' s' @# \) v2 `* G5 R6 a
6.生成后修改
( L2 w1 t9 c! G3 s9 [; V- T
[9 Q9 [9 ~' {. g! ]2 r [& V6.1 usart.h
: |7 S! e/ r0 C, E9 v# [# I: Z+ ]: A# _. z7 @; V( R* i
- /* USER CODE BEGIN Includes */& a5 ?) V4 G1 W5 q2 X
- #include "stdio.h"# `1 @7 D) Y' j+ \
- #include "string.h"0 E4 P" {( s+ M, M
- /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */
" A4 D6 c. f% x7 W9 V - . H7 k" ^& G2 H% V3 K" p* U& ]
- #define USART1_DMA_REC_SIE 256! e' g, z' y! O( `# Z. S1 [7 G
- #define USART1_REC_SIE 512
' N, T% P+ k' @4 s- d - #define USART_DMA_SENDING 1//DMA发送
# G% @ k( M( ~) J% A$ O+ q - #define USART_DMA_SENDOVER 0//DMA发送结束9 ]) n; N/ N( N0 n* h
- typedef struct
8 I7 X( `7 f" x% I2 i) p5 [, a - {) L2 b. V4 \; d: Z3 k) d; E _0 J
- uint8_t UsartRecFlag:1;//接收标志3 b" {5 z1 d3 b; |& d
- uint8_t dmaSend_flag;//发送标志- X% e A0 I$ Z
- uint16_t UsartDMAReclen;//DMA接收长度: g' F4 e2 i" N+ |
- uint16_t UsartReclen;//串口数据缓存长度. c& k- `# Q$ e/ q* |8 Q
- uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
" _ ^- v* t% a8 A - uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据% p# @( J1 }# a7 X, I
- }teUsart1type;
) q& b" U5 n, N8 ]3 R
9 f4 F4 }3 C' [0 [7 m- G) [9 b- extern teUsart1type Usart1type;//定义数据 }( ]; r3 w: j( }) [: x& ~
- 6 Y" K/ N7 t! P. _: V; R6 D U
- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
5 X' F1 f: Y8 v# f4 i - void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);: t+ c5 ^7 m0 L/ }+ A r
- void Analysis_Serial_Data(void);% q( N+ ~1 m6 M( ]5 R. k# d
- void EnableUsart_IT(void);4 @1 s! g+ j8 d" P" d( k$ W) R- s
9 B8 m% r( H4 g3 c3 Y- /* USER CODE END Private defines */
复制代码 ( x3 _9 m4 V7 ~% j
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
8 @4 _' D1 }6 K
# `& c! \7 i, Y- teUsart1type Usart1type;
7 G; z* g/ B. s# Z1 o - /*****************************************************************************
7 P0 Y" x, ~& n0 s% W% u - * 函 数 名 : EnableUsart_IT
9 i7 j% y5 U7 F - * 负 责 人 : by6 ~ K4 E: A& s
- * 创建日期 : 2020年8月26日
& |0 V9 I$ m' l4 ?& u# J - * 函数功能 : 串口2初始化函数,空闲与DMA中断( m- Z$ T- d1 x3 z! b/ k
- * 输入参数 : 无2 `( |- m# s# }: n8 @* l0 ?+ Z
- * 输出参数 : 无
+ u+ g: K; K, V% C0 N - * 返 回 值 :
6 W$ l1 A+ A* `4 k/ d - * 调用关系 : , @ M$ R* a/ ~! a7 e0 Z' e
- * 其 它 :
! R4 t6 R/ ]* ?# E - *****************************************************************************// j6 f) M) K0 O! r; e5 c
- void EnableUsart_IT(void)
5 D) j& N3 D1 L! ^ - { ) u3 @5 t& p! i3 c
- __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断6 d, q: G6 J' ~1 b* u: i9 x5 e: g
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
" _7 \# B O! T6 H: @ - }
. a, v; g) {0 B$ }6 d6 h- F - /*****************************************************************************5 p2 H# ^0 |( E- |) h+ Y
- * 函 数 名 : Usart1SendData_DMA5 P1 V) w" a) J7 t
- * 负 责 人 : by) y4 F) v3 A6 w" a
- * 创建日期 : 2020年8月26日
. ~4 W6 ]7 L- T) w/ [$ n. z - * 函数功能 : 串口2DMA发送函数3 q) ~8 K# A3 u0 V2 e: W
- * 输入参数 : 无+ I& z- j- R' z1 J, n3 ?+ i
- * 输出参数 : 无
! ]' g/ Y5 r) C# e; |9 ^( | - * 返 回 值 :
. A( T% O _# b E4 J, {) L - * 调用关系 :
9 _- C8 @8 Q6 B, I - * 其 它 : 0 Y1 q, i4 x" g4 `
- *****************************************************************************/
* Z, c3 t# ^ v1 v - void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length) ' t2 o+ p/ |3 N# ], {1 o1 S9 \; U @
- $ w. V% m/ v# j. ~4 _- q3 a
- { . M2 r1 H+ W8 b% B# w. ]* q
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
- g' x% x e( f& m+ r" h/ n- X( k - Usart1type.dmaSend_flag = USART_DMA_SENDING; 6 s9 l4 |! n- S8 v7 N8 e
- HAL_UART_Transmit_DMA(&huart2, pdata, Length);
4 o, d1 h& v5 S2 a& @8 x - }
4 D$ E, I* P2 p' j# X( Z - /*****************************************************************************3 o4 T. @1 M5 u* l9 @% ~
- * 函 数 名 : HAL_UART_TxCpltCallback
& q' o) ?' @1 e8 e - * 负 责 人 : by/ o. Z$ v. U- \2 C
- * 创建日期 : 2020年8月26日0 t: i' `- o% Z% ?. V6 [$ J
- * 函数功能 : 串口2DMA发送回调函数
8 m% D' p9 ^6 O" Z( D. ] - * 输入参数 : 无& \$ [6 ^/ R; f; p `3 a
- * 输出参数 : 无
+ X! F* l1 {2 q* X( \% h - * 返 回 值 : + Y! \2 P# c+ j8 x
- * 调用关系 : # @6 l4 X% [, q# a' H7 l% \: ~/ q/ t
- * 其 它 :
1 s' ~5 S7 k a! @3 @+ s: w1 @ - *****************************************************************************/. [4 [- N1 P7 F, ^
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 8 x/ a( ~! j9 T/ x1 X" Q7 C! X5 X
- {
3 s6 M3 v& G% m3 M+ {: T/ O - __HAL_DMA_DISABLE(huart->hdmatx); ! q u* n% Z2 j1 `/ V
- if(huart->Instance == huart2.Instance)
9 g. F# x0 n' K - Usart1type.dmaSend_flag = USART_DMA_SENDOVER; " P2 a9 Z; F/ s
- }
5 K! O2 D7 E$ i3 ~: w - /*****************************************************************************% ]0 n8 N0 M9 r* H. J D3 _$ g
- * 函 数 名 : UsartReceive_IDLE7 U* i! L" h$ z! e, s: A
- * 负 责 人 : by1 Z0 }7 v8 Z0 [# o- U1 K
- * 创建日期 : 2020年8月27日
6 U' c) U) i, U5 s; U% @& K' X' s - * 函数功能 : 串口接受空闲中断处理函数8 J! R1 M, n# _. b
- * 输入参数 : UART_HandleTypeDef *huart 串口句柄$ G$ T% c6 P, V; K/ d
- * 输出参数 : 无, [% w6 D- m1 H9 L% E W% v
- * 返 回 值 : " D- X) o0 d% T* I
- * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收 6 h$ F+ K7 {5 h8 }+ f8 K
- * 其 它 :
* J; l3 ^5 t& z. @ - *****************************************************************************/& Y9 Z& g5 r: a: \7 l
- void UsartReceive_IDLE(UART_HandleTypeDef *huart)
! x% v7 U" B3 x; c w - {
5 b: Q1 x) ^: U! C8 z9 ^ - if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
8 _7 Z( f9 H& Q, h4 S- F/ X8 t( |8 M - {
, U# M0 s6 Q9 Q( [% t. n" D$ _: ?7 P - if(huart->Instance == huart2.Instance)//判断是否为串口2" S/ j9 t) t8 @, s
- {
) f9 y! _0 i* i& l* O9 q - if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断0 h; O# z) ~! ?# A! o
- {5 b( ?. ]. G0 k: {6 m4 T6 O
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
]/ o/ {1 J7 m+ E, \! p - HAL_UART_DMAStop(&huart2); //停止本次DMA传输
' I) B; ~' C% Y( W - Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度8 U; I2 M' @& ~$ e6 G
- if(Usart1type.UsartReclen>0)4 ^9 F3 J% A- [ X
- { l" t0 y# [! L) r: u* d
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen); c. \4 V, u# E/ P: ]
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;% S7 Q5 y. X0 a) w+ a ~
- } 6 F! x' W+ q6 |0 ^9 A: [& s& ~
- else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
3 ]6 R* M( ~6 X& s! E - {% U/ H7 W9 N; t8 J4 c v2 P
- Usart1type.UsartReclen=0;
: n. V, D7 E9 U0 J - }
7 [3 v2 ?- J# ^! B- O m, O& L. ^ - else
$ j! s0 f* M3 e# Q. q - {. U( i/ c+ n3 q& ?
- memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);& M1 h) }, h& a& ^
- Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
9 n* c- x9 f1 }& V, o - }
( l, |0 J; G# h7 e5 ]* p - memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零 , c# A- I. }; e/ d; ]
- Usart1type.UsartRecFlag=1;//空闲标志位置1: n% q4 `. R: |
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA; C9 P Y! c' {' H' n1 w
- } 1 e" ]4 y, E& d; ?3 T! T- K
- }% N: [5 M: {* t; n8 b
- }
+ q: z4 \, t& D0 H% K1 r6 c6 E - }
) H1 L( K8 |! i# z7 Z) J - /*****************************************************************************
) i8 {7 o- s8 a/ h" T - * 函 数 名 : Analysis_Serial_Data' R, c; O/ r- e
- * 负 责 人 : by' F: k& V5 n* K J& Y
- * 创建日期 : 2020年8月26日
: X% I3 N" C' N# e g% h - * 函数功能 : 串口接收数据直接打印
+ \* m! h! I; L: p, b6 g% w( O; f - * 输入参数 : void 无2 V- M* t2 Q) @! M& T) J k
- * 输出参数 : 无+ l0 l3 l5 f- a) V6 Y
- * 返 回 值 : void- L5 i+ k; C# V, K; t" \ _/ ^
- * 调用关系 :
. O" r5 _1 s2 z9 J - * 其 它 :
1 K2 C% R( T% P- O# C - *****************************************************************************/
/ o8 z6 U, i& J: l' m2 Z - void Analysis_Serial_Data(void)
" {6 ^# [% V; ^4 ~7 T. i( `' H5 L - {
5 }5 k A3 y& ~2 S - if(Usart1type.UsartRecFlag): F. _0 A( m3 `2 J# ?% V' W
- {
. F( ^; ]$ h" B - Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
1 Y- P: P1 S' x2 ~4 h8 [, } - Usart1type.UsartRecFlag=0;" H' w! M( d: H3 A$ s/ A
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理
' c$ h' P. ^+ I; E6 k - }
6 p& {8 Q. g0 k/ |. z - }, S; w: X; ~& O/ u% }4 v" Z
- /*****************************************************************************+ U6 h9 N; r: Q- @" P3 Z$ n: d
- * 函 数 名 : fputc- ~- O7 n& \! Q7 c3 L, C
- * 负 责 人 : by+ Y" f) K! S7 _2 o, `, e
- * 创建日期 : 2020年8月26日
/ H/ N: @' M5 C# f - * 函数功能 : 串口2 printf重定义# j' R/ E, Z6 v; h7 M4 @" I$ B
- * 输入参数 : printf(d%/s%/%c,a)
4 }: h% ~" Z3 s1 `. @ - * 输出参数 : 无
' D' w4 |- U5 c6 w - * 返 回 值 :
- N1 q3 m/ s4 ^& {& s3 g# f - * 调用关系 : ( O, n# V( V% K/ _
- * 其 它 :
' p, `+ p- X$ `% W# o {% c - *****************************************************************************/
! d9 k# }* \# `6 q - #ifdef __GNUC__
6 G# |2 [7 S' s. ]* m# ^ - * o5 m- o" Z& a/ U; [+ S
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
6 t8 b6 l8 R" J0 p8 S5 L+ t& \3 L - set to 'Yes') calls __io_putchar() */
; X& \# `7 U- d9 J7 q0 f - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)) n% W' [: N4 Z+ z% Z a
- #else" d; i$ G9 k* I: v2 T0 C
+ B4 c, }; G- L) M: h# M; m- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
2 J+ v E: P4 x! Z3 l J - #endif /* __GNUC__ */& [" |! T0 P' [/ \. E, p; o! o
- ; z# w( w) g6 q R( E6 ]1 W' w, P
- PUTCHAR_PROTOTYPE+ s( t$ u; n" X, G: r7 `% _
- {
6 W- r. ^4 ^+ @. F) t5 r$ A( | - HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
. q( X) W, }# H, W' r" r/ j4 |2 a: d - return ch;
) L4 F/ h/ b4 L# ?3 @/ W9 n - }$ A; N& w4 j+ ]. h
- 8 {1 V/ S1 x) i0 `7 G+ ?5 {
- : K8 i. L# Z5 g, x* G5 h
- /* USER CODE END 1 */, z, u1 G. E% p3 k& l) H$ t
- DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。
" @7 h* W3 e3 [0 |% [& w$ T - ! N% \$ B1 [+ S' ^
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
/ h% ?9 ^1 @, y4 T5 d: ~+ o - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码
/ x: k' r0 k0 D" E5 X; k7 e# z9 e; V; p- u4 n
6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */
f( S) q9 q/ H# r - HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
; ]5 F$ Y' `4 \9 ^ - HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/7 f/ U$ g- E' N( h
- HAL_CAN_Start(&hcan1);/*can初始化*/
7 s- Y2 v) \8 e - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
7 @- P6 ?" D3 Z% W, H0 _0 [$ O. Y - EnableUsart_IT();/*串口初始化*/
% S, t7 j# ?& }+ { - CAN_User_Init(&hcan1);
* E3 f4 U0 T0 }$ N5 [8 _ - /* USER CODE END 2 */
复制代码 " ^6 G$ a5 R+ s
循环,对应数据输出
; s" U# Y' B7 X+ u8 c# |: t7 `: f( M' D8 q0 ^: t" q
- /* USER CODE BEGIN WHILE */" e2 M: |. {! ~1 l4 ]
- while (1)# ~% @" m7 ?' t9 a+ I- A& f3 a& j( d0 ?
- { 9 [; _2 i5 H* H# t2 b2 ]% i7 l9 g
- Analysis_Serial_Data();: V: t5 k( K8 l7 r
- /* USER CODE END WHILE */. i- V5 F& w6 J8 W
3 W, W0 `) Y+ z1 R8 `* [3 M4 q- /* USER CODE BEGIN 3 */
$ ]9 q# p8 T& ~9 B+ t - }& W) P: ~' L& _
- /* USER CODE END 3 */8 {3 d7 D$ I; Y1 ^3 Y
- }- _% Q$ P1 X! C8 d, H
- 7
复制代码
2 X! g+ T8 R R( u9 b( E6 g& ~、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误
! d; f- z h* h5 t
4 |# Q% N. i. J U, n/ T
, w+ s4 ^* r- l- Q
* q O1 _( ]. [2 ^0 V4 V( y& E1 Y0 ^9 B3 G% `
|