所谓的串口直通是指MCU把从USART1接口收到的数据送往USART2接口处发送出去,由USART2->USART1情况类似。这个时候MCU只是当作一个调试模块,而不做任何操作,举个例子:比如蓝牙模块的接口是串口,我们想要使用MCU来对蓝牙模块进行读写控制,在调试时我们需要确定蓝牙模块是否良好,这个时候就可以使用串口直通模式来测试与蓝牙模块的通信是否良好,代码很简单只是开启了DMA即可,如下:- #define USARTx USART1+ p& x; ~, T( c8 s7 _, [
- #define USARTx_GPIO_PORT GPIOA0 n5 _( G( I3 q2 j
- #define USARTx_TX_PIN GPIO_Pin_9; R j8 L U! c& _9 n
- #define USARTx_TX_SOURCE GPIO_PinSource9" R9 }# g- ~; C$ J4 `5 k! j r. ~: }
- #define USARTx_TX_AF GPIO_AF_1
/ C+ ]& f! V" r9 x/ C+ k - #define USARTx_RX_PIN GPIO_Pin_10
. O( i5 b# V1 y/ J4 B$ q9 v/ z - #define USARTx_RX_SOURCE GPIO_PinSource10
. q* k+ t0 ]# l8 M& g - #define USARTx_RX_AF GPIO_AF_1
, x! }9 U( _9 f - #define USARTx_IRQn USART1_IRQn9 u- E, x. d2 D J9 {* [4 I
- #define USARTx_IRQHandler USART1_IRQHandler0 g5 `+ D- d8 `: P$ G! r
- #define USARTx_CLK_ENABLE() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)8 Y, l! E9 q/ n4 q
- #define USARTx_DMA_CLK_ENABLE() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE)
, n; {6 N6 v# k8 ] - #define USARTx_GPIO_CLK_ENABLE() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE)
" L L" q* Z! G; z -
, p$ @6 s* @! E0 T# H* M' X - #define USARTx_RDR_ADDRESS (uint32_t)&USARTx->RDR( f8 i0 E1 y- s# A
- #define USARTx_RX_DMA_CHANNEL DMA1_Channel3
# U8 h f% y1 T, b7 c9 H8 s - #define USARTx_TDR_ADDRESS (uint32_t)&USARTx->TDR3 h e. q# d5 F C% u# \4 g
- #define USARTx_TX_DMA_CHANNEL DMA1_Channel2- d3 U2 ^9 W$ x( ]7 X# {' d+ S* u% }
-
; d) J1 T$ \- d* ^/ W7 o - , E2 |9 ]/ v5 D" l6 A8 ?" ]- O
- #define ISP_USARTx USART26 l9 @+ q/ K0 z$ p$ k6 J1 u
- #define ISP_USARTx_GPIO_PORT GPIOA6 { w0 u( O0 \$ h/ n/ M% K
- #define ISP_USARTx_GPIO_CLK RCC_AHBPeriph_GPIOA
' Y$ h% L8 t! G g2 O - #define ISP_USARTx_TX_PIN GPIO_Pin_20 f6 L1 }8 X1 T e
- #define ISP_USARTx_TX_SOURCE GPIO_PinSource22 O ^; D) K' Y: O1 j
- #define ISP_USARTx_TX_AF GPIO_AF_1
# ~4 p. C5 b3 Q7 g" i# M - #define ISP_USARTx_RX_PIN GPIO_Pin_3
8 w1 y8 _0 a/ P: V9 ?* Q - #define ISP_USARTx_RX_SOURCE GPIO_PinSource3
+ j; d, W1 b8 e( ]% } - #define ISP_USARTx_RX_AF GPIO_AF_1, t2 U* M' a+ X
- #define ISP_USARTx_IRQn USART2_IRQn
% w; F/ Z' ` L( I- |* a - #define ISP_USARTx_IRQHandler USART2_IRQHandler
" `) d, O9 G$ E/ v* s% j I. B - #define ISP_USARTx_CLK_ENABLE() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE). \3 X( F$ ]. U+ Z
- #define ISP_USARTx_DMA_CLK_ENABLE() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE)3 t- U, o# J7 s3 U/ a1 D! o
- #define ISP_USARTx_GPIO_CLK_ENABLE() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE)2 C5 q* q6 E2 T6 ?; Q
-
' Z. H3 Y: H. Z j& P, `; p - #define ISP_USARTx_RDR_ADDRESS (uint32_t)&ISP_USARTx->RDR
, N7 V0 c, C2 h) B& D3 P8 r - #define ISP_USARTx_RX_DMA_CHANNEL DMA1_Channel5
4 U/ p0 v5 I) k - #define ISP_USARTx_TDR_ADDRESS (uint32_t)&ISP_USARTx->TDR" f* k& X) e$ n4 Q! ?4 d# Q* C
- #define ISP_USARTx_TX_DMA_CHANNEL DMA1_Channel4% t1 g F$ O5 E- O, v% B0 L6 y
-
) c6 b# ? @9 o9 j - void uart_init (uint8_t baud)
9 f# @- H, q5 b - {
- k2 {+ X3 r! Q% _2 q. k - USART_InitTypeDef USART_InitStructure;
+ Z# J: S+ j9 R* o% P - GPIO_InitTypeDef GPIO_InitStructure; 7 o( x+ O4 ^2 u5 I# d
- DMA_InitTypeDef DMA_InitStructure;, [2 p# T6 ~/ s2 d; @) X
- / W. r! M0 e- e7 e" X9 K
- USARTx_GPIO_CLK_ENABLE();7 w, F, m, @$ Z0 X# `6 f& T2 w
- USARTx_DMA_CLK_ENABLE();
; N# X' {1 Z6 [$ |! ?* z - USARTx_CLK_ENABLE();
* E" k! l/ j8 [# f - . ^& Z. n% r5 v% c5 s& O
- GPIO_PinAFConfig(USARTx_GPIO_PORT, USARTx_TX_SOURCE, USARTx_TX_AF); L8 X' @5 Q: T0 ~) e W" X& F' n
- GPIO_PinAFConfig(USARTx_GPIO_PORT, USARTx_RX_SOURCE, USARTx_RX_AF);
7 n: d5 O( o) u4 ~) Z -
8 ^( ?) n5 c& p - GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN| USARTx_RX_PIN;
% r7 @& v4 ]4 n1 H2 h - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; $ d X. A4 T) @4 z5 e4 ]: H9 _* M9 ]
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 2 F& O; X- h& t3 K
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
' {' {6 Q- ]* d7 z- h - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
' l5 B6 q; F' L - GPIO_Init(USARTx_GPIO_PORT, &GPIO_InitStructure); 3 Q* L. R2 F/ `" r4 Y
-
# ^8 e, W- A' b K' {) m2 ] t& g - USART_InitStructure.USART_BaudRate = 115200; " C3 E& N% P' o: X4 C5 D. h
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; " k2 l$ O4 }2 N% A
- USART_InitStructure.USART_StopBits = USART_StopBits_1; ; z' |4 F" i. e- V- m
- USART_InitStructure.USART_Parity = baud_type[baud&0x0F];
* M5 A0 x1 i7 M& o! ^. {! S - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- d4 @( T/ V3 S% E' w - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; / v7 j. m8 ^; ^& f& P) |
- USART_Init(USARTx, &USART_InitStructure);
! s5 W: b% a2 ~- ?- K0 ~1 \ -
# t; k0 P) f0 u - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
$ `- l0 z% c L) Y - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;: @6 k1 s# q) o% [
- DMA_InitStructure.DMA_PeripheralBaseAddr = USARTx_RDR_ADDRESS;" P& p8 ], @+ G
- DMA_InitStructure.DMA_MemoryBaseAddr = ISP_USARTx_TDR_ADDRESS;# H% Q% L! v* s0 O- _) d
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;) A' J( ], V. d& Z+ e! v
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
# Q4 O0 l4 J/ f0 A5 e - DMA_InitStructure.DMA_BufferSize = 1;
: B/ ~5 Y' X+ U8 D" B - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
0 w8 A/ I; {% K9 g1 f - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
! G5 \5 p) P- n, l, o5 Z' R4 } - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;( ~9 @" w% f! z2 i$ U- Z
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
' k" @, H' G3 K. ]9 A$ T( M - DMA_Init(USARTx_RX_DMA_CHANNEL, &DMA_InitStructure);
5 |* X3 _0 J7 J5 b# T, P -
: H8 P1 @" v* b, E, \, U - USART_DMACmd(USARTx, USART_DMAReq_Rx, ENABLE);( p: ]! P! S& e- w: h
- DMA_Cmd(USARTx_RX_DMA_CHANNEL, ENABLE);
8 Y, d0 u. X" G4 c5 s - USART_Cmd(USARTx, ENABLE);
1 @- m% _" `* |* u! N% h - 8 ^" x6 ` b1 y$ J1 V/ @1 ?
- }
! V& t$ f- H* T* k$ L$ F - / U4 b; [2 R6 X V) _& {
-
( W. h$ `0 P7 T% E6 U - void isp_init (void)5 g) d2 V, e3 [/ {
- {# x) ^' J) ?' ~8 M0 q
- USART_InitTypeDef USART_InitStructure; ; i% l$ L6 h% y- W
- GPIO_InitTypeDef GPIO_InitStructure; u5 C$ @3 K) G7 _! H
- DMA_InitTypeDef DMA_InitStructure;0 y. k$ L9 z( b* {' [! f% }
- + e1 c7 w$ s' @6 ]7 K( Q' j3 J6 }
- ISP_USARTx_GPIO_CLK_ENABLE();
( q+ k7 t6 O' g- @3 N - ISP_USARTx_DMA_CLK_ENABLE();
( ?+ O! A+ R1 H3 h: X - ISP_USARTx_CLK_ENABLE();
2 H# a, Y; ?* R/ q6 d+ e) s D -
' U! c/ }* ?) @8 _ - GPIO_PinAFConfig(ISP_USARTx_GPIO_PORT, ISP_USARTx_TX_SOURCE, ISP_USARTx_TX_AF);
3 F W, @0 W% x2 h8 t" {4 i: [ - GPIO_PinAFConfig(ISP_USARTx_GPIO_PORT, ISP_USARTx_RX_SOURCE, ISP_USARTx_RX_AF);. d& b S7 L; l1 e, ]) p
- 1 N9 W) \0 f$ ?9 N& S: X
- GPIO_InitStructure.GPIO_Pin = ISP_USARTx_TX_PIN| ISP_USARTx_RX_PIN;
/ R) {" V' b$ m; N3 X# x/ B% a: l7 \( | - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
" ~3 }* m* G8 S, z - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 1 o8 f) J: M: g! P- F+ @- W8 M
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
, I) K; h, I/ o' g5 Q - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; 4 y# u: a8 h8 L G
- GPIO_Init(ISP_USARTx_GPIO_PORT, &GPIO_InitStructure);
2 A( K: n' ~" P- O6 y- D; D# Z, p - 2 i8 Z/ v0 z: d ?% w
- USART_InitStructure.USART_BaudRate = 115200; 0 J% \8 }, X$ G8 J
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
! o- Z* y) C6 n; h) D4 {6 I - USART_InitStructure.USART_StopBits = USART_StopBits_1; 1 E W& E! Y" w; C. Z' ?: m- b; s
- USART_InitStructure.USART_Parity = USART_Parity_No; }2 U: m' t% M! h+ r9 z* j: i
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; , y( x5 Y7 |0 }3 J8 v
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 6 |$ f& ^4 ]# B. d, s9 @( V, z5 S
- USART_Init(ISP_USARTx, &USART_InitStructure);
8 F2 D& X# ?' l9 T -
: x8 s% @0 [+ E% i" | - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;$ ]9 p0 {& ]& x, {
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
3 J1 c8 Z, x/ O! ` L) m - DMA_InitStructure.DMA_PeripheralBaseAddr = ISP_USARTx_RDR_ADDRESS;
% X$ ]7 V, J! R2 s$ x - DMA_InitStructure.DMA_MemoryBaseAddr = USARTx_TDR_ADDRESS;3 n2 j- S s" _' B2 @, P
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;3 d7 a8 V( `6 O+ V- E6 x8 @$ }
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
$ u; t' w0 s; C5 E - DMA_InitStructure.DMA_BufferSize = 1;
5 g: X7 P' G4 i; o- ] - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
' E* ]3 e6 s/ b. s c3 k) } - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
4 ~0 c, R$ E+ u6 @ y - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
0 s- b/ a9 o. H2 H7 @ - DMA_InitStructure.DMA_Priority = DMA_Priority_High;. k; q) A! I0 k
- DMA_Init(ISP_USARTx_RX_DMA_CHANNEL, &DMA_InitStructure);! a- D# s" V. k- B1 b2 `( [/ k
-
1 W1 f* C- m* O9 p5 j - USART_DMACmd(ISP_USARTx, USART_DMAReq_Rx, ENABLE); 5 J8 ?4 m6 y! Y3 A' D* h/ A6 E
- DMA_Cmd(ISP_USARTx_RX_DMA_CHANNEL, ENABLE); 1 X9 ]' f2 y* D0 r# A/ U
-
2 E& ?9 y9 h9 B - USART_Cmd(ISP_USARTx, ENABLE); X4 W- E4 f: F( O" z% f8 Z1 K! a
-
! x4 l3 u p: ^ B" j; Q - return;, q3 V& e! g; c% Z2 G2 k& c
- }
复制代码 分别初始化两个串口并使能DMA RX功能,且DAMA的模式为DMA_Mode_Circular,内存地址不再是SRAM而是另一个串口的TDR地址。如此这般,就可以把串口1的数据直接从串口2处输出,用户在串口1中输入控制指令就可以操作与串口2相连的蓝牙模块了。" e* ?* t; M: Y( J
PS:该代码只是在调试阶段方便调试使用。
/ k! z( b3 r' e! P |
还没出现过
之前我是在接收中断里,直接把数据给到另一个USART的TDR寄存器。
嗯,之前我也是在接收中断中发送数据到另一个USART的TDR寄存器中,后来就想省略中断用DMA,正好顺便测试下DMA的外设到外设的数据传输,这也是我想的一种DMA外设到外设的传输场景。
我用的电脑虚拟的两对串口进行调试,连续发送一直丢数据,只能等实物出来再调试看看了,感谢楼主的分享与回复