1.配置系统下载程序方式9 ~2 T9 v, M1 W+ S& x" g
8 [' @# V7 k2 S- [+ J1 ~
0 T' c' Y6 f* [
, |$ m3 {& `% X V8 d 2.RCC外部晶振
: I+ U; M, p9 r" y, _2 [; S% r! \
! I/ ^( n" ~- O: A! ]4 B
c, H- w% E$ S. O6 i" P6 p 3.串口声明
C$ u0 Y {2 U+ t& l
, f! s6 E3 j) y! b
" m/ G5 W# I! W) Q( y- W
8 n/ c/ q/ `& N* ~& u3 {; C6 O4 O/ ^( d9 @! d4 X0 \
9 k& Q6 j7 X, D! \
7 k9 x( V0 O! ~ G% M5 c) U$ g& _) C2 r! g$ k& M) g ]
4.系统时钟) ]8 [! K! S j
3 c1 x- e6 i W. p9 ^% m; C( Y
$ R( p7 K/ @: F0 l& Q& o" U
2 r8 {6 g8 p* R. b- e
5.生成文件根据自己需求配置
+ v7 B/ S1 ^$ c9 U B7 ~; {1 W8 e1 n& _8 @# p& v
0 l9 g" a6 C B8 k5 x( l
: `2 J" F+ W% n: L! s% p0 q 我这设置了所有库,可以选第二个仅需求的' K1 Y+ c' W( X( w
8 q6 q% r1 X; |5 z' C; p
3 n5 D2 B/ a, |) b
( }( d: `& W; ]9 D7 i) i 还加了其他功能,这里可不参考,DMA要放在串口前
k" D# H4 R. R& ]' f7 a7 {8 N- \/ _! z) j5 u+ z
$ j9 u6 {7 p0 s, i" f: |
~6 b) Z9 a5 H; I6 U7 g& H' [
6.生成后修改
6 h3 p5 @* S: H V' G0 b( w
2 `6 v2 @0 \8 n, t$ b4 G& y6.1 usart.h" P. r2 Q8 C' Z, Q) W
; K% i: P7 m) H
- /* USER CODE BEGIN Includes */
6 O$ U0 i# @* }! S: | - #include "stdio.h") g# u1 O( w W
- #include "string.h"/ D' {& @! ~. ?) `2 h: J) e
- /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */0 R8 t2 g# p7 D; _/ e: V8 l
- 3 X- B# N: \9 ?$ J0 Q% \! B
- #define USART1_DMA_REC_SIE 256
" K0 l+ |6 G% { - #define USART1_REC_SIE 512) M, H& h) y; l1 q' C' v$ b
- #define USART_DMA_SENDING 1//DMA发送
2 K( J# Y+ B' u/ q - #define USART_DMA_SENDOVER 0//DMA发送结束/ |; c" f0 t- S$ T5 r* ? |) l6 {
- typedef struct4 @; C" \! L7 J! X
- {- ^" r" ?* m' s! O/ K9 Q, d( u6 G
- uint8_t UsartRecFlag:1;//接收标志
! N- q0 i. y" W7 {5 d2 {2 m& Y8 ` - uint8_t dmaSend_flag;//发送标志
4 d) ^% O9 z2 Z - uint16_t UsartDMAReclen;//DMA接收长度6 D; h- F- |! W, o$ @
- uint16_t UsartReclen;//串口数据缓存长度2 N7 P% ?6 K$ `) k3 {6 t5 u
- uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
" `, w5 i) a" R2 {. ]+ R - uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
. z& I, d0 d% B, x - }teUsart1type; W p# @, z5 v: _0 S# n, E7 F
- % |5 Z6 k4 b% i9 J/ w' `$ d
- extern teUsart1type Usart1type;//定义数据
- P/ _# |. H% w& h# R, ~% g; @! M
& [2 e' D& ^6 E: s- void UsartReceive_IDLE(UART_HandleTypeDef *huart);, [* S+ J3 S* @" C# n( }' v/ M+ V
- void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
6 n( l9 p" M& Z; {3 T, q - void Analysis_Serial_Data(void);8 t' @# \9 @" V9 r' K- c- X6 A
- void EnableUsart_IT(void);
6 P) v \) ?5 A8 c$ g2 `5 a - `3 F1 y9 z/ @& ~. q* P
- /* USER CODE END Private defines */
复制代码 " `0 Z$ w. `% w. z
6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。3 L' R% v- N. ]2 _1 B
% ~0 _* _% Y* r( y: h9 Z- {
- teUsart1type Usart1type;
: F6 P: s) Q7 u, S1 s5 \ - /*****************************************************************************
% p0 T8 y8 |2 f, k ?# |- e* l - * 函 数 名 : EnableUsart_IT
- @$ Z: p$ C( \1 c# x, V- q - * 负 责 人 : by6 ^% i: H9 P9 s7 q
- * 创建日期 : 2020年8月26日! t1 w9 Y9 V9 o; @/ ^8 Z5 n
- * 函数功能 : 串口2初始化函数,空闲与DMA中断+ r$ m p- I8 i8 J+ p+ y9 t- s
- * 输入参数 : 无
0 Y j. H& ]. ? - * 输出参数 : 无4 }% @1 A0 M/ X, r% s" ]3 {
- * 返 回 值 : 6 d" H' a6 Y# M7 u& B' D
- * 调用关系 : ( e+ ]3 _) D2 ?8 F
- * 其 它 :
. K% r2 p, r3 |1 U+ I - *****************************************************************************/
7 _4 ]7 q' g1 V* L! D5 M7 m - void EnableUsart_IT(void)
@* u4 C8 o; O9 p* Y" E8 b+ f - { 0 k3 @, x$ H+ S6 L6 B
- __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
7 o# V: N3 a( B4 g5 s - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断( V5 u9 A0 Q& @; h$ k
- }
& O# C, ], c0 ]2 H) O- ^ - /*****************************************************************************
3 y7 y2 s# Q3 _6 h. [ - * 函 数 名 : Usart1SendData_DMA
, O) q. E3 e O3 X$ M - * 负 责 人 : by
0 s( A' U6 a& {. Y0 }" M; D - * 创建日期 : 2020年8月26日, M& S; z) a, ]2 x) F9 E# H
- * 函数功能 : 串口2DMA发送函数
8 }! H& L" c" t$ u - * 输入参数 : 无
7 M1 F2 L2 T* s9 F - * 输出参数 : 无. v6 V) O8 `0 }' Z5 g( h
- * 返 回 值 : , x6 |7 P3 d+ @+ V5 ^6 z
- * 调用关系 :
" v6 A1 \- D" A6 e3 \ - * 其 它 : 4 F5 _4 @. R* s
- *****************************************************************************/ W3 c6 x, W6 D" Q
- void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)
) l& h) S( c2 h2 q$ ` - 8 O: G0 a% Q8 Z a/ p
- {
, m- @9 l8 o* G/ E. ]7 h. Y* T3 x - //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
) F; x5 T( |4 I- U - Usart1type.dmaSend_flag = USART_DMA_SENDING;
- }' b% h0 m: L3 F' \ - HAL_UART_Transmit_DMA(&huart2, pdata, Length); : s' T7 G6 ]. e. ^( c
- }
k+ ^0 {/ U8 X. X - /*****************************************************************************
+ \7 X; C' a4 w - * 函 数 名 : HAL_UART_TxCpltCallback
8 [0 y/ y' i' X/ ~& ^ - * 负 责 人 : by
. Z- p+ m3 c1 b2 e$ Y1 z9 G2 I9 E - * 创建日期 : 2020年8月26日! b# x A/ x% V' D' k: C
- * 函数功能 : 串口2DMA发送回调函数
) s4 e+ b% y- N9 F/ ~) x% T* {+ k - * 输入参数 : 无
* ?7 X3 B/ x2 k; f a1 C! C - * 输出参数 : 无
9 s/ c1 ^; A; {* J - * 返 回 值 :
9 x& X3 K! T B5 m7 L& P% d6 v - * 调用关系 :
# f& P8 [9 x9 a/ |& c - * 其 它 :
. v6 Q6 Y5 n* N- n' C+ ^ - *****************************************************************************/) p) d4 Z$ p6 `
- void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) ?8 c: g) L4 u) O& K( A1 ?
- { , C7 O+ B0 ^; b" i# D0 h/ W$ J! [
- __HAL_DMA_DISABLE(huart->hdmatx); / i, n5 K! z$ b3 c9 [, x, ]
- if(huart->Instance == huart2.Instance)
% d4 Y0 x' ~) s- z0 V - Usart1type.dmaSend_flag = USART_DMA_SENDOVER;
; B4 ?' F! O, A& U$ ~$ h2 H5 N - } # C3 r# {( {+ x _2 j, b
- /*****************************************************************************) j. a2 Z' _2 Y
- * 函 数 名 : UsartReceive_IDLE
, m3 r- }( Z! l9 @! n - * 负 责 人 : by
+ s: H3 W( K: W8 F8 ` - * 创建日期 : 2020年8月27日
) c' N5 M6 G' i; [ - * 函数功能 : 串口接受空闲中断处理函数
4 K8 s8 y+ X" F3 A" | - * 输入参数 : UART_HandleTypeDef *huart 串口句柄 ?, C. i$ ^7 v
- * 输出参数 : 无
" C' s" l N) h+ o1 [8 o( h/ J - * 返 回 值 :
, _6 w8 `3 M* d U. e - * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收
! Z# f: L# b1 b+ h8 p3 ^0 \5 U - * 其 它 :
! J8 G6 a& D& q - *****************************************************************************/- @9 x$ R P2 g+ f0 M, t; N7 H- i
- void UsartReceive_IDLE(UART_HandleTypeDef *huart) \, z* s) X+ a' }9 I
- {+ b$ }8 K, t. n! B
- if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))1 L3 v" M" z C+ S5 P7 P" r' b% r
- { 4 X' C' [; O4 v% h
- if(huart->Instance == huart2.Instance)//判断是否为串口2
. f- U% A$ U. h, B - {+ I: {1 Z6 m* |. {
- if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断- m8 H( c9 k, D2 B% N
- {" V3 w' O: ?: @( N, z
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
7 `; b* O2 v( O, Q) ? ^ - HAL_UART_DMAStop(&huart2); //停止本次DMA传输
. z/ T F c( O# `$ u - Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度& @2 z ]' O. W Z2 g+ d; N
- if(Usart1type.UsartReclen>0)
1 S$ e7 A5 }6 e/ D# U0 m2 D - {; h3 G3 M, y: G) o
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);/ P4 g* ?9 ?& C7 \/ [' x+ t
- Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;* h4 d9 i+ O& H W R4 z- R. X
- }
# m) ^! }8 k# k8 R - else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录5 Z6 x" u& [0 o+ b2 h5 F
- {
+ H1 `- \: k& d# E - Usart1type.UsartReclen=0;; i1 L6 p' g% g. W! t" Y
- }
- z0 N- |3 ~2 X$ y% R8 w - else
7 l) x o; k8 _0 e3 O$ H- n - {
2 c4 g0 @8 M) B, H+ R2 G - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);* F) x5 J- T- v
- Usart1type.UsartReclen=Usart1type.UsartDMAReclen;, O5 y/ ^- g, G/ x7 O+ ~
- } - N) f2 A7 Y+ j3 D! J4 Y
- memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零
6 Q& z7 I( d7 Z7 N" b& ^ - Usart1type.UsartRecFlag=1;//空闲标志位置1
$ L9 `, m* t3 p. o2 d& s2 g. D - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA p0 b- J1 `3 b
- }
/ U* T( M B6 X) R( A3 T - }# U* L, e4 [+ u) n' E. I. h
- }2 d/ h# i9 Y% N3 @+ x
- }8 S# s7 g9 u+ ?9 k+ [" g
- /*****************************************************************************
; W9 P9 D% o7 @: e - * 函 数 名 : Analysis_Serial_Data! G. z! X+ L2 Y: |1 _4 m! V1 d
- * 负 责 人 : by
; {, i. f/ |+ I9 G- @/ r - * 创建日期 : 2020年8月26日
7 o; |3 S* Z) r, ~ - * 函数功能 : 串口接收数据直接打印
4 d5 W& U' W2 X- r. h& G - * 输入参数 : void 无
2 }' P: L) `: M. ], M& R - * 输出参数 : 无
( U( C1 A6 ?* a. F - * 返 回 值 : void
, X5 U# E. j2 e& C; N: D - * 调用关系 :
* u, S3 O s) n) a3 s - * 其 它 :
! M) a% q0 ?+ v/ w4 p - *****************************************************************************/ b" x* C, \& f
- void Analysis_Serial_Data(void)
; ?# y7 p! o% Y A: \. c2 O2 q - {
4 i7 E, D) t5 |/ l* u - if(Usart1type.UsartRecFlag)2 ]: g) j u7 Q. X
- { 7 i6 Y! P; Q, X' v) m/ E
- Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
; b5 N8 M6 }4 c: j! x" i - Usart1type.UsartRecFlag=0;/ b, \- N1 D' o+ A# u: i
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理 ! T H) b: }( O# G/ s8 s8 a
- }
$ X9 Q: G% ~8 K0 e, e& K" } - }
) g# F, U+ D/ N+ U - /*****************************************************************************1 y8 @+ c3 T7 ~+ l) J
- * 函 数 名 : fputc4 Y& O Z1 M; i. H
- * 负 责 人 : by
+ s3 I0 |3 a. J+ x4 K - * 创建日期 : 2020年8月26日
" }* q, {+ p8 q - * 函数功能 : 串口2 printf重定义
' y% T# c4 c5 g, |% s - * 输入参数 : printf(d%/s%/%c,a)
4 b& i3 A1 j7 h1 P; u - * 输出参数 : 无
$ H! E! Q9 @' L) c/ e8 q# B3 P# h - * 返 回 值 : - ]; O2 N* P2 O8 [( V2 c
- * 调用关系 : 1 G& |; T- n1 Y: E0 W
- * 其 它 : 2 T8 S& K; a8 e$ ^) Q6 Q
- *****************************************************************************/
* O |5 b0 P6 L1 E8 i - #ifdef __GNUC__6 J: {- t9 ?" W# \) J) B
: `1 @! f7 W0 P( ~# J- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
3 g+ P& q1 a1 o; ^+ ]$ Z3 z - set to 'Yes') calls __io_putchar() */
) n o( r' P3 \6 L4 @, N4 M - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
" X2 h: `% e/ l/ K - #else
% Z- b+ ?: A- Z" t
) e- w( O1 |% Q- u" N# ?( Q- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f), w8 I1 ]* H; q
- #endif /* __GNUC__ */
. j8 L K% p4 D/ \4 c7 M - & f6 t! N R& e
- PUTCHAR_PROTOTYPE
5 l! R6 C0 O& v+ R, y2 `0 Z - {- \: `; ^8 _( k! m+ a
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);% `1 w* L: c4 r+ E& @9 n5 t
- return ch;
' Y1 Y4 k: L6 y - }
9 e7 j9 D) B. x' y) x) T2 j
1 ~* W2 k$ G: q* @* `7 @- , D: v$ }4 ?/ @
- /* USER CODE END 1 */
! E; K, l# Y/ J1 V* C+ Y7 o* `' p - DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。$ K, y' v6 r$ A% ?$ a: A9 W+ `
- . B) n1 R; C5 Y8 L( g# v
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
* i; i7 `& y; J - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码 - l( U& y8 ~# D6 L( Z+ L
0 \# E: c5 c5 b( k# {, ]* C+ e6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */( |4 J0 S& U6 z& p& K1 ?
- HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/. h, U+ a- k( a5 Q/ m% w
- HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/8 s0 u: p3 p& X. V; q' U
- HAL_CAN_Start(&hcan1);/*can初始化*/
2 }3 ]: k) M J; C- L3 n* s4 Q* u - HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING); 0 w* h5 U) P( z$ ^* q
- EnableUsart_IT();/*串口初始化*/2 r+ S/ F4 o4 b0 I- w
- CAN_User_Init(&hcan1); % D/ m' u. ?/ K
- /* USER CODE END 2 */
复制代码 4 B/ \8 S& |/ |; c( q- w) y5 ?2 M
循环,对应数据输出
v9 r/ l. F( I6 ]# R, x" D! O% W
# D! h: I! w9 h& F" v- /* USER CODE BEGIN WHILE */+ Q. N/ S' Q) j4 z) p3 k% ?5 R
- while (1)
4 p: o; H+ c8 A M/ K# w0 ] - { ?2 k1 B1 s: I7 a0 y( L" j' N
- Analysis_Serial_Data();
# k0 [2 \% I5 f( y: v3 | - /* USER CODE END WHILE */
9 M) v) Q. s( h5 @: Z5 i M
: H9 X8 a+ I3 V0 W" J& u- /* USER CODE BEGIN 3 */
% ]& Q5 Y) V6 D - }
f; c" n2 i" P7 o, D! H - /* USER CODE END 3 */0 ]: {+ V. J& Q4 U2 N
- }, T7 q8 ?! @7 w
- 7
复制代码
6 i( d/ L. e2 v7 i、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误3 }) p) ~4 L7 D% v9 N6 v
' T6 m. Q5 I1 f+ n
, w+ C$ [- i6 W4 ~8 n: V h
1 D& B- R. Z) W6 p% b9 p
: x* @5 v7 t$ l e" U8 D4 J3 k0 s |