HAL驱动的串口编程陷阱" q1 _7 F4 {+ p
7 H3 _8 \- A# {. w+ a' Q$ q+ jSTM32远程升级(基于串口本地升级与WiFi通信远程升级)& t( [2 {+ F1 j6 D' S
) U1 F3 b5 x- M/ R+ A! w
5 U1 F5 C m6 g9 N
4 u$ D6 m2 I; ?* v, _+ G
串口是嵌入式开发中最常前的外设设备,既可以用作不同单片机之间的通信,也可以用作在STM32 MCU和PC机之间的通信,STM32F407的串口功能非常强大,可以接红外,可以接流控,也可以接SIM卡接口,但我这里只介绍我们最常用的UART通信的一点调试经验,以STM32F407为例,对其它STM32芯片也适用,希望对大家有所帮助,如有错误不当之处欢迎大家联系指正。
5 ^% x" S( D# F6 ~. d! n# d2 n2 c1 V/ d7 O
一、串口的三种工作方式
4 S$ p! r" q( P操作串口一般有两种方式:查询和中断;STM32还支持第三种DMA方式。
6 r: a& @/ H, e(1)查询:串口程序不断地循环查询标志,看看当前有没有数据要它传送或接收。如果有的话进行相应的写操作和读操作进行传送或接收数据。
$ i# d- F5 R. a! l4 u- O(2)中断:平时串口只要打开中断即可。如果发现有一个中断来,则意味着有数据需要接收(接收中断)或数据已经发送完成(发送中断)。& t" V4 u: W; |5 N* w9 W
(3)DMA方式,设置好DMA工作方式,由DMA来自动接收或发送数据。
/ h% Y' m+ P s1 ]( y9 m7 O0 `( N; e一般来说,查询方式的效率是比较低的,并且由于STM32的UART硬件上没有FIFO,如果程序功能比较多,查询不及时的话很容易出现数据丢失的现象, 故实际项目中这种方式用的并不多。
# a7 ?; z% ?0 g! J) B+ p中断方式的话我们可以分别设置接收中断和发送中断,当串口有数据需要接收时才进入中断程序进行读读操,这种方式占用CPU资源比较少,实际项目中比较常用,但需要注意中断程序不要太复杂使执行时间太长,如果执行时间超过一个字符的时间的话也会出现数据丢失的现象,这个波特率比较高的串口编程中比较容易出现,可以考虑用循环BUF方法,在中断程序中只负责实时地接收实数数和发送时的填数(写发送寄存器),其它操作放在中断外处理。7 o$ W) B3 C& r' n8 Q* {
STM32还提供了第三种DMA方式用来支持高速地串口传输。这种方式只要设置好接收和发送缓冲位置,可以由DMA来自动接收和发送数据,这可以最小化占用CPU时间。4 S3 I" H$ @: q7 r! Z
& u3 a4 m' W' U; f
二、串口的使用步骤
' Q6 {7 m2 d5 g" q [( I(1)中断方式
$ V( D. [6 G. N; q基本步骤是初试化时钟,脚位、波特率设置、安装中断服务程序、开中断等,参考代码如下:
# A0 X) ?4 t7 F& ]
, Q) \ B* l% b2 a- [- f% i- void uart_init(void); v& l y, |. q. V& Z9 H, ]
- {2 J# X4 o! f5 Q" H5 z) g" k
- USART_InitTypeDef USART_InitStructure;
) g1 ~6 }0 ~8 Y) B) H: t' e2 p - NVIC_InitTypeDef NVIC_InitStructure;# V; h1 K R+ h" H
- GPIO_InitTypeDef GPIO_InitStructure;0 Z# h$ K- Q# l* t
- 7 v* `) G( k$ a
- /* Enable GPIO clock */+ w% q. w5 @* G' R; R. k
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
: T: J1 Z/ A+ A% k -
/ V& L( y' a1 A( K% F6 F/ \, G - /* Enable USART clock */5 E. f/ S8 @9 j0 ]6 M7 n, X- g% S
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
) I& h5 U; n. ]( a, P" a u -
. R. O; @: q7 L! Z; ]- { - /* Connect USART pins to AF7 */+ ?2 ~' g, M7 a, u8 g* ]
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);5 w3 R* F1 L: d* A2 e7 W/ {5 w
- GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
: f J7 B# G4 h - - x0 {( w" |2 t) Z* ^% X- u0 E/ W
- /* Configure USART Tx and Rx as alternate function push-pull */
* y/ ^* H7 z/ o2 z- W) y - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
) f# f% W- p& B1 [5 `; g ? - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
6 q. X4 U# {& t8 C$ Z( U - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
, r( u1 J9 q2 K* v, D - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
" r! g: O+ p4 i/ E$ | - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
' k& {6 w* v: \' ]/ O* V1 m A - GPIO_Init(GPIOC, &GPIO_InitStructure);- [! X( A# x- z+ R+ g: b
-
) n# y* v6 O# o+ f+ t: T - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
) o J; r5 \+ f/ Q - GPIO_Init(GPIOC, &GPIO_InitStructure);0 J9 z+ I1 e+ A- Y
- /* USARTx configuration ----------------------------------------------------*/& U8 S3 }6 {, @9 J' j! I1 a! ~
- /* USARTx configured as follow:% d8 l# f4 d. J* {, A: n/ W
- - BaudRate = 3750000 baud
( d! m! h- ?4 @ - - Maximum BaudRate that can be achieved when using the Oversampling by 8
9 U, m* \. Y0 R& Y( I - is: (USART APB Clock / 8)
9 r3 @8 s+ j6 m- ? - Example:
9 B/ c! }6 F5 Y, c, F7 k - - (USART3 APB1 Clock / 8) = (30 MHz / 8) = 3750000 baud/ z6 K, ^. I' q. L. Q( E
- - (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000 baud' x* Q6 [) h3 Y7 R6 s4 Q+ |3 E
- - Maximum BaudRate that can be achieved when using the Oversampling by 16
0 u% C9 D V/ ]/ ~7 Y - is: (USART APB Clock / 16)
4 m% ]! z; E% J. a# a - Example: (USART3 APB1 Clock / 16) = (30 MHz / 16) = 1875000 baud0 e/ i. E- S0 p2 y; r% S9 [
- Example: (USART1 APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud7 F }0 d/ @& `0 d9 U
- - Word Length = 8 Bits9 `4 g" @- g* j- ]+ B
- - one Stop Bit0 T+ ?9 y9 e# L0 N7 [/ J
- - No parity
# u, t7 \% b; y9 ]5 e - - Hardware flow control disabled (RTS and CTS signals)% w3 S0 D7 o6 ]! P" ?; w! P5 G5 W
- - Receive and transmit enabled
" u9 m" G2 L E o P( V7 j - */
2 e# p5 [! H& K - USART_InitStructure.USART_BaudRate = 115200;* Y; n' m* f2 s# n
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;, x- e$ p7 G$ \. [- k
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
) l% E$ B0 n: m. u, m - USART_InitStructure.USART_Parity = USART_Parity_No;0 ?# P% V# ]4 T" @, q
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;9 W+ j8 W6 }7 G# ?7 z+ f
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;' |! D' f4 a! p5 R
- USART_Init(USART3, &USART_InitStructure);
1 }/ _1 B' O7 d: t: l' k - + i( X- ^* K8 y& D# Q: W
- /* NVIC configuration */$ Z$ Q* e% I& z6 K
- /* Configure the Priority Group to 2 bits */9 \+ N3 e' Y4 Z4 Y" t3 q! Q2 q$ g+ a
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);. v0 }8 r" \! K
- ; ?! ?) f1 h/ Y; v. `4 ~, j$ ~$ C/ j
- /* Enable the USARTx Interrupt */
! U( k }& m, P - NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
% ~" K% q8 _: R - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;% b, h A; u5 Q' ?: U% _
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;8 r! L/ ?6 @9 U( U/ G
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;* X$ f( c% Z5 b& T. e
- NVIC_Init(&NVIC_InitStructure);3 Y0 m. i4 X# ]* E: I" _
-
5 l! e# F% g3 o9 d! A9 D K6 f- U - /* Enable USART */3 m/ a7 t$ b( R6 _1 g# ?7 w
- USART_Cmd(USART3, ENABLE);
) O+ C$ q: [ s- p8 e - USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);5 G1 w; @- X% K/ t
- }+ N8 k& P8 |/ A" c2 }
复制代码 * w7 w4 O' x2 ?0 B. A# V& w
中断服务程序如下:5 g0 F- e. ^( F8 G% Q
- void USART3_IRQHandler(void), v6 ^2 b/ Z7 }
- { @9 j# p. Z4 G: r' B
- unsigned char ch;
1 }; r2 O. ~* w! N$ o0 T$ c* E; H - if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
' y+ x6 `. k8 s& V" S6 Y9 L - {7 y9 ]4 ? ]- H% P8 P
- /* Read one byte from the receive data register */
) I) c) b V. k, k& r; R0 r - ch = (USART_ReceiveData(USART3));
3 z# o5 ^) i2 m' V! s
3 a+ s {; ? e# Z& \7 A; H: O- printf("in[%c].\r\n",ch);. f7 O: o1 D5 F/ t/ }' |: N: ~
- }
. s' Z9 r) r& R( q _1 o - }
复制代码 9 s, R& X' S( l6 c" j3 X) A
5 U& Z% ?% l7 s. E9 ^5 }2 q0 x
直接把接收到的字符打印出来。
! E1 E; Y& V+ o2 V# U- ~+ R- Y- ?- V
(2)DMA方式9 G- Z- } O. `
基本步骤同中断方式,额外需要DMA的初始化配置,参考代码如下:& F* Q* \9 S$ o E$ W" i9 v2 r5 R' j
- void uart_init(void)
3 ?& z F: X! e- H; S" o - {
& L/ w( O1 c/ x+ L6 v - USART_InitTypeDef USART_InitStructure; C9 x' p( W, R8 ^% y
- NVIC_InitTypeDef NVIC_InitStructure;1 h0 Q% G+ j4 g+ l& A- i
- GPIO_InitTypeDef GPIO_InitStructure;9 H# H; m/ z, s; W5 i% _" ?+ x2 B
- DMA_InitTypeDef DMA_InitStruct;& n' ^2 D5 ^9 m; q1 s6 a. e! o& l
-
- B, s! V- z! m4 G! D* I - /* Enable GPIO clock */
2 `/ S1 U: }+ J; i. x/ o - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
B& I. ^" V/ r; i3 \8 [ -
, n& \, |2 }! p: L7 ^8 k, ~* J - /* Enable USART clock */+ e1 k! K. N% O* A4 Z
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
S0 L9 `1 B9 A# q8 C8 o - 1 o& i ^: W2 S( f9 |$ m
- /* Connect USART pins to AF7 */
V' p. w% s$ D/ C4 Y - GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
, |) u* u! y$ |1 h! ]$ C% m0 ? - GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
5 R* f5 T6 b/ y; H -
& `/ w; ~" w' i: k) u: ? - /* Configure USART Tx and Rx as alternate function push-pull */$ N4 v+ L2 ]% R& j' S
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
6 I E. r+ A! F/ U; { - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;8 X+ f9 |! V: P3 D% ?7 |- r% D
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
) g$ z! X0 t7 J1 Q( h - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;5 p4 a- A4 x9 l( B1 y& `
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;' e( V7 N% k( f( a9 c
- GPIO_Init(GPIOC, &GPIO_InitStructure);1 C* D& l' ]5 b7 J" `$ V1 }5 m# a' X
-
, J. Z; U- X( m! _) E - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
m6 z' C8 H% g: I: p. Y# ` - GPIO_Init(GPIOC, &GPIO_InitStructure);
, c/ b2 P$ X* F1 C: T - /* USARTx configuration ----------------------------------------------------*/
6 r5 v: n" H1 ]7 f0 K# Z* G0 z - /* USARTx configured as follow:; \4 q) L, T5 d- s) x
- - BaudRate = 3750000 baud
1 p8 T! P( U" G, T - - Maximum BaudRate that can be achieved when using the Oversampling by 8# o+ z1 L# F, I; v9 w$ H4 r5 X+ X
- is: (USART APB Clock / 8)
5 h2 `" A. y8 K( T4 [ - Example:
- Z& d; `! u, I, y - - (USART3 APB1 Clock / 8) = (30 MHz / 8) = 3750000 baud
0 J" d9 y/ p; f; H8 y - - (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000 baud
1 N: q7 D4 j+ B1 n" }$ f - - Maximum BaudRate that can be achieved when using the Oversampling by 167 e- D) C8 N- P. I% T
- is: (USART APB Clock / 16)
# T; W; f7 F; ^' \! b! n - Example: (USART3 APB1 Clock / 16) = (30 MHz / 16) = 1875000 baud
: H$ s) F# L# G. P) n8 U - Example: (USART1 APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud
6 h7 A" S! q. T4 c% l - - Word Length = 8 Bits
% v8 G$ v* E- W1 ~6 z' b - - one Stop Bit
7 d4 s3 e/ d% d7 p' l - - No parity
' i% p. W& [6 C9 S: _9 M - - Hardware flow control disabled (RTS and CTS signals)$ B- Q5 Z9 b3 C2 X
- - Receive and transmit enabled2 D& i0 _: a8 s$ h* ^+ g
- */
. u( ]7 @8 `' t/ ^1 ` - USART_InitStructure.USART_BaudRate = 115200;
3 D$ ]& U0 b3 [ i+ r' a) y - USART_InitStructure.USART_WordLength = USART_WordLength_8b;. R$ V8 s1 W; O, O' G% m, G, _
- USART_InitStructure.USART_StopBits = USART_StopBits_1;/ t. \% L+ r' N: X6 q
- USART_InitStructure.USART_Parity = USART_Parity_No;
3 v t) J2 E* Z2 z - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
) i) @' W5 G* `9 `" t% s" p - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
C) {- t' D) z2 N5 Y - USART_Init(USART3, &USART_InitStructure);
: k7 z+ v, Z: U) B9 B
" m# l; {% n% t5 q! w- /* DMA_Configuration */% h. g' g1 [0 U% h1 w
- DMA_DeInit(DMA1_Stream1); 5 S0 j+ i3 h' _
- 4 Q8 G7 Q# y, O
- DMA_InitStruct.DMA_Channel = DMA_Channel_4; * x8 }- [6 [0 @' [1 F7 K( S0 @
- DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&USART3->DR; //source buf
$ F. B- j. R2 M - DMA_InitStruct.DMA_Memory0BaseAddr = (u8)pdata; //target buf; K1 _) s5 P! z j( {
- 8 C0 P5 M: Y4 _! C4 q1 v8 \5 O. E n2 b
- DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;2 H2 \' f6 x' h4 n: |
- DMA_InitStruct.DMA_BufferSize = lenght; //BuffSize;& M# N" P% Q% C, _
- DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- m# K5 J. o$ w4 e! S | - DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
/ t0 r: M; K. w0 D6 z& C - DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
# r" y P2 p5 w5 n - DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
2 D, h; l" G! C0 V0 A l* X% F7 G - DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //DMA_Mode_Normal; / L& l6 `! b! G5 S
- DMA_InitStruct.DMA_Priority = DMA_Priority_High;
! k- ]3 {* _$ M2 @8 ~/ E/ V - DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
# M, w5 L+ _# Y5 R' t9 V2 [ - DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;8 [* p) }0 a4 P+ B( k
- DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;7 K7 [7 X- _" L: O# D
- DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;/ \6 W1 R& P, C* ?! u. p. O/ q
- DMA_Init(DMA1_Stream1, &DMA_InitStruct);' E' f" j4 o/ O' Y0 e0 c3 a
% @) Q0 {4 B* E j3 [- /* NVIC configuration */" I6 G* m. ~ L* K
- /* Configure the Priority Group to 2 bits */
9 I' k' }/ N* v3 J4 M: O: Q - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
& a% l) w, O, n% E, S5 | - + W# u; c- x5 J( S
- /* Enable the USARTx Interrupt */. L. c+ k! V* j2 V/ e4 A9 x
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn; 3 b/ v! v. i% O2 S
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
! B6 g% {) M; C - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
% M' s3 X3 ]9 x# \/ N8 ` - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
; R& i' c" c) \( e/ L4 ] - NVIC_Init(&NVIC_InitStructure);
2 W0 k! b$ I+ D0 a# D
/ T; l6 p9 j$ T- /* Open DMA interrupt*/
" n) O; ^. S) P" d9 Y& D - DMA_ITConfig(DMA1_Stream1, DMA_IT_TC, ENABLE);
4 u; {! C0 m" d' R( Z a - DMA_Cmd(DMA1_Stream1, ENABLE);1 E5 }% v+ D9 a8 D: `# S# @
- USART_Cmd(USART3, ENABLE);- G1 J8 v% k4 E9 W+ |4 Y
- USART_DMACmd(USART3,USART_DMAReq_Rx,ENABLE);2 y+ Z8 d/ U! v$ ]$ O9 O
- }
复制代码 : D$ k8 o: B' a8 Y- r; I
* A L( E3 [ g9 w3 g
DMA中断服务程序如下:
4 J; W9 B1 K# z6 q( Y( w/ j R$ [1 l- void DMA1_Stream1_IRQHandler(void) //UART3_RX9 e6 t6 C7 o7 w' ~; Z1 r
- {( n+ Z5 i1 F" o, ]1 g. j2 X
- static short i;+ h: M+ S; b+ E
- 0 p* q0 y$ p& O8 I
- //When a Transfer Complete
6 b9 i6 M( }0 e0 \+ H5 ^: C# i F - if(SET == DMA_GetITStatus(DMA1_Stream1, DMA_IT_TCIF1))) Q* }, z5 P+ V- [4 ~! Y
- {
; f4 ~+ z. x" {0 S3 |: i - DMA_ClearITPendingBit(DMA1_Stream1, DMA_IT_TCIF1);
+ [5 r: K" r3 ? - i++;: r2 x. l2 U* w& `% R8 a$ ?
- }3 U' i9 p3 M. k3 t# o
- }
复制代码 4 \% b. I" a: j. f: |1 G2 z
; o* X1 `1 E- A, {上面程序只配了DMA接收,发送类似。
7 I; X: ^+ F L) F! p$ {/ V; u3 x$ Z7 e1 c8 ^! `
% N, Q0 ~* f* Z' w, ~
三、实现DMX512协议
* _# n3 j% w1 z# A6 c! \DMX512 协议是美国剧场技术协会( United States Institute for Theater Technology, USITT) 制定的数字多路复用协议, 其制定的初衷是为了使舞台、剧场等地所使用的众多的调光器和控制器能相互兼容。虽然它不是一个行业或国家标准, 但是由于它的简单性和实用性, 自从出台以来, 得到了世界各地生产商和使用者普遍承认,这个协议在LED控制方面应用很广泛,利用STM32 USART可以高速传输的特性,我们很容易用STM32来实现DMX512协议。
% O# }8 s1 Z1 I0 q4 u(1)数据的格式及传输
- c2 O. H( D$ C! S h0 TDMX512 协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX 协议要求数据传输的波特率为250kb/s, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的“Break”信号, 接收器接收到“Break”信号就准备接受随后而来的数据帧; 紧接着“Break”信号之后是不短于8us 的高电平信号M. a. b ( Mark after Break) ; 之后就是数据帧。在DMX512 协议中, M. a. b 之后的第一帧数据被称
% E6 V9 m, K; U6 e: j: m) ?- W为“Star-t code”, 在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值, 以传递特殊消息。“Star-t code”标明其后面的数据是8 位控制信号数据帧。数据帧之间可以有时间间隔, 也可以没有; 同样, 数据包之间可以有时间间隔, 也可以没有。DMX512 协议规定“Break”信号、M. a. b 信号的最短时间, 并规定“Break”信号、M. a. b 信号、
" L. O3 x/ g0 A9 X数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。为了严格实现DMX512 数据的时序要求,“Break”和M. a. b信号我们可以用定时器来实现。3 `; h( Y4 n3 I' x8 i7 o6 `- J8 v
具体的UART配置如下:# }0 o+ F b3 W; ~: z, J1 K
- USART_InitStructure.USART_BaudRate = 250000;
% W" f! }4 I! L& b - USART_InitStructure.USART_WordLength = USART_WordLength_8b;/ ~8 X7 o& M) V8 Z
- USART_InitStructure.USART_StopBits = USART_StopBits_2;
0 v& }8 r# e5 t/ l - USART_InitStructure.USART_Parity = USART_Parity_No;' h) t5 u# w I
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
5 `. z9 t9 E7 ^( ~: L4 x% W - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
% D! r; ~6 Q' r& k I( } - USART_Init(USART1, &USART_InitStructure);
复制代码 5 C3 ~$ Q0 K4 r. R- }' A) Z% k1 s
' S( {( p& b6 L* ?1 U
( D- }" y. g; D9 T$ C, y' x8 p发送DMX512信号过程如下,先把UART的TX脚配置为普通的GPIO并输出低电平,然后启动定时器计时88us, 时器到后把TX脚置为高电平并计时8us, 时器到了后在配为UART模式用DMA方式把数据发出。
O5 Q5 N4 v- R! x8 a/ r0 u7 TDMX512信号的接收是个难点,一般直接配为UART接收就行,不需要在UART模式和GPIO模式间切换,但需要在接收过程中检查接收到“Break”信号时的状态是有帧错误出现,并且接收数据全为零,这样的话可以确认已经收到“Break”信号,随后数据正常DMA接收就行了。
" `7 j. O$ g! G
! z8 T$ L+ W0 [8 V" l# s8 E |
1. 使用已经调试好的例程,特别是参考官方例程包。% u- d; N9 A5 q+ y5 m# l4 s
2. 使用KEIL的RTE配置串口,很好用。
3. 使用CubeMX配置串口,也很好用。