你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 串口详解

[复制链接]
STMCU小助手 发布时间:2022-4-17 21:05
01、USART的特点
0 G' l# N- P. t* [: N3 p; Q/ rUSART是通用异步收发传输器(UniversalAsynchronousReceiver/Transmitter),通常称作UART,是一种异步收发传输器,是设备间进行异步通信的关键模块。UART负责处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式;通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用两根信号线(Rx和Tx)就可以完成通信过程,因此也称为异步串行通信。
! X# [2 c. N7 B8 X$ ~( h7 T% V  s5 ^+ x! E  q# n. V# e
全双工异步通信。
4 `9 }$ @3 m8 e' H6 G$ ~6 @  B  T
# f# z- X$ N4 }" Z8 X, \8 C* O小数波特率发生器系统,提供精确的波特率。+ f* M, r3 j6 h+ u9 V- r( J5 s
( i  k- `  q) T
可配置的16倍过采样或8倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能。/ A2 x! v* Q9 p7 X7 X( q

# s4 E. Y: o. X8 n) @可编程的数据字长度(8位或者9位);
( j6 {/ v( d+ t! d+ B4 W7 U" T3 f2 y) `
可配置的停止位(支持1或者2位停止位);# a! J2 A5 J; f1 g' r* B7 f

" Z6 l0 m1 k+ @- c. ]2 U6 g可配置的使用DMA多缓冲器通信。8 H* a9 T6 |9 F( e

! }0 x% E- I0 z0 `# h2 e. N单独的发送器和接收器使能位。
# {" f# y! U2 V4 B5 A$ A9 v; ?) t' `9 W* Q/ X8 K' L
检测标志:① 接受缓冲器  ②发送缓冲器空 ③传输结束标志0 Q, n6 y/ `& F& g; i9 @6 t- x+ i

. W) w  H3 o' P- r' Z  i5 T多个带标志的中断源。触发中断。
: E& `6 w7 L* o" `; ?7 C8 j" ]# R4 |2 m! l& c$ ^
其他:校验控制,四个错误检测标志。
( L. \. d# p3 e8 |( k& |( |$ C8 N/ o: [
通信结构% l# ^/ @& V# N9 j  m- h
  }- N5 k% i0 n/ ]; E
64da5001ea7f81a28083c1cd86bb944c.png
5 Q% q9 w% O1 v- F* ^; m2 H- d& e: l4 b! E2 l' [8 ?( }/ J% N; W% K
02、USART简介' ~4 n6 a2 @, n% u" i; C  D
2.1、数据传输模型; ^4 e0 P. ~) q5 j( _; Z4 c! W

6 R" b2 }# u, ]3 ]6 s0 w( n! M
1977cd0bcc091b8c312ea4a33b863b5c.png
1 k3 u4 ~$ V# ^( w8 z0 y
! ^. k2 {8 M9 E2.2、帧结构
  m( I6 M- e. W7 V
串口异步通信需要定义的参数
3 x. U  m- ?3 L
& e8 ~- g0 E& I" j/ E4 X  O% R. R① 起始位3 ?7 U! @4 z; C/ X/ G" `
1 j0 W8 B: U4 \, u
② 数据位(8位或者9位)
0 t. b8 E9 S4 M8 D4 \4 a/ k3 k  ]6 l  t
③ 奇偶校验位(第9位)
) O7 u9 g  ]! U
6 ?' l1 ?8 ~* h4 r) f+ m④ 停止位(1,15,2位)1 w9 N  b" B: \/ {  g1 @8 Z
0 Q2 s$ Q9 @1 n
⑤ 波特率设置
* n- ~3 j" l  _# h) k6 P" H
& p. l1 r1 M' o8 z; s% y带奇偶校验的数据为就是9位
( a1 |8 m3 h1 S
9 c- j0 X2 U' F4 `  E; G eb6f9d3c3694e60fb484985396bd61dd.png " T: T+ o7 g3 ]1 Q0 c1 e

  l' F( b9 ]3 m# c) K( L1.数据包
5 D+ t9 Z. Z& P0 ]% L) c
0 ?' N4 r; A+ W/ c串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。
% A; X2 t1 ?$ W% ~6 D; t
% l3 X* r. C) h: ]. z; ^: G9 q2.波特率  O5 b! k. {# \4 {$ y
4 \* T3 N+ c# l: v' n' q( |
由于异步通信中没有时钟信号,所以接收双方要约定好波特率,即每秒传输的码元个数,以便对信号进行解码,常见的波特率有4800、9600、115200等。STM32中波特率的设置通过串口初始化结构体来实现。' T4 A6 u" b  g' b9 M: H. |
) ~, v2 P4 q% \
3.起始和停止信号/ l/ [- G' ^0 a0 B
) n  e# y0 D; E! ]6 i1 N' |
数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。STM32中起始和停止信号的设置也是通过串口初始化结构体来实现。
, C( }% Y, z# L5 m: B% i9 m7 w# j* `6 w
4.有效数据
+ E9 e9 e+ V. ]0 {& s$ \9 \3 r: a+ z4 F/ I+ a5 r7 t
有效数据规定了主题数据的长度,一般为8或9位,其在STM32中也是通过串口初始化结构体来实现的。, H4 q; k. i2 T, a% V
# G, m- m5 A) b& N/ }" n
5.数据校验3 \7 w0 t4 K# Z

2 @) {! c- \/ ]: U在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0 校验(space)、1 校验(mark)以及无(noparity)。这些也都可以在串口初始化结构体中实现的。. ?6 _6 [, H1 b7 c: c
0 X0 ?5 i9 U2 n) _+ L- k
2.3、波特率
9 K2 C  f: E4 M6 V) p$ p/ f5 n
! n/ K$ ]% L! z0 \4 ]: v
3e627d64bae5a7b44019ad5fdf9505e7.png
7 }+ c2 u0 |$ v+ t8 S! y* c# V3 Z3 w! S9 ?  b. T. e, y
OVER8,用于配置过采样,通常情况下,OVER8设置为0。
* d( v- d! s! z2 N
1 y  x* a5 k) S- Z0 u 7843ff80095b38cd6e63233c463f3a09.png
/ l9 D& \6 m7 o6 Z; Y2 P% V
" W5 k' N0 b4 ~  t/ f& i如果时钟时84M
6 R, A8 X* l) h& b2 ]2 V9 X/ b/ s( L- V% u
USARTDIV = 84000000/(115200*16) = 45.572
3 ]$ s& `8 F& R9 _( `
% `1 v& J/ i+ W那么得到:
( @0 C  U4 l, X. {: N
5 m. V" \& E7 W1 ~0 O" G* B* r' ?DIV_Fraction = 16*0.572 = 0x09;
* i, L, s0 C, E5 `% \5 ]" R- `
1 h' M) S/ D2 d8 pDIV_Mantissa = 45 = 0x2D;. t" ^5 v  `  [
0 [3 B) ~2 t6 M- P7 S4 J( v( f: n
03、STM32的USART: r; ?& n, ^3 F; l9 N8 R
根据STM32F207数据手册,STM32F207一共6个串口
: T5 ^$ z& a* n+ H$ h7 K0 g' A
" C* D7 K4 B/ y: i. ]2 [ 00d99484cbe8d677c01519eaf62e9e10.png : _8 V& I5 Z* h3 N( i! E9 u
9 z/ x, w5 Q, N
下文我们以USART1为例讲解
( Z/ C- a2 X4 D$ I! e5 H$ u1 }' A) Z0 l$ ]" o
从STM32F207数据手册的Table10. Alternate functionmapping图中看到USART1的对应管脚,下文我们选择PA9和PA10作为USART1的管脚。
% u# r+ L2 ^7 ]3 N7 e, a4 l) i; f
$ G1 f8 I/ E9 ?$ _6 p* m5 c* F. t 9d5255e81468bc957360deec15d92bd9.png
: ?9 A7 U: r% E( m! H: A" p3 j& ^  V: }) M3 g
04、代码配置
, g$ q# ?, l" i配置中断优先级。
% Y8 Q, T9 I/ \% [. Q- e9 n6 b9 W
( O! v  K) t- a0 Q) q3 A
  1.   /* Enable the USARTx Interrupt */
    0 g1 y6 J+ s0 K2 K
  2.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    * D. X/ C; e% l* v* h: e9 k5 x' @# E8 t
  3.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;; A2 b9 m  v$ o$ r# Z- ?  o$ m
  4.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    ! A! P; c) A3 V8 t* Y( o2 N
  5.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    : i' v/ u% h! `# K
  6.   NVIC_Init(&NVIC_InitStructure);
复制代码

5 r4 Z4 q# M$ h) T, ?打开串口与相应的GPIO引脚,配置好相应串口信息与GPIO引脚的工作模式。; B5 S' O: F$ s1 P! T

" E9 ^7 t+ y/ y) t  v
  1.   /* Enable GPIO clock */
    2 j% a6 ^2 D5 w2 u
  2.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);3 {; ~8 ^7 n! a4 f4 m4 ]
  3.   /* Enable UART1 clock */, J3 O) y) ]1 ?. H* y
  4.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    ' H% W* g* G" J/ Z9 u& V, s
  5.   /* Connect PXx to USARTx_Tx*// x; F5 |3 c4 [+ d" b
  6.   GPIO_PinAFConfig(GPIOA, 9, GPIO_AF_USART1);
    1 B- G7 X- ~* u7 C- v: [

  7. 6 H. J' u. E7 m7 p$ w* e' u
  8.   /* Connect PXx to USARTx_Rx*/& g; l2 _2 F& X' h+ k1 F& d
  9.   GPIO_PinAFConfig(GPIOA, 10, GPIO_AF_USART1);
    % n2 l( e# O; k$ E- T# c
  10. 1 z) i# w8 t2 a# }
  11.   /* Configure USART Tx as alternate function  */
    0 L& _$ N1 D* C: x: K8 Y
  12.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;% ?# [: P( u, N' |& L) W6 f
  13.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    " ]7 l, ~: Y% `* C% s2 b
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    ! f4 B5 n, \0 f3 ~0 L- X- \$ W6 E# K

  15. 3 n. J. m- i2 l" \- E+ m* y; ~  g
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;* n; j/ U4 d# x8 z6 P5 a
  17.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' ^) }8 h  u: P: q
  18.   GPIO_Init(GPIOA, &GPIO_InitStructure);2 R0 x  o0 R  Y9 ?! Y2 }4 ]

  19. & w: a8 n9 d4 g: `& k
  20.   /* Configure USART Rx as alternate function  */( n" Z, g! F+ j2 C" e
  21.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;# R9 ~0 U6 G; C" q0 y+ d  R" ]
  22.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;9 h1 P# E) M$ ]  m+ a& {
  23.   GPIO_Init(GPIOA, &GPIO_InitStructure);
复制代码

) W" ?* ?; M$ M配置USART1。
7 q. i0 t9 U, e8 j2 S+ \7 H
  1. * y& \4 S8 [! H7 N
  2.   USART_InitStructure.USART_BaudRate = 115200;//配置波特率
    : \7 B0 n; \( t8 j
  3.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;//配置数据字长( t3 J5 F* Y! g* I  O. h
  4.   USART_InitStructure.USART_StopBits = USART_StopBits_1;//配置停止位# K. N6 b6 T0 N/ }
  5.   USART_InitStructure.USART_Parity = USART_Parity_No;//配置校验位' H/ Y. }+ {) C; }! n; X* A- _
  6.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//配置硬件流控制: i6 Y2 a6 e: R. L4 M/ F% I
  7.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//配置工作模式,收发一起9 m* M0 \+ H+ @; Q; Q6 S
  8. 8 w2 G0 h5 n; r9 J* Y2 j0 H7 o, h
  9.   /* USART configuration */
    6 O  |" ~2 |; W- z8 @2 T  Q. E/ b- ?
  10.   USART_Init(USART1, &USART_InitStructure);// 完成串口的初始化配置. \# x' Z* X  Z& M, J1 Q0 G
  11. 使能中断配置。
    2 Y& ]+ c6 e% w- O* b

  12. 4 Y% s8 f1 N; J, p7 x3 `/ E# g: k
  13.   USART_ITConfig(USART1, USART_IT_TC, ENABLE);
    ( c' n8 F' L# x( y
  14.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)
    4 Y$ g7 q" b$ c( }2 B/ Y
  15. 我们配置了发送传输完成中断和接收数据寄存器非空中断。我们可以配置很多类型中断,在ST提供的标准库函数中看到。
    * c* a) A8 }+ P2 M2 D

  16. ) ^* O; ?& I' K* u  [
  17. /**4 T- S8 T: l2 g3 }7 g
  18.   * @brief  Enables or disables the specified USART interrupts.
    0 }7 ]- _( C( g8 k
  19.   * @param  USARTx: where x can be 1, 2, 3, 4, 5 or 6 to select the USART or / V( q# R8 f) \! h! q) [$ S8 r; ]
  20.   *         UART peripheral.
    * Y* a' ~, h8 v1 Q. o+ A3 ?$ G# U: _3 {
  21.   * @param  USART_IT: specifies the USART interrupt sources to be enabled or disabled.
    ' V7 z3 U/ n; D0 J% r& Y/ a
  22.   *          This parameter can be one of the following values:& h0 }" w# w3 _. i& Q; b% D
  23.   *            @arg USART_IT_CTS:  CTS change interrupt
    6 W! A" q2 d( [: O  N5 a# T% s
  24.   *            @arg USART_IT_LBD:  LIN Break detection interrupt
    2 H; V1 V) y. U3 v& l" R/ |/ J
  25.   *            @arg USART_IT_TXE:  Transmit Data Register empty interrupt" s% x) t$ E, r$ j" S2 G+ X
  26.   *            @arg USART_IT_TC:   Transmission complete interrupt* ]/ W& Q# N: z3 S0 }, N
  27.   *            @arg USART_IT_RXNE: Receive Data register not empty interrupt; _' \7 ]) B5 f& T+ _) c& S
  28.   *            @arg USART_IT_IDLE: Idle line detection interrupt3 h9 e! z. s% Z0 k4 _
  29.   *            @arg USART_IT_PE:   Parity Error interrupt
    ) p5 r1 q& P5 b# k0 c; b
  30.   *            @arg USART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)7 W) F  o. k# X1 m: S$ U
  31.   * @param  NewState: new state of the specified USARTx interrupts.; A* I, S! ~! x! z6 @4 e
  32.   *          This parameter can be: ENABLE or DISABLE.
    # v; H: C& z/ ~" p/ f. r
  33.   * @retval None2 t3 r' m) M- O. q& d+ }% i
  34.   */
复制代码

5 f8 P0 i, d6 P, e/ `最后使能串口。
  1.   /* Enable USART */
    ; c3 [& l; A" E: j% H
  2.   USART_Cmd(USART1, ENABLE);
复制代码
% c! t0 y3 h: F0 t
main主函数,功能是LCD显示串口接收的10个字符(如果不是ascii码则不显示),串口倒序返回接收到的10个字节。
' V8 p1 g* ]" \4 u: {, ]1 m- m3 L
  1. int main(void)
    9 N$ z$ L. L' ?& D# P1 B2 _' n
  2. {; s' `2 n( j" _1 M/ [
  3. /*省略初始化部分代码*/
    / u8 _1 ^4 H+ Y2 L# ?; `
  4.   while (1)' _4 w" H/ F1 @& v- c
  5.   {
    ; i, y. C; ^& Z- S
  6.     if(LCD_refresh_flg){
    9 J4 T4 R' o- Y( U' p
  7.       LCD_refresh_flg = 0;8 q. X+ V( Q' v1 [1 V2 v0 \
  8.       LCD_ShowString(0,16,receive_data);2 B+ z4 |/ L6 G$ H1 K
  9.       receive_num--;
    4 C& y/ a2 i: F; D
  10.       USART_SendData(USART1, receive_data[receive_num--]);
    & D$ K8 F9 a  v7 L
  11.       send_flg = 1;
    , Y* Z9 U( x3 ^9 V7 p
  12.     }
    % \+ Q) O# ?5 v. k3 |2 g5 V- z7 q# r
  13.   }5 q$ g6 o; A$ p. K) c
  14. }
复制代码
( e# c% y  e6 b9 ~3 g
因为使能了中断,我们还需要编写中断函数。% M' \; ~; J% r* S* C: p
/ i3 V6 R' C- J) M# Q) \) f
  1. void USART1_IRQHandler(void); C  W/ K" M. g7 E& R" H
  2. {' Q$ w& N7 y0 n' @. }
  3.   if(USART_GetFlagStatus(USART1, USART_FLAG_TC))
    $ ^' n5 ~+ X2 V. ]' S; N- u6 i  M, N
  4.   {5 K2 ^* F2 |8 J. {) o/ e
  5.     if(send_flg == 1){* a2 ?: Z4 m9 I" X, }9 b! \% ~
  6.       if(receive_num==0){+ U4 Q$ O$ D" m, `
  7.         USART_SendData(USART1, receive_data[receive_num]);
    % b8 v& d# r7 ]2 ?
  8.         send_flg = 0;& z( z0 i* X% n3 e8 a  j
  9.         receive_flg = 1;
    , ^2 t. t; F- b3 w, g, m
  10.       }else{
    % V) D0 e3 x! z+ h6 y
  11.         USART_SendData(USART1, receive_data[receive_num--]);
    % s2 ^# U9 q1 X, h
  12.       }$ S1 e7 _+ [9 |! t/ {
  13.     }, H6 {4 S" N8 Z, I  A/ _# q
  14.     USART_ClearFlag(USART1, USART_FLAG_TC);
    + k: s% [  W+ Z
  15.   }- ?3 z$ m+ O6 @5 T- b( X
  16.   if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
    7 C! e) V, _4 V$ {" Y9 w% u  [$ W
  17.   {
    1 [( }9 N1 M- ?( w; t# ~
  18.     if((receive_flg)&&(send_flg == 0)){
    " k" ?( s) L! p
  19.       receive_data[receive_num++] = USART_ReceiveData(USART1);7 s2 A9 J) e% T1 c
  20.       if(receive_num==10){
    . r6 a$ p0 G2 h; ^
  21.         receive_flg = 0;
    3 H0 q" R- F% q3 i2 H$ [$ B+ y' z# `, K
  22.         LCD_refresh_flg = 1;
    5 n# j9 B' U2 d" ?- r& y- w
  23.       }
    ! s( O/ H  n/ i- B" J
  24.     }, X  N$ p4 ^1 P! }& M0 u
  25.     USART_ClearFlag(USART1, USART_FLAG_RXNE);
    . ?) \$ v9 e. @, J
  26.   }
    - w" c& [! U5 k7 o) u
  27. }
复制代码
& S! L% W5 e5 G7 T5 J; w# ]

0 I' Z+ k$ t: ^0 l; \& A8 O下载验证
: Y( q- ?) J. V
, m0 D0 \- r9 G9 K1 E# d$ ^5 mLCD显示屏可以显示接收的10个字符,且PC以100ms为间隔发送数据,发送977包收到977包回复,测试demo就够健壮,没有出现丢包。
% g7 X7 [+ _+ N. E+ f" ^3 M
5 t: I' Y8 W) s) {  A0 S7 B dfae4faec397eb4df0fbe9e952cc35dc.png , X* D( D1 @( P
, R, U) X# {# L, L7 a' N

6 X3 |9 k* N: D5 c$ G  _4 h" p- E3 L

. _. H2 J5 s( k2 B1 b
赞 收藏 评论0 发布时间:2022-4-17 21:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版