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

STM32基础设计---查询串口通信

[复制链接]
STMCU小助手 发布时间:2023-1-5 21:11
首先总结全文,通过查询方式运用USART1口收发数据的主要步骤如下:
* q) F% r: x4 o$ n1 u' Z; Y4 a$ J9 k1.初始化GPIO口
/ X4 ^( \8 N' d: n2.初始化串口, `) T2 ?6 L7 s; e
3.编写发送数据函数
0 [$ Q. b9 x& H# ^4.编写主函数! m; D. S1 Q% Y; t
下面介绍详细步骤:
9 e5 h" l3 S0 F! h2 ]* F/ l9 o* W8 f+ Z- A; T7 `
1.初始化GPIO口
) W, Z, j8 t5 u! Y- U( x  I! ?3 S+ }通过查阅STM32数据手册可知,stm32f103c8 ,USART1的输入、输出引脚,分别为GPIOA端口的 Pin_10,Pin_9引脚,所以先定义GPIO结构体并赋值:
" E2 y% l) i, o( @6 k3 X! h9 G7 ]
  1. void IO_Init()
    + b( _: G* ~  x" Y. i
  2. {: @' F% C( Q! e
  3.         GPIO_InitTypeDef Uart_A;
    9 |% M& f  v$ H8 b2 k
  4.        
    : v6 D& S7 H, G+ A$ t0 f
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    ; ?* U) Q+ N8 g& ~: _# ~- I/ V( k
  6.         Uart_A.GPIO_Pin = GPIO_Pin_9;! a6 ^- s; G  c
  7.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    - b- P9 J! Q9 P7 X6 c5 K
  8.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
    / A' ^( [/ A5 N1 j  T5 n
  9.         GPIO_Init(GPIOA,&Uart_A);
    5 K) P3 I' w$ p
  10.        
    0 r$ F- G) a! R0 c$ c' l
  11.         Uart_A.GPIO_Pin = GPIO_Pin_10;
    , E3 M0 P; L' w- U
  12.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    & w) M1 Y3 v$ D' Y
  13.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //stm32 data sheet page 110
    8 x6 v) K. z" \2 W( {, R+ m; j' w
  14.         GPIO_Init(GPIOA,&Uart_A);
    8 D; }- c* m2 y
  15. - n# G' U* z3 x, b, _
  16. }
复制代码
7 D+ u" G' o& I$ p9 L  E
还和以前一样,先定义GPIO结构体变量,在使能GPIO外设时钟,紧接着分别对各个引脚的寄存器赋值并初始化。5 r. ~8 M5 ~$ h
. M8 L9 [2 p& ~* Y6 ^$ t
这里需要注意引脚模式的选择:根据STM32参考手册,在全双工模式下,输出口的引脚(Pin_9)要配置为推挽复用输出,接收口的引脚(Pin_10)要配置为浮空输入或带上拉输入,刚开始学STM32不需要过深了解,只需要知道引脚要配置为相应模式即可。如想深究请查看STM32参考手册110页。
5 a7 B: @/ G6 F6 B# P9 k
8 O3 D9 M+ j! K+ f* t2 R
2,初始化串口
3 N% s: b; |4 p! B/ ?( i要初始化串口可以利用库函数中的串口结构体 USART_InitTypeDef,这样对于初学者来说方便易懂。
6 w  ^& Q' t4 M" }" [/ C. S# G, u% `, q2 {. L
库函数中的结构体 USART_InitTypeDef为:
/ \6 X# [7 W6 O! H& e2 u1 m* e+ z, U  Y" k- u- Y
  1. typedef struct5 P9 b: W7 D+ K3 M  h, P
  2. {//波特率
    , y6 Y; ?' U1 d$ M$ @, D
  3.   uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
    , r, G7 T7 |- `* B& j9 s  b
  4.                                            The baud rate is computed using the following formula:( x4 l, w) G4 L
  5.                                             - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
    2 @. w( K, L" Q& a1 _7 u
  6.                                             - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
    $ A# V+ y) Q" d
  7. //字长9 @4 t6 O$ b. _7 c: p2 Q
  8.   uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
    4 @3 B* h) T3 b) ?7 K
  9.                                            This parameter can be a value of @ref USART_Word_Length */5 e! q% a$ r- d" r; @& k8 |# o
  10. //停止位
    ' ~! R8 n! O- {2 u+ G2 }9 c
  11.   uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.  C& J% y* Q: u  }  A: H2 P
  12.                                            This parameter can be a value of @ref USART_Stop_Bits */
    / I! E- k7 ?( r1 q- \+ {
  13. //是否奇偶校验
    3 [8 q# {  ~/ C8 ?% B5 W
  14.   uint16_t USART_Parity;              /*!< Specifies the parity mode.
    ( y6 b0 ?  @5 r- w' I% E! |
  15.                                            This parameter can be a value of @ref USART_Parity
    % I+ k) _+ E, ~0 i
  16.                                            @note When parity is enabled, the computed parity is inserted
    9 p3 D( k* z+ o9 w" e* [
  17.                                                  at the MSB position of the transmitted data (9th bit when* g8 `# x" b. F3 V! S, R" b
  18.                                                  the word length is set to 9 data bits; 8th bit when the
    3 U! I2 H) u$ A" d+ x2 C
  19.                                                  word length is set to 8 data bits). */
    4 U4 d" l2 y  n
  20. //串口模式,收or发?8 g% M3 X. @1 n# S: l1 F+ O. _, T/ m
  21.   uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.3 Y6 P. |: F- P
  22.                                            This parameter can be a value of @ref USART_Mode */
    $ I0 U$ J: [1 A. B8 b1 f
  23. //是否使能硬件流,这个初学者暂时先放放,还用不到(博主现在是初学者)7 f) I' \' O) ^. p8 \: j
  24.   uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
    - n. e" Q- ?2 l5 f" c: I, d
  25.                                            or disabled.
    2 A# X# ^4 K, Y, u+ e2 M3 l
  26.                                            This parameter can be a value of @ref USART_Hardware_Flow_Control */% U1 L2 S5 a2 ^  K
  27. } USART_InitTypeDef;
复制代码
$ f0 O' I( s1 |) P* t2 J
知道了结构体,便可轻松理解下面的定义了。
) \1 m8 ~" h1 w7 k3 e3 n! {" I& B9 I( O
  1. USART_InitTypeDef Uart;
复制代码
+ x6 G/ u  z6 n4 |4 ~
2 U4 n# h. P# h/ w/ h* y3 \
使能串口时钟后,依次对结构体中的变量赋值(注:STM32的每个外设都有其单独的时钟,只有使能了其时钟,外设才能开始工作)详细代码如下:5 M+ }3 N/ S$ o: C' `% R
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
      o( q0 Q# r5 }( [% h8 ^5 z* w( J4 a
  2. Uart.USART_BaudRate = 115200;//波特率115200, B5 [0 ^9 H: t2 l# T; G  `8 g- e4 @1 t
  3. Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流失能
      L0 G  Q, f% T, A
  4. Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置为 输出和输入模式1 {$ h7 K! M' K9 E0 ^
  5. Uart.USART_Parity = USART_Parity_No;//不进行奇偶校验
    : {5 u7 ~, A9 t! T9 {
  6. Uart.USART_StopBits = USART_StopBits_1;//1个停止位3 E, q' T% `: f
  7. Uart.USART_WordLength = USART_WordLength_8b;//单次数据长读为8- P6 U; J2 p* k
  8. USART_Init(USART1,&Uart);//初始化串口
复制代码

2 `, F3 S6 ~" i# v8 V3 {在初始化串口后,按照STM32参考手册还需要对usart使能见下图:
# C" p7 a0 k' R/ ^& F, f/ B$ E) O& l) }/ Y, M1 B
20180319234442899.png - z$ ~0 M- e/ x' L: T; h

. B5 C8 v+ U# v  o(注:博主当时在这里想到一个问题:STM32有多个串口,但是只有这一个串口使能位,也就是这么多串口公用一个使能位,那么,当使用多个串口工作,如果临时需要关闭一个串口,怎么办?答案见文章最下部分,答案1。)& |2 y. x3 Y: o. a

/ _# D, H# O- F, L( b. N由上图可知,在初始化串口完毕后,还需要使能串口:7 ~# ~/ o  t' U$ U8 z9 l
, C  {/ M! u+ J( n9 M$ W
  1. USART_Cmd(USART1,ENABLE);
复制代码

2 K! Q2 J( s9 R# _6 T, ?1 D& H/ d6 `+ l

5 @% w  ?1 e& f" S; U3 k# f然后根据参考手册:- U) @& g- r  v

# I; v& ]' }" z% U3 f4 Y9 E
20180319234937352.png ; X  q9 B5 W& O! e4 N
' c& C  R" E, H" `( R/ Y) e+ O. \
2018031923501878.png 7 B& R/ T- s8 }/ G" y
1 a2 _8 ~7 W. I+ x

# z$ M' T5 w9 F; |" F8 Z此时还需要先清除状态寄存器USART_SR的发送完成(TC)位,要不然发送数据的第一个字节显示不出来。代码如下:& c5 @( S9 ~1 }/ R' {/ S; }
4 z1 g, U$ `( |5 W% U
  1. SART_ClearFlag(USART1,USART_FLAG_TC);
复制代码

) r8 Z6 H6 ~" j! w4 L$ P9 Z到此,串口的初始化也就完成了。) w. x! W; ^; S, Y
( Q2 Q' Q7 l8 r; j& a5 U
3,编写发送函数
& g& l4 ?# |, c# ^- S& I$ i  U4 i此处比较简单,先说代码:
& U1 A$ s+ {, i/ E5 N5 J
  1. void sendByte(uchar character)) {, N( e0 o7 `  \4 |' @' j, M
  2. {
    * X3 C9 d2 Y7 E" u$ ~
  3.         USART1->DR = character;' i$ ]  l: [5 g: \5 d2 K
  4.         while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
    . V! J$ b0 P2 R5 c& g
  5. }
复制代码
+ b7 R" H9 {  G  L+ K/ q
需要发送时,直接把数据赋值给USART1的数据寄存器(USART_DR),即可通过串口发出,接下来需要等待数据发送完毕,当数据发送完毕后,USART的状态寄存器的发送寄存器空(TXE)位会置1,(RESET在库函数的宏定义为 0),即,若数据未发送完成,那么循环会一直空转,直到数据全部转到移位寄存器。+ @2 t! N% w. f8 v* S9 i+ L6 s6 r# T9 k
6 f' J5 x6 h$ d; t: k4 k9 @8 Y
4.编写主函数
3 C5 ?) ?  [; [本文是通过运用查询方法来实现串口的发送。通过串口向电脑发送一个字符,串口之后会自动向电脑发送已发送字符的后9个。
: k$ M' c4 U+ P# o+ Z  k/ X6 n1 h( v8 `2 U4 L$ d6 Y$ q
先粘贴代码在解释:/ v. C: D1 z# a$ z9 o
, P  H9 W, k5 {2 e0 Z9 E0 t
  1. int main()3 f2 `) w- J2 k& C8 c+ N! S
  2. {
    1 |9 B  t! q  o& [, y; w- j) L
  3.         int count= -1;
    % q4 R0 ^: p6 y* K
  4.         char temp= '0';
    + o. W5 s: a( b# @- i5 n0 m
  5.         IO_Init();
    ! S2 J' f/ S# D* e4 D
  6.         Usart1_Init();
      j1 b" l, ?" {# i4 \; y! N+ S  i, X
  7.         while(1){
      F2 B! [$ U0 d
  8.                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//判断是否接受到数据9 u. R/ @" v3 J5 \1 I" E
  9.                 {
    8 \( Z5 ~. h% q) P  S8 w* ^# V
  10.                         temp = USART1->DR;//若接收到数据,则将数据从数据寄存器取出7 y$ {$ E, Y4 b; t
  11.                         count = 10;0 T4 b$ d  T+ b/ W& f  @- i) V
  12.                 }       
    5 I* y3 b! c4 R! U- N
  13.                 if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))//判断能否发送数据. {" \' m; N8 [: i) {3 G
  14.                 {% c: m  E: G  Z. q- x9 e
  15.                         while(count >0){- `# k6 a% ^$ ^+ b
  16.                             sendByte(temp++);//若能发送数据,则向接收端发送数据
    # ?7 N7 w- Q' b
  17.                             count--;//连着发送10个字符1 R; a# g$ G5 s
  18.                             delay(1000);延时一秒: D& x2 J" s8 X$ G$ B! L9 A
  19.                         }. T2 i; L* s7 p& w/ ?$ q6 m4 g
  20.                         if(count<0){
    ) p9 G( {5 y5 C- b4 z9 ~6 W% [$ D! o( U
  21.                                 sendByte('\r');//博主本来想在电脑接收端输出回车换行,但是一直接收不了,还没弄明白。
    7 a& ?& M% x% q. Y" T+ w- s8 D
  22.                         }( l& @5 {; k  g3 `4 D
  23.                 }
    9 @. b5 l0 O5 g/ v+ g# t
  24.         }
    1 T% e  o- }  C" E% I! G
  25. }
复制代码

/ |/ q4 q/ h5 z, ~( `  f解释见代码中的注释。3 K; p  `5 g, ?! T: W; m( S
$ O# W% G( S3 }& @' b
答案1:当不需要使用多个串口中的一个时,直接将对应串口外设的时钟失能就可以了。
3 t' J8 R) T0 k% I! f& a; k7 ^
5 Z/ d6 j+ m& h
通过查询方式实现串口收发数据完结。2018年3月20日/ G& b  D7 K7 L/ k9 [
  b5 Q) j5 H! ]% U
下一篇,通过中断来使用串口。
8 @# X- ~* I- B. D
( H% v6 ?) f+ e+ C7 z( l) }
见STM32基础设计(3)---中断串口通信
: i% g- [9 ^# U6 B5 v/ z' o- z  w/ r- N; t6 w. f
本文的完整代码如下:
: o: k: G, T6 \$ T, |
  1. #include<stm32f10x.h>
    ' X( X) R$ K  ?: H, L
  2. #define uint unsigned int
    6 U9 p; P) W! R6 S
  3. #define uchar unsigned char) U8 Q7 U& a/ U$ y0 y
  4. void delay(uint n)* Q5 ^. s% T% Y8 S5 e* R2 ?
  5. {" a' z- U+ p% d
  6.         int i,j;
    , {  ^$ [0 D7 P2 l% k; _8 K  D, l
  7.         for(i=0;i<n;i++)
    - K' W) X$ c# ~0 w
  8.         for(j=0;j<8500;j++);
    % T$ U0 E* W# W) t0 [. c$ ^
  9. }9 D8 c' O. |9 v: H  V
  10. 1 ], m6 W+ c! `
  11. void IO_Init()
    5 I' z/ U1 k4 j4 Z
  12. {
    + }9 X& [! h4 L$ Z, V
  13.         GPIO_InitTypeDef Uart_A;
    & f4 c6 ^- c/ M5 m. B; o1 ]
  14.        
    5 k5 E4 z4 k8 L9 @
  15.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);0 }! U6 \. e/ Y9 z4 a" T
  16.         Uart_A.GPIO_Pin = GPIO_Pin_9;0 L* Q7 g2 Q1 e; ~
  17.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    - Q7 H! H; m/ L8 {; P. L  _
  18.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;/ L9 f9 n# I0 ^/ _
  19.         GPIO_Init(GPIOA,&Uart_A);
    / o8 S8 F: V+ {0 f* |- ~
  20.         / [  I/ I; _6 ^
  21.         Uart_A.GPIO_Pin = GPIO_Pin_10;: A. S0 T( [9 `! H3 u
  22.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    ( N* d! ~* [! p
  23.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
    6 I( R; l( d- @% G+ K
  24.         GPIO_Init(GPIOA,&Uart_A);5 ~2 T3 `$ U) B5 y5 F! c9 f0 X+ K

  25. 2 I9 [1 ]$ _3 f9 e4 h0 X2 c- C+ K
  26. }
    4 W: \; H/ b9 d# Y, C6 m& X
  27. void Usart1_Init()7 M- x+ ^$ f( t0 u* g- Q
  28. {# Y: i5 x. y1 s2 \; P
  29.         USART_InitTypeDef Uart;5 K8 p  T! j. W6 ^6 S* i  `3 K
  30.        
    2 M% P  ~5 l6 s& n
  31.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);2 @/ E1 t$ R4 t: u- X: {2 L4 Y
  32.         Uart.USART_BaudRate = 115200;
    ! w# u5 w; W* A  e8 ^: a7 h
  33.         Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;. z  s; }7 U8 T
  34.         Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;) G5 C8 ?+ b6 m( t! j# o4 I
  35.         Uart.USART_Parity = USART_Parity_No;
    6 h$ ]0 v4 N! M9 ~! T
  36.         Uart.USART_StopBits = USART_StopBits_1;3 J+ i' ~# T9 N& g2 U) k) c2 g
  37.         Uart.USART_WordLength = USART_WordLength_8b;9 Z% ]) a: }+ c5 u  ^7 w2 L* Z
  38.         USART_Init(USART1,&Uart);
    # F( {* s  M. C1 h$ x
  39.         " s8 r  J* q& ^- W' e. ~$ u
  40.         USART_Cmd(USART1,ENABLE);
    - N- }# U% t% n0 r9 t; T
  41.         USART_ClearFlag(USART1,USART_FLAG_TC); //page 540: u4 I* [8 W: h. q, H$ f0 n
  42. }
    / K2 c# J) L3 E2 h

  43. ; g, _: ]4 {5 G/ d
  44. void sendByte(uchar character)
    ' T4 {/ I0 v) ?7 E% A
  45. {
    ) Z: o3 U$ O: e, g# A6 `- ]1 B
  46.         USART1->DR = character;
    * x% }, s* @  L! f1 Z, P
  47.         while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);* L2 M( b6 @" A' k9 l! D
  48. }
    $ O. {4 g( c' I# R8 s' }
  49. 1 ~, h5 r. F) Q
  50. int main()+ o& E( A9 E3 Z# J: P- O
  51. {
    6 m2 k# S. A7 D- ~+ ~
  52.         int count= -1;
    2 C( r6 x1 u% Z& {: M0 Y
  53.         char temp= '0';
    5 v/ O; E/ @( [% l3 O
  54.         IO_Init();/ I& X& H3 z5 f, p
  55.         Usart1_Init();) \& v$ f+ i- O! R6 ^6 ?
  56.         while(1){8 O& G9 U# V( Q0 ^) l1 y
  57.                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
    2 x7 p( u& F  y) @$ q
  58.                 {
    4 O! J7 W- ]  C0 C1 D) e
  59.                         temp = USART1->DR;7 Q4 A( ^' v: g0 |. N5 \
  60.                         count = 10;  S/ U; w6 W% J% p, q: q# I7 V
  61.                 }        & l' g5 Q( i1 U! d( E  N
  62.                 if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))4 `5 L+ I. V8 ~% _# h6 @( C- e
  63.                 {* ^+ H) i8 R. f& b) A" m$ Z
  64.                         while(count >0){
    " q( g9 k1 e- |$ P! v1 `
  65.                             sendByte(temp++);
    ( C% i6 z& P3 ^; |
  66.                             count--;' X3 k( W' p" u8 \- z* W
  67.                             delay(1000);
      ^5 w3 F0 B7 u; x, l6 W( k
  68.                         }( J4 A2 I  K' S3 |$ G7 j( b
  69.                         if(count<0){
    ; r" o( g4 K! U4 @1 a
  70.                             sendByte('\r');                                           8 X9 Y/ ?& m; u, k4 @4 ?6 C) s. V
  71.                         }
    & y8 I8 z. E, O1 }2 s0 ]9 t
  72.                 }
    1 b; W: r- K  F2 G
  73.         }
    5 E4 b# d% i4 ?0 h3 c* [, x" v
  74. }
复制代码
) i' {# t: E/ b0 ^& G0 t
————————————————' x! t. d* B1 t  I: s; r  H5 I
版权声明:家安
: k/ [& q' m. w- N( G+ p9 b, j+ R; U6 u! q1 ]" ^; {. x
3 o4 Y. T) L7 O  c& [3 \2 Q
赞 收藏 评论0 发布时间:2023-1-5 21:11

举报

0个回答

所属标签

相似技术帖

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