1.配置系统下载程序方式
! R5 }: I2 K. L+ Q! g5 q2 ~+ c
$ a5 }+ B0 v0 y6 l8 z6 M6 [' B0 a! d% u
2.RCC外部晶振
) y8 ^ W, z4 l) Y: y* O$ u8 P9 j/ U, w4 Y6 [$ i" b
% D" d7 T4 w% [3 G4 c
6 V# y4 w3 _+ \; L4 g! H
3.串口声明
5 _& r& B4 ?* f" F' ~
' L# q- }; |/ I/ G. E
) r: H$ E9 U2 b* ^( D, W2 `! k1 K* ?# h7 B$ L: N! _ k
! f! S. F3 Z' ~( ~0 C" v6 T
! q! A! z6 `" k2 T# a! r4 G+ C6 j
/ Z6 M! P. X& F& K# M! p' C$ }$ _6 G* q
" E3 ?* A p& N* b1 L7 u- C9 e4.系统时钟
& m( K+ d6 n. Q" D' @
, e4 J3 e3 {0 m' G ]2 T; n
8 v" s0 g' ` S5 e2 w
' T' w2 q- ~" R( l, f* V5 e 5.生成文件根据自己需求配置
; V- J& n& U5 P/ a' f( O
* Z' `! z5 U. O: L' A. I; m8 }9 m1 R' z9 N1 U
8 a \. f) l$ ?0 M' v 我这设置了所有库,可以选第二个仅需求的
" a K: @* @( J9 N0 o
) e$ E1 R* s0 v5 l ]3 _$ u
4 R$ q& U3 u7 [: A
' B; D2 g* ?9 X6 {1 P Y) w, z/ x 还加了其他功能,这里可不参考,DMA要放在串口前0 D2 I: e! V* w% P5 Y. {
9 r4 g2 i; @8 Y' K' @5 v0 d4 r
1 |$ S4 z& J# @/ E8 D& e- P& f$ E2 P
6.生成后修改8 ]: v; Q* J3 s6 u) E+ Q
- g" I# v1 T* T! C. V+ e" z6.1 usart.h: m1 v8 B) F: r' s6 I2 W. t
) S8 D9 _( F# D' N9 f6 a- O
- /* USER CODE BEGIN Includes */
+ X0 c$ }+ ?5 Y - #include "stdio.h": p. g l Q, ?0 T1 i: |2 w; V% S, t
- #include "string.h"
* v$ q$ V3 g8 O# { - /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */8 k: T. x' C2 a& e' C! y8 D
- 2 T) B; A/ U+ z O9 T p9 ?% |# B! n l
- #define USART1_DMA_REC_SIE 256% h/ g* }% J6 _9 @' _
- #define USART1_REC_SIE 512
8 U, x( ^7 d3 E - #define USART_DMA_SENDING 1//DMA发送
( s; a3 _5 w" k' s' R- i$ b1 z - #define USART_DMA_SENDOVER 0//DMA发送结束
1 w% C g/ \; N# @" J/ `- ^ - typedef struct
. |7 j# F$ \! ?+ K' S+ G# L6 h - {7 g! g$ S4 T" r- J. g7 ?; J9 v
- uint8_t UsartRecFlag:1;//接收标志! N0 g% R: s' x5 j
- uint8_t dmaSend_flag;//发送标志
! B" l3 E2 q/ H1 G5 ~+ } - uint16_t UsartDMAReclen;//DMA接收长度0 q( p- [$ X4 p& M8 T- h' d
- uint16_t UsartReclen;//串口数据缓存长度
9 {9 y0 K3 D+ G8 }' t1 r - uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
. p0 _& [/ y0 T: W& y+ J+ w - uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
0 V+ s) t" {+ J5 | - }teUsart1type;
: }& c# V7 M* ]# n
, K. N Y" ^( E: g3 |- extern teUsart1type Usart1type;//定义数据
+ i; R! }* B+ ?) z4 u; [
4 x2 ~6 R0 ~4 e; z- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
- N8 M: f x. D" b; j- Q - void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);( V* J) _" Q0 t- |7 T. x
- void Analysis_Serial_Data(void);- u; g/ _$ ]$ g. \; D) M
- void EnableUsart_IT(void);, d. K, X. j: `* R9 c' d9 L7 I2 `
- - X& N% E( {4 x3 p
- /* USER CODE END Private defines */
复制代码 % @4 E8 q1 A' i3 _
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。
+ n0 W$ |$ P5 o0 m9 _5 d' N9 x, p1 Z, D5 |: G" d* [
- teUsart1type Usart1type;4 H4 V0 V" U/ _1 ]
- /*****************************************************************************9 p7 g- q* P7 U1 ?7 B
- * 函 数 名 : EnableUsart_IT: }! y5 k4 X1 ]0 i0 Z& G( [6 W+ |
- * 负 责 人 : by
6 ^! I: I7 G \' i: A9 K - * 创建日期 : 2020年8月26日( f3 [9 D _1 ~! m, r( @
- * 函数功能 : 串口2初始化函数,空闲与DMA中断
2 u7 B4 Y7 y5 u8 J/ I - * 输入参数 : 无
! F- |8 z6 m/ w' y( b! G - * 输出参数 : 无
w+ R& w: K& P D# R6 } - * 返 回 值 : 5 t: F) L* ~8 T* w9 [% o+ o
- * 调用关系 :
: Q- r" D3 N4 H5 V - * 其 它 :
; o, _) Q+ r+ c2 V2 I - *****************************************************************************/
7 e( Q. j/ |0 M: A% z# J2 } - void EnableUsart_IT(void)
, M7 H* `: P1 i* j% H9 A3 H$ I - {
. S: i2 n6 T, a. m7 d2 W; Q- s - __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断* R9 `9 ?0 j! T- G, M, L R
- HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
) i0 r4 j, s4 |# t; s" x - }2 Z! f7 i) W* w Z$ _ s# Q6 b
- /*****************************************************************************
" ~( x4 ]6 B. W) N" J3 F \ - * 函 数 名 : Usart1SendData_DMA/ \- g$ z8 V6 w; e. _, N
- * 负 责 人 : by2 r$ y# E7 n7 ]6 e& C
- * 创建日期 : 2020年8月26日
* h: {+ Q2 [% b* ^. A7 N6 i - * 函数功能 : 串口2DMA发送函数4 ~# y5 _: K4 t7 f# `+ \ K
- * 输入参数 : 无
5 D" I% c$ G) o5 k( i6 T - * 输出参数 : 无
7 m+ Y. K6 L$ L& H - * 返 回 值 :
7 a5 A: Y* p- v - * 调用关系 : 3 D8 Q+ E! T' N- f1 K
- * 其 它 :
# r: P3 l8 @/ s0 V* J# i! P6 Y - *****************************************************************************/- Q' v6 U7 D! F3 [) O
- void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
: {3 F7 N0 T; g Z4 @! x - & f9 Q W: O6 o8 _; f
- {
( U$ Y0 ?4 N$ O H - //while(Usart1type.dmaSend_flag == USART_DMA_SENDING); $ j( G6 M; k+ M! F: X- q9 c
- Usart1type.dmaSend_flag = USART_DMA_SENDING; 8 f( {+ n3 [9 u6 l5 L' ~1 F2 X
- HAL_UART_Transmit_DMA(&huart2, pdata, Length); + H4 u4 A4 M0 T# s
- }
% N# }1 O, w9 n1 p% ^ - /*****************************************************************************" [8 A1 ]( E3 a
- * 函 数 名 : HAL_UART_TxCpltCallback0 X. _, z% l% ^5 L8 _7 K4 W
- * 负 责 人 : by
5 f, ~/ i l' t$ k2 ~ - * 创建日期 : 2020年8月26日
; w2 X! V) ~/ B m" G% s - * 函数功能 : 串口2DMA发送回调函数& H" F' {8 o0 s: L4 c
- * 输入参数 : 无
( z: Q% [3 j: a T! _ E - * 输出参数 : 无$ @& K2 o8 v- ]6 t, K
- * 返 回 值 :
0 g3 b# E# Z5 z" \( s4 ^+ | - * 调用关系 : . E& z# |: s; C, g1 @
- * 其 它 : 3 M0 K/ n# ?" M ?( h+ T. c
- *****************************************************************************/9 P6 d. [" ] J
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
- C! q/ H3 m: T5 A/ G8 c- b - { 6 i% S3 c3 e+ q
- __HAL_DMA_DISABLE(huart->hdmatx);
4 E3 w7 F# @+ E8 e - if(huart->Instance == huart2.Instance)
h* T$ b8 h* L' E9 f/ D - Usart1type.dmaSend_flag = USART_DMA_SENDOVER; " j$ S: m" m- W6 B& M
- } 7 W$ m8 W4 {4 ?& ~% ?5 m; l( m, ?; a
- /*****************************************************************************4 c0 Q9 W9 x5 H+ [( \9 l
- * 函 数 名 : UsartReceive_IDLE/ Q& G9 ?" j* R
- * 负 责 人 : by
) s5 M* k: @( n; B4 G# k6 g9 T - * 创建日期 : 2020年8月27日
# D) W& _- m6 U' o- P - * 函数功能 : 串口接受空闲中断处理函数5 v5 d7 v# t* B6 K% N" P
- * 输入参数 : UART_HandleTypeDef *huart 串口句柄. r7 z, E9 o; ]
- * 输出参数 : 无+ [* d: ?% P) N5 d. o7 M
- * 返 回 值 : 4 m" o# V! `7 N6 e5 ^9 @
- * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收
1 d) a5 O; [8 q/ _. O" h+ C - * 其 它 : ' P5 T; I9 [! T; r3 Q# i
- *****************************************************************************/
7 P) t) S- b A$ Z6 g8 X+ P3 S3 W - void UsartReceive_IDLE(UART_HandleTypeDef *huart) y$ g+ f/ K, T X7 w0 P
- {6 b/ |4 j* q1 d! h# s7 r% u
- if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))5 C- C9 o& p, O0 q
- { ( Q, p1 z. b) |' N: ^. |
- if(huart->Instance == huart2.Instance)//判断是否为串口2' ?; k5 w+ _( r/ f2 S6 _
- {
|# _# ~7 R+ y4 x% D1 }6 d, I7 f - if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断
3 [! \/ ~# J) Z2 O - {4 u* u9 y! `% c8 h* n8 d+ B
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断3 h1 a8 { x1 q) \
- HAL_UART_DMAStop(&huart2); //停止本次DMA传输0 l# k& L2 q/ V7 h, | N- \
- Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度/ J3 e3 M/ e& K. t8 P+ @
- if(Usart1type.UsartReclen>0)
- B2 p( m k* ]- J/ \& j9 q - {
7 f$ j, O2 z# z( Y( j$ h - memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
& H9 t- o3 K# m) F - Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
* ~8 o6 ~9 d! K1 ?6 ^/ j" I - } . u' F4 ?/ b6 o5 a' d* R
- else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
/ y) A( ~3 O6 X; Q7 |2 b - {
! q* G( Q! @1 k* R0 A4 J2 i& U! @ - Usart1type.UsartReclen=0;
5 N7 w3 V" ^& E9 c: w! e! @ - }
7 x& p( E. u9 L Y7 Z8 f - else. u4 G# k. G: T7 |+ c
- {
2 _* g# g5 `" u4 t& G - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
" d O. ^# Z8 k2 u- z2 j - Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
8 v( C5 o, t. g( N+ K+ [, | - }
# S+ M8 G% t7 Z, _5 H8 d - memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零 d3 ` f" p; m% r3 [2 U5 V+ w
- Usart1type.UsartRecFlag=1;//空闲标志位置1
$ \) X0 [( \: T9 Q0 [. o' | - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
: i$ K4 C3 V. R# i- W8 @ - }
' v" R3 j# X6 E0 i2 d0 |1 ] - }7 y; a5 ?# ]+ o* P
- }
u6 n7 g1 _. e# X9 ~+ O3 w1 X - }0 k% ]) F4 L$ ^4 v9 A, U" Z& w
- /*****************************************************************************
' Z- X. R! s" u# Q; N9 N! j - * 函 数 名 : Analysis_Serial_Data0 g7 u, H$ b+ x+ R% K0 s
- * 负 责 人 : by
+ B T9 M" C z+ Q. N. E+ t - * 创建日期 : 2020年8月26日0 ^% K7 @2 a9 t+ O1 s( g
- * 函数功能 : 串口接收数据直接打印3 {+ i9 `9 w+ [: U, d
- * 输入参数 : void 无
- Z1 V9 v' a9 B$ o) i* B/ d7 x - * 输出参数 : 无
, E% v% I: h0 g! S7 I - * 返 回 值 : void
# \( t5 @$ V8 x" C& _. V - * 调用关系 :
6 j I# O; H- P2 ]# y - * 其 它 : " a$ p5 H9 l' g! Y2 y1 H0 j/ z! p
- *****************************************************************************/- d/ o, K: |1 E% y
- void Analysis_Serial_Data(void)
2 i0 c9 N! t+ I; N) z& Z0 w - {
? c& D! v- |7 y4 }5 t8 | - if(Usart1type.UsartRecFlag)- n" n/ V N; P: l! r2 V, V! A
- {
2 w, R5 i/ [7 A) b- S - Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
! I/ Y$ G! K( e2 c f, D - Usart1type.UsartRecFlag=0;$ t+ |; f: E8 ]
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理 * `3 U) i. l& x+ g8 D9 z# u. K0 ?
- }
, Y) ]5 L! l9 f1 b8 H4 R0 f; K - }. `" |+ D1 z1 _
- /*****************************************************************************
: F* \/ B! G: S; s* U - * 函 数 名 : fputc4 G3 V* {) P% B% ]. @7 U, W
- * 负 责 人 : by4 i% [# C* `- N' s" d9 a
- * 创建日期 : 2020年8月26日/ p, ?' G) b5 C; E
- * 函数功能 : 串口2 printf重定义
: p* q. n$ D9 D7 M3 H/ D" k! J - * 输入参数 : printf(d%/s%/%c,a)
! q5 E, d: _# n7 K ~( Z - * 输出参数 : 无' B4 W2 I5 k% Q; J
- * 返 回 值 :
+ M; l, \2 R" b- y0 n: R8 Q, t# k - * 调用关系 :
8 I/ y4 l6 _7 g8 O( Q - * 其 它 : / u1 T! H1 Z S7 [4 e# j
- *****************************************************************************/
; |& i7 l; Z' j2 g1 B, a/ L - #ifdef __GNUC__
$ R! ? T% Q! c: i# [+ {
8 W- S( P$ Q- T, v- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf7 `6 o, N' |+ m. F! l
- set to 'Yes') calls __io_putchar() */
0 I8 K$ |+ |6 _8 z - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch); h$ N, L, q9 G8 t
- #else! j$ A# Y1 O4 q. @' V
- : K4 B f0 ~7 l$ O6 ]% e: J+ m
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)2 @; j4 e7 a8 C6 A/ ~6 H
- #endif /* __GNUC__ */
1 Z0 E' H9 b) i& V* I1 y9 _ - % S& u4 H# Z7 F3 {2 A
- PUTCHAR_PROTOTYPE6 `9 b H- F! G, |" a
- {
# l, j- C; R. W! y5 S - HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
2 d- G' x& T3 c0 A" @ - return ch;
( x- O% D/ p3 a - }5 m4 [6 a* x$ a, @) U% q
% D5 ~0 c% d# C& v( A
0 G) J9 `, u* V% d* a3 [4 Q- /* USER CODE END 1 */( a8 L" y) r. f( M& N7 g/ `( d
- DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。( O2 A' }0 ?( T# Q" j& J5 w
+ G: f4 u; X3 x! W) }7 e; |; `- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
& a' @; T+ u. c0 C; E: \: m - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码 % O7 |3 e3 B' q) J: Q' L
5 l0 @ b: K! s6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */
0 k k) |& s# R" K6 [$ j! j7 Q - HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
) e' S6 d# N$ m9 @- R: i$ k - HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
# `; J/ F# [1 D8 g/ h - HAL_CAN_Start(&hcan1);/*can初始化*/0 c; X1 B X$ S( ^9 `' Y+ D/ E
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING); ) s9 j P0 O& B. u/ b
- EnableUsart_IT();/*串口初始化*/
5 |: r& R. ~# n) M" J4 x - CAN_User_Init(&hcan1);
* s" U! F) C+ r* | - /* USER CODE END 2 */
复制代码 0 c9 L- E+ `7 W* ]8 t* v/ ~
循环,对应数据输出9 `) z1 J* f* [4 B4 o
2 p0 \; p" G# ]" d0 r0 J
- /* USER CODE BEGIN WHILE */
. S7 [( \" F* Q5 G' B8 f& m - while (1)4 g" y$ r |+ \
- { 3 ~( ]# n+ }+ P2 T
- Analysis_Serial_Data();
- @" [3 a% O2 w3 K ]& N/ d/ q' a- x# ~ - /* USER CODE END WHILE */4 N, y$ w% n8 N( r8 {6 {
1 k& m% `4 n1 K9 V+ m- /* USER CODE BEGIN 3 */
6 w: V3 X# a3 w - }. [+ t2 a2 z9 D- B# {1 J
- /* USER CODE END 3 */
* K! c1 C9 s( \4 c - }
2 B* m+ Q( B- L Q - 7
复制代码
3 x, } ]2 ~& ^( G: L, \、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误+ P3 m+ ?) I. A" f1 ? P
9 ~7 M; r( k7 b0 B
% Z! E* T J' F x7 i* H
% m8 @1 g! Q' `8 h6 B4 j; y; V. N7 p. B$ k: [$ x4 m8 g
|