1.配置系统下载程序方式
G2 D& l6 B6 r7 `1 n3 ~
# F+ T3 D) K: j! U
' D; O7 X% |+ X# m, c
0 Q! L1 p9 f, J0 n1 j 2.RCC外部晶振: K; B7 p+ d4 E9 G
& V( O! Q) ~% {( G
& [) o; i* M- t8 w
8 z @" J8 P4 F6 ~6 t$ b 3.串口声明2 R0 r7 B% W) @+ w
3 r7 k- s- m+ B4 [
4 p; W+ u- H7 L" K
! J4 |( Q3 I1 U4 G1 j) ]
3 f; Q0 X7 h/ s! S. q
5 O7 y; _8 Z' [/ Q, z4 y% R
$ p# _: R7 P. B$ H e2 X/ \; h7 t+ p3 `, ?$ F
4.系统时钟% V' ^ O# ~. g& T4 X% T
! V8 b! u1 L \% J6 P
' V) [! ?) y0 C" n8 u# Q3 O
& v; m6 q, ?3 F$ K 5.生成文件根据自己需求配置
) u. V' a& L8 }- o. W7 X: _6 T4 ]; \- E
3 a6 j' k1 f e- k0 g; c# D. K) G) x, q! U/ w
我这设置了所有库,可以选第二个仅需求的2 Z" H; K# o; Q% w% U( x
6 ~5 l/ `& h5 d6 G! B) k: v- a! Y0 A! p
$ D- n* ~0 k( L8 R 还加了其他功能,这里可不参考,DMA要放在串口前+ W0 r$ Q& W; w+ T: u6 L
8 G& E. j* `. P( e/ X. c; |
0 L: a& g+ \: R2 l" k/ {1 T
8 [+ a9 p% ?9 E/ W: M& m+ O$ k8 V6.生成后修改( B/ }$ e- l$ u
2 Q b( ]! {( L1 k2 k# E: y6.1 usart.h
, v. A( g& c* ~' j- }+ B- p6 y4 \3 A, J% I, z' V* V+ f
- /* USER CODE BEGIN Includes */
* Q8 S9 `, E( E6 {7 t& s8 { - #include "stdio.h"
8 j* p y* N$ L9 w5 a; w6 D$ ^' o - #include "string.h"/ S8 |1 S, i) k: a2 Z! S, I
- /* USER CODE END Includes */
复制代码- /* USER CODE BEGIN Private defines */
! T$ n$ b3 s$ H
% E. \; c+ | s4 Y, i( f. I0 R- #define USART1_DMA_REC_SIE 256
# P: m# s; @/ E1 S. i0 \ - #define USART1_REC_SIE 512
. \4 q+ D8 E5 M) x& ?' r7 I - #define USART_DMA_SENDING 1//DMA发送 ; ]4 O: Y- p2 u0 I, j
- #define USART_DMA_SENDOVER 0//DMA发送结束' L) G7 Y2 u5 {3 J4 o7 L% S
- typedef struct
2 c; V, F5 s# j* {/ s* f - {# b% f9 } p5 g% `
- uint8_t UsartRecFlag:1;//接收标志
6 N$ S0 i& j: W( b - uint8_t dmaSend_flag;//发送标志 M0 |' M* h5 h
- uint16_t UsartDMAReclen;//DMA接收长度7 }# P. f& T" a5 A
- uint16_t UsartReclen;//串口数据缓存长度2 {( b; t" b5 Y) f, [# l+ I
- uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据' I; s J' w& `2 [4 t4 @% Q
- uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据# y4 l! g* l7 f
- }teUsart1type;
- b- K' C# m0 ]% ?/ @ N9 a. b
; ^* D! P0 S3 E1 z- extern teUsart1type Usart1type;//定义数据5 F5 A( ?$ j$ ?6 `1 P/ t8 y7 N+ ~
- ( H0 z* C3 s( z9 {# D: B
- void UsartReceive_IDLE(UART_HandleTypeDef *huart);
* J7 \& h, L7 F/ ~- ?' {" _! U3 W& L - void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
# i' t' j+ h) X: Q1 J( k2 C/ l* j3 U - void Analysis_Serial_Data(void);
" t" E6 |2 I+ ~ ?9 U' ` - void EnableUsart_IT(void);: {; A$ s/ g/ H9 c" t* u5 `! F
3 f% ]. y. O* ~& @- /* USER CODE END Private defines */
复制代码
! k. \, X. ?* {6 \1 k/ T6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。5 J. _) @2 P i3 @* t2 i' x
7 Y; K! |. m( B" m$ C- C. M
- teUsart1type Usart1type;
$ s0 `7 Y6 y; U2 [7 f3 S - /*****************************************************************************
, Y! L) |( Y1 i9 v: \* G! t* B - * 函 数 名 : EnableUsart_IT3 }* c p! q6 U$ v0 ]3 a5 j
- * 负 责 人 : by
- V) h1 e2 F! \) z7 H - * 创建日期 : 2020年8月26日# ~- R' F+ c% m! K+ d3 ~
- * 函数功能 : 串口2初始化函数,空闲与DMA中断
- B- L; l) u. B, l - * 输入参数 : 无# @9 x3 L6 I. d% W& g* \- H
- * 输出参数 : 无6 x2 T: [. s2 |8 t( b8 S4 t) y
- * 返 回 值 :
+ N! ]8 K* A3 k: `& ]' @2 q F1 ^, t/ L) Y8 V - * 调用关系 :
5 |' i2 k9 _& a6 S" r6 x) T; ] - * 其 它 :
6 z- n8 ]! `2 l, B* c# y! m+ \2 X - *****************************************************************************/
1 s C4 i; e; D2 H - void EnableUsart_IT(void)' W2 I7 V: q/ Z& K3 ^
- {
6 _2 ]5 i" S7 s2 t% q- _8 _( v7 n( y - __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
0 ^- s2 c; {9 k - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断' O! e2 i, q- y5 i( [8 F9 S5 I
- }3 v2 w& f2 ]1 L! C
- /*****************************************************************************
: {+ K" t7 t1 {/ U - * 函 数 名 : Usart1SendData_DMA
6 C, x* ~2 \% [3 G$ ^; A - * 负 责 人 : by
* d" D+ e" M; L+ \( X - * 创建日期 : 2020年8月26日; X+ y% t5 F+ O: _. U
- * 函数功能 : 串口2DMA发送函数! c G5 Y# ]/ F1 F L; {& S/ M: U
- * 输入参数 : 无8 t6 E3 f; t. F1 M6 u- G
- * 输出参数 : 无
# e! {7 z1 }4 D* ?. l - * 返 回 值 :
" E V( G% e2 Z/ o2 _- n' n5 d - * 调用关系 : # z4 E6 ]& V4 N
- * 其 它 :
* O1 M/ @7 R# Z4 T, G1 I - *****************************************************************************/6 x! ?0 T% c" N( y4 d, E3 f4 {
- void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length) ! y5 Z9 M; i5 O' e
- - t5 H2 i5 q2 \. A) T
- { 2 ~ A& V5 O& T& a- g
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
- N% p2 X& b& `: u - Usart1type.dmaSend_flag = USART_DMA_SENDING;
% ?7 C% ~* D3 u4 ]9 l5 p - HAL_UART_Transmit_DMA(&huart2, pdata, Length);
* t9 a8 N' N/ U; b `* q$ `: F - } . [! Z" J9 K4 P' a
- /*****************************************************************************5 r* K2 Y$ h! J% n
- * 函 数 名 : HAL_UART_TxCpltCallback
# D2 | J: W6 T. m/ {; K" _9 E1 S - * 负 责 人 : by2 Z& L" m. i7 H: Z# r) A% W
- * 创建日期 : 2020年8月26日* l# i/ t- L- B1 }: g/ g# L
- * 函数功能 : 串口2DMA发送回调函数
( z6 P$ _$ m! [) v2 Y) `9 Z' N - * 输入参数 : 无
1 Q! y( K) V4 K/ \6 j - * 输出参数 : 无
1 {3 D: l6 o! Z" n. z - * 返 回 值 :
7 h0 a/ R1 y8 t$ x3 |+ A - * 调用关系 : . v# g! Y7 O; b0 A+ S8 W7 @
- * 其 它 :
: _; u- u; W: R/ l* ?0 k/ ] - *****************************************************************************/
8 A0 V8 o0 F! x# J2 G+ @ - void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
/ z F& \; N4 t* ] - { $ }" E8 J; G6 F: V! J
- __HAL_DMA_DISABLE(huart->hdmatx);
, ^9 R, \ w' i. ~' S* N0 L" L1 w - if(huart->Instance == huart2.Instance) 1 A6 {& l5 J+ V1 u
- Usart1type.dmaSend_flag = USART_DMA_SENDOVER;
* g, Z* T2 s4 x - } ) O+ U9 M7 h" L, Y; {: f8 O
- /*****************************************************************************
4 Q: ?2 R2 {! a3 q; d9 B - * 函 数 名 : UsartReceive_IDLE \) y% v2 ~8 A K- B5 `
- * 负 责 人 : by
7 I: p/ |* ^7 O - * 创建日期 : 2020年8月27日
' h& j- J+ C7 I" ~3 x - * 函数功能 : 串口接受空闲中断处理函数
- u, Y4 Y6 u) ]" P. }+ G( n" } - * 输入参数 : UART_HandleTypeDef *huart 串口句柄
; m5 x" S! g5 o4 \4 [! R6 ?0 f - * 输出参数 : 无' m/ c' S6 w; b, h" p) n
- * 返 回 值 :
) j# c: A! x0 T2 M: R; E! ~+ Y - * 调用关系 :DMA接收的数据缓存在USART接收中,释放DMA继续接收 2 B r. Z* o: @
- * 其 它 : T/ J8 D9 h2 J8 s5 N9 R1 e
- *****************************************************************************/
! u" U: x* E0 o! |. q - void UsartReceive_IDLE(UART_HandleTypeDef *huart)7 d2 k s8 g6 s( v' c
- {1 J T2 l3 b6 f! F! U
- if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))1 f* v1 }7 V; ]" Y9 L
- {
7 N7 o) a8 L" q$ C6 |# r" J - if(huart->Instance == huart2.Instance)//判断是否为串口2/ A; ^0 h" |6 q, p, E
- {
- l4 Q& U8 O5 f - if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) //是否为空闲中断0 s8 U w, C( T/ P
- { k, B7 H. Y6 U* b3 e6 ]% F! I
- __HAL_UART_CLEAR_IDLEFLAG(&huart2); //清除空闲中断
3 ~/ {2 b, R( H& u9 |- E3 l" a - HAL_UART_DMAStop(&huart2); //停止本次DMA传输
+ J" a$ ?: l. ]: p1 ` - Usart1type.UsartDMAReclen = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR; //计算本次传输数据长度
, K# t' O }5 H - if(Usart1type.UsartReclen>0)
/ n1 d/ \' _% ]! w% G% _ - {0 X& A/ ~* S5 O: j
- memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
9 t: f" z2 F1 z6 H1 J& p% | - Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;2 \: G ^4 U" x# u
- }
2 ?6 R4 J0 V/ {+ e7 q& y - else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
% Q: C% V% ?3 v5 e' j" j - {
3 ], `! e4 ? \# r* ` W; o - Usart1type.UsartReclen=0;
5 A5 i* A4 Z! @ - }, q; ~- l$ H% A
- else
, N. q8 k$ C ^. n - {
: A( I9 W& L' f - memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
/ y* \% q. [3 U6 K u L0 Q- p - Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
7 t/ r4 e# L- k b7 m% Z2 [& |% f - } ) a' e. k4 L- j& J+ c$ l
- memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零
3 J7 Z) ]! V/ b7 _ - Usart1type.UsartRecFlag=1;//空闲标志位置1
0 o$ K+ C. T7 k3 b8 \ - HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
: _ ~6 w4 t4 c* x - }
. T3 f. e. y5 g( H$ Z - }, q# W/ j; R+ Q3 H2 p
- }
6 j" o5 A7 @0 m- g( | { - }
8 R0 V" [: P' A- a1 A+ y) k( B - /*****************************************************************************4 F5 Y/ T7 ~2 \; G7 `7 Y- q" W
- * 函 数 名 : Analysis_Serial_Data* _& w6 B4 s3 O' \- Z# K
- * 负 责 人 : by. @. @ @- G4 L; S/ } \ h
- * 创建日期 : 2020年8月26日/ E7 i$ i' V) Z
- * 函数功能 : 串口接收数据直接打印1 p; ?) r8 |3 r
- * 输入参数 : void 无7 J1 ?7 P- Y1 |
- * 输出参数 : 无
- o" D4 z" h( y* x% v - * 返 回 值 : void
# V! o& F+ d2 X+ Y! B0 r - * 调用关系 : ( e$ B3 p) @2 _0 K/ Z
- * 其 它 : 5 R# [0 f7 Y* \: T* l$ K
- *****************************************************************************/$ u1 @% c& O) |/ L1 f1 {
- void Analysis_Serial_Data(void)+ s4 Z$ ~$ Q5 Y$ E
- {
& @% L b; H2 k/ f9 M" e - if(Usart1type.UsartRecFlag)
+ ~7 M# [' O1 h! f$ ]+ h9 g - { 3 D: `. ?7 q R6 |" M5 H7 G
- Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);
" L. f. [% o. b; l* u3 c9 z: R - Usart1type.UsartRecFlag=0;! r5 j; y" {' E; E
- Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理 7 R6 Z2 ^- {0 Z+ C8 d: ]* ^
- }5 j8 L) I: K: Z) i7 [, ~
- }
4 t0 L9 [; r& [& Y - /*****************************************************************************; o4 W& _) L, ]. N' Y3 n! E
- * 函 数 名 : fputc
3 D6 o' V$ u% C' N - * 负 责 人 : by
9 n I) Z, Y' X - * 创建日期 : 2020年8月26日3 H3 U% Y, l3 ?$ ^9 z1 r
- * 函数功能 : 串口2 printf重定义/ k# a' F P7 l( Q0 n3 f* u
- * 输入参数 : printf(d%/s%/%c,a)
! d/ ^5 O1 W, c: M$ i! D - * 输出参数 : 无$ c2 q" o$ R9 ]& r2 j" `, _6 J
- * 返 回 值 :
; I7 N5 G: {( }2 V2 k - * 调用关系 :
7 b7 |9 H: q I - * 其 它 :
; U3 c# t& @. L1 V, Z - *****************************************************************************/! d& l5 A. ]1 i- Z! r* p- {% }
- #ifdef __GNUC__
2 o7 t ], n: H9 b% x+ ~8 o - + O0 T; z; D7 k; l+ Z( J
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
; ~# @; f; c' @. \# d - set to 'Yes') calls __io_putchar() */4 j% p. v/ k( V; U( {! M: P7 B
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
& W# {5 W) a! ?5 r* z3 b$ a) T* ]4 c - #else
3 c0 l7 o8 C& ?1 M) `) U$ p& {
- ]2 ?$ a6 s, k1 e3 P7 l# n R- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
3 J1 {- z W4 |4 k, }8 T - #endif /* __GNUC__ */
; M% a7 T }; d8 r7 T) @$ e -
3 b6 j5 g0 b" m' O - PUTCHAR_PROTOTYPE
3 ]8 A" y& o% H7 ~, n( l7 S - {: Y; G! D. a& n0 d% W) N# M
- HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);) g! J8 |9 j/ G/ y% Z5 G4 @" e5 }% E
- return ch;& A# H- \% V* k+ S$ X
- }
6 _- {7 F0 G2 G* ?3 p- J" C9 I - ) F7 N" r) p0 t3 m! h$ y% J, X
- 5 M2 H' ^# r% ~3 s4 J
- /* USER CODE END 1 */& W7 k' a$ x1 s9 E" m& V
- DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。! h% v0 V( i0 t$ H
- 3 Z! W: x; u1 ~, }, N6 |
- //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);
3 O5 ] e+ q$ s8 e) _) U - Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码 8 T0 _0 {/ U5 V& o. w" p
1 t1 X# e; d7 N1 G6.3 主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数- /* USER CODE BEGIN 2 */' d' ~- V( b( z2 R4 b
- HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/( u4 T7 T9 W f4 y6 Q6 L* Y
- HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
' `0 ?: V) s5 m3 C - HAL_CAN_Start(&hcan1);/*can初始化*/& l: k1 `$ G9 r% |& j/ J
- HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
6 H: b& f$ N; q+ W+ k - EnableUsart_IT();/*串口初始化*/) w+ M. D, S/ x" w
- CAN_User_Init(&hcan1); * N" ~: ~7 Z3 }; t
- /* USER CODE END 2 */
复制代码
6 w! E. q8 s! g: } 循环,对应数据输出) k2 W6 t* M3 k4 w) E1 m
" ?: @- ]3 W+ E0 P
- /* USER CODE BEGIN WHILE */
7 B, e8 g9 D+ H2 F# ?* C - while (1)' n0 v) R+ L( ?# k: e1 F
- {
+ h6 J* a7 N" b0 Y" J8 x% E, a - Analysis_Serial_Data();3 W- \7 n+ L; `" Z
- /* USER CODE END WHILE */
4 v0 a1 h6 I% O) l4 I8 Y
1 W; c2 d- Z1 t4 `- /* USER CODE BEGIN 3 */1 W: W9 U5 g/ J8 L' m
- }
5 P0 T" o/ }' n; o" }7 d7 B" u - /* USER CODE END 3 */
7 m( r8 N, {" y' W7 ` - }
0 X# ^! O# o' }5 @$ S - 7
复制代码 1 h& ]" ? G7 c( q7 ]: |' v
、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误
: t$ `8 @: ` L# k3 [( ]
' P- a8 s3 s6 b( M9 C2 B
4 @& i2 x: T1 I+ e/ _2 L+ V( _ h9 k9 R9 F; s. T2 f4 u. S6 P
. _- \1 [& f) ]" L. \
|