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

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

[复制链接]
STMCU小助手 发布时间:2023-1-5 21:11
首先总结全文,通过查询方式运用USART1口收发数据的主要步骤如下:
) H  G) T3 |. n3 n( J8 O# P* y( h+ J1.初始化GPIO口( n9 `2 A* l( j3 t% w5 D# m# b
2.初始化串口7 }  z5 ], ~$ i0 m# h# s7 f
3.编写发送数据函数% R* `: Z  ?& K* L5 U
4.编写主函数" B5 Y# u( c' V
下面介绍详细步骤:
' [  C: O- D  a) W$ a- U/ x- P1 R" d, ?4 G+ v
1.初始化GPIO口
8 y/ e2 G5 T$ w$ l0 ?, S, L通过查阅STM32数据手册可知,stm32f103c8 ,USART1的输入、输出引脚,分别为GPIOA端口的 Pin_10,Pin_9引脚,所以先定义GPIO结构体并赋值:; f" ?- G! w/ W" l9 R
  1. void IO_Init()
    # Q* S  G- Y0 [6 B: X' _( [! ~3 H
  2. {: W) e& i& q7 ^' `) n; y  \6 f5 |* Q- G
  3.         GPIO_InitTypeDef Uart_A;
    ! U7 G- s! G' ^  F! e2 ]
  4.         % p$ a* u# h; a! W) E! g
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    % a4 S! }4 M+ _# p2 O/ Y
  6.         Uart_A.GPIO_Pin = GPIO_Pin_9;5 k' F: l7 J- j- Y8 C
  7.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    9 o+ a! E6 O# s& q2 c
  8.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;  _" U# l% a9 c3 c
  9.         GPIO_Init(GPIOA,&Uart_A);
    " X2 f/ u% y" F: f- _
  10.        
    5 D  X1 Y; n+ z: u* O7 i
  11.         Uart_A.GPIO_Pin = GPIO_Pin_10;* o6 t+ a" T8 h+ B* I+ U$ c# r8 D( Y
  12.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;5 z! Z9 J% q  _) ^
  13.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //stm32 data sheet page 110
    2 c1 q. P0 W% P  g
  14.         GPIO_Init(GPIOA,&Uart_A);
    7 j, Q( D. `( W; x* M. E8 R: x
  15. : }" o% C- h8 G' E- h! p4 J
  16. }
复制代码

# b! T/ F  G% J$ N5 p! K# E  }还和以前一样,先定义GPIO结构体变量,在使能GPIO外设时钟,紧接着分别对各个引脚的寄存器赋值并初始化。( s! K# l: L- e# W8 [# b
8 U7 V3 U0 m$ n( ~4 u/ O
这里需要注意引脚模式的选择:根据STM32参考手册,在全双工模式下,输出口的引脚(Pin_9)要配置为推挽复用输出,接收口的引脚(Pin_10)要配置为浮空输入或带上拉输入,刚开始学STM32不需要过深了解,只需要知道引脚要配置为相应模式即可。如想深究请查看STM32参考手册110页。7 p* ^  ?$ A! |. e
, d' V7 X+ j: K5 a
2,初始化串口
# X5 B: m8 x/ G) Y  F要初始化串口可以利用库函数中的串口结构体 USART_InitTypeDef,这样对于初学者来说方便易懂。
; z  F! ?0 f& }# M" {0 c7 Y( T/ A7 `* P  k- }
库函数中的结构体 USART_InitTypeDef为:
" |/ Y! ]1 u! t" Z, M/ b+ L+ I1 H* F! C7 C6 h
  1. typedef struct* S' T! Q. L: Y
  2. {//波特率* O' d' t1 k- [. X; m
  3.   uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.& L0 S! l0 q$ u
  4.                                            The baud rate is computed using the following formula:2 S: b2 a. q3 A' o8 y8 L9 v
  5.                                             - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))4 o& B5 N4 i: O1 Q, `' [
  6.                                             - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
    ' e' M# c. z7 [
  7. //字长+ S  x' N+ s& W0 L( Q8 t6 K
  8.   uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
    - Z0 ~* a8 T# a$ {% c8 e/ J
  9.                                            This parameter can be a value of @ref USART_Word_Length */
    9 Y7 U9 f" P! B, {- y, B7 l5 }
  10. //停止位
    5 F) @3 v) F6 a% x  c
  11.   uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.$ a  j/ L+ p1 b) N4 `+ g( C( Z
  12.                                            This parameter can be a value of @ref USART_Stop_Bits */
    5 X: h5 c9 j4 A" D- l
  13. //是否奇偶校验
    ( ?* U% z4 B3 [& y
  14.   uint16_t USART_Parity;              /*!< Specifies the parity mode.& j( C# b6 y0 S) K/ g6 r
  15.                                            This parameter can be a value of @ref USART_Parity
    ) y& T. C6 ^2 R- c' Y6 w& ^0 o0 n
  16.                                            @note When parity is enabled, the computed parity is inserted
    - g* e4 n! e" W  u0 K/ i) s" z# t8 u* c
  17.                                                  at the MSB position of the transmitted data (9th bit when; Q) o- _( o8 h0 C! e7 n
  18.                                                  the word length is set to 9 data bits; 8th bit when the
    8 b' M( I) }' }
  19.                                                  word length is set to 8 data bits). */
    8 m' j( @& f' Z: E- _
  20. //串口模式,收or发?
    % A6 {2 I; N" s* x1 Z' @
  21.   uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled." v# b; R- a/ G6 v, f6 Z
  22.                                            This parameter can be a value of @ref USART_Mode */
    % x1 L2 S8 l% S7 n! \6 t8 w
  23. //是否使能硬件流,这个初学者暂时先放放,还用不到(博主现在是初学者)
    & f1 D9 {$ H3 p# W+ N# e: Y" q
  24.   uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled8 E$ N1 O- N( H% c
  25.                                            or disabled.4 O( O3 C3 @3 x$ g! F8 h2 B
  26.                                            This parameter can be a value of @ref USART_Hardware_Flow_Control */
    4 H2 W' f; k3 e; ]) w; ]
  27. } USART_InitTypeDef;
复制代码

! f" q  Q( g$ z! b0 a9 e* f知道了结构体,便可轻松理解下面的定义了。9 }, u" l  [3 M( b9 N) K$ F. `

- {( b: q3 v" Z4 \2 u# z8 ~
  1. USART_InitTypeDef Uart;
复制代码

+ E; v, i- a, t2 Y  n5 X5 p6 u  Z+ I" ?
使能串口时钟后,依次对结构体中的变量赋值(注:STM32的每个外设都有其单独的时钟,只有使能了其时钟,外设才能开始工作)详细代码如下:
6 Z0 G0 `( Q4 }" U, j8 p% p; R; {
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);7 @2 I& F7 w+ Y7 d0 S( s$ {! L3 C
  2. Uart.USART_BaudRate = 115200;//波特率115200
    8 ~" ~) \, b6 c# _
  3. Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流失能7 E' ?# }  `# I4 D8 L. h
  4. Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置为 输出和输入模式4 J% F, ?8 \( w, A5 @
  5. Uart.USART_Parity = USART_Parity_No;//不进行奇偶校验
    # D3 ?3 m8 v1 o. ^- V) c8 r
  6. Uart.USART_StopBits = USART_StopBits_1;//1个停止位7 ~- h% _6 s! r$ B
  7. Uart.USART_WordLength = USART_WordLength_8b;//单次数据长读为8- t# Q6 F5 j! M9 w
  8. USART_Init(USART1,&Uart);//初始化串口
复制代码

' m( u; {# r' e9 T2 `在初始化串口后,按照STM32参考手册还需要对usart使能见下图:; N0 p, n0 r/ A( g* r: d
+ i+ u& ^, ]/ |/ b' S
20180319234442899.png ' i. P. }" \5 D* V/ T
" p9 K( C& o) N2 n5 |0 S! b: k
(注:博主当时在这里想到一个问题:STM32有多个串口,但是只有这一个串口使能位,也就是这么多串口公用一个使能位,那么,当使用多个串口工作,如果临时需要关闭一个串口,怎么办?答案见文章最下部分,答案1。)0 @) W9 O5 I; y: o# s

4 f1 t. g7 l  ]8 M由上图可知,在初始化串口完毕后,还需要使能串口:
6 c, |' y. N. c# Q/ t
& C" o' n* i" {6 S
  1. USART_Cmd(USART1,ENABLE);
复制代码

/ s# ?1 n- x/ X9 H4 t! o  Q( v0 g  `2 m/ }2 `* i
) N3 s1 z' \0 N$ u1 ~
然后根据参考手册:9 q9 F3 p' d0 M+ w% q, n8 }! e8 f
5 R. f* \# s( u, v
20180319234937352.png
- E* A) ?) ~2 e" `- ~5 m9 C6 R8 Y: G: `" |; N
2018031923501878.png ( @( }: ^8 l) O$ ?# K2 z- B

! C, f. _5 ]8 H& D3 @0 M, V9 b
2 @: U+ Q4 \  X6 e' W* H" }  e
此时还需要先清除状态寄存器USART_SR的发送完成(TC)位,要不然发送数据的第一个字节显示不出来。代码如下:- ?/ c- z, }- l9 @. U5 s% R/ `/ X
! W2 ?% k, C) m1 }
  1. SART_ClearFlag(USART1,USART_FLAG_TC);
复制代码

7 S* t' Z( w/ X/ }" o$ i到此,串口的初始化也就完成了。5 x1 R6 `. o; w! ?7 J7 I" ^

) L) V) }. s& m! f3,编写发送函数9 S$ }0 }% r5 ^) A2 _0 h# x
此处比较简单,先说代码:
2 S: h# R4 W( U0 G) C8 l' Y
  1. void sendByte(uchar character)% B( \+ d6 D! g
  2. {& q% G% b5 k4 s. t
  3.         USART1->DR = character;# `  x1 @  j; r$ X6 ?$ z
  4.         while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);* H- C* _& |$ q
  5. }
复制代码
2 D8 b6 M2 a/ v# v
需要发送时,直接把数据赋值给USART1的数据寄存器(USART_DR),即可通过串口发出,接下来需要等待数据发送完毕,当数据发送完毕后,USART的状态寄存器的发送寄存器空(TXE)位会置1,(RESET在库函数的宏定义为 0),即,若数据未发送完成,那么循环会一直空转,直到数据全部转到移位寄存器。8 c" s! H- a5 I
$ p. z# O& V6 r2 A5 M( M
4.编写主函数# ]) _1 G! M4 S
本文是通过运用查询方法来实现串口的发送。通过串口向电脑发送一个字符,串口之后会自动向电脑发送已发送字符的后9个。
- V8 |' ?1 J* ]/ t/ l* }4 y+ m  {" u/ Z
先粘贴代码在解释:
% k- R5 d( Z2 I4 `9 B  w  I1 k: j% |1 ]% I
  1. int main()- \5 j* ?( {5 p# a2 q
  2. {8 z+ `2 K% @; Z; S% h3 @
  3.         int count= -1;! p- b: g: _, v) ?5 {' t+ p* K
  4.         char temp= '0';0 v- b8 n4 \$ U" }. b. h# W
  5.         IO_Init();
    ( ]# M# l6 u0 ?7 F/ g' r$ `
  6.         Usart1_Init();% K9 z' P" E* P! m& C
  7.         while(1){
    3 c, j- h4 e: U' w5 Q. r, U, I7 N
  8.                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//判断是否接受到数据5 J3 F$ w8 [0 }# ]2 y
  9.                 {5 w$ _6 Y% }1 W- m1 Z: c# Q3 L* R
  10.                         temp = USART1->DR;//若接收到数据,则将数据从数据寄存器取出
    ' D/ |2 W9 M* @2 |2 ]" A' r
  11.                         count = 10;( @8 ~* k& o& m( [* r1 t9 X) q
  12.                 }       
    0 c' x! w2 w5 C8 r6 S) S
  13.                 if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))//判断能否发送数据
    & H9 s& D; d  L
  14.                 {& a* n. m( h. o+ k! M6 v6 ^
  15.                         while(count >0){$ z* ~5 t7 D- w2 _
  16.                             sendByte(temp++);//若能发送数据,则向接收端发送数据/ u* g5 x) P  k
  17.                             count--;//连着发送10个字符* z/ O) k* f, c4 b' n& Y8 |# V+ ^
  18.                             delay(1000);延时一秒3 ]/ [2 M: E7 \9 a
  19.                         }
    & q0 c9 O4 ^) q: q
  20.                         if(count<0){( n4 b( J* g5 m7 w% I/ d
  21.                                 sendByte('\r');//博主本来想在电脑接收端输出回车换行,但是一直接收不了,还没弄明白。
    7 F) N4 O: \- G" a
  22.                         }
    ; p  g4 _- B0 W; r0 @% `
  23.                 }6 Y5 m) L) @/ n2 {6 Z. b
  24.         }% w7 q; A/ V! X5 E, m7 K5 x. i
  25. }
复制代码

( y+ F/ o% [: ], g% Q解释见代码中的注释。
- n, R/ O: I. v4 i* `% ~1 ^' x1 \

1 b! N- R$ L6 F6 f* n0 n答案1:当不需要使用多个串口中的一个时,直接将对应串口外设的时钟失能就可以了。" w1 U8 O! {3 Y1 @
$ K8 G5 b/ a/ v$ Y8 W
通过查询方式实现串口收发数据完结。2018年3月20日% }4 s# ^* }! X0 @
& S- h+ I" W. u3 _
下一篇,通过中断来使用串口。' v6 e: w  C! O& d7 g  t$ B4 ~
1 X. j5 x# @7 i( `! I3 J/ q
见STM32基础设计(3)---中断串口通信
- Z7 x9 k7 A8 P8 q) E0 J& V
% L) n6 l5 p: A* U& r本文的完整代码如下:
" `" \- q) Y& C' V# S
  1. #include<stm32f10x.h>
    ) {4 h) ]4 U4 f. Q) }7 l
  2. #define uint unsigned int  v/ s, R. |7 [8 ~2 k' s( e
  3. #define uchar unsigned char
    ! n; S/ P4 z3 O$ F& X: D: a7 `
  4. void delay(uint n)3 N) _0 K6 w& Y1 \
  5. {+ x) C5 n* U+ z; q$ K- v
  6.         int i,j;
    / B4 l( [* Z# O- M3 ^4 Y
  7.         for(i=0;i<n;i++)5 Q' N) K5 \5 I. S0 h! ]4 v+ r# w
  8.         for(j=0;j<8500;j++);
    4 P! T7 d) |: }3 Y
  9. }& V2 p! y) k3 [; N

  10. 4 j3 O* F# z* s6 @5 Q0 M* z! x. z
  11. void IO_Init()
      K: l8 l) U) P+ ?
  12. {2 U% \. m! W- }; q
  13.         GPIO_InitTypeDef Uart_A;
    1 j5 X+ `- d+ L1 s: y/ Q9 L
  14.        
    8 ], o$ c7 z. ]0 \
  15.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  k# q. J6 R% O# a# k; y) H8 s
  16.         Uart_A.GPIO_Pin = GPIO_Pin_9;
    3 F0 W) E5 q) V* ~. [
  17.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    # ^; `0 I. d' C* ^9 |
  18.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
    , q8 D& g' k8 x5 N! v
  19.         GPIO_Init(GPIOA,&Uart_A);
    2 I. Q; Z( ~, N& G: Z5 W0 @
  20.        
    $ p9 |( {: C% Y. n; t$ E7 p6 @6 T% _
  21.         Uart_A.GPIO_Pin = GPIO_Pin_10;
    4 E; m) ^+ N" i* ^
  22.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
    / r' T! Q1 }4 I/ M) \$ J. M" [% ]
  23.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 1108 n0 D4 C5 @0 N) ?9 |+ u/ r. G& y
  24.         GPIO_Init(GPIOA,&Uart_A);
    / m2 R6 h3 a0 |& Q
  25. / |! E  Z( w3 Z% y
  26. }! c# j5 |- R8 e3 ?
  27. void Usart1_Init()0 s5 [; U" Q3 C5 {( p7 N
  28. {: p8 Q' Z8 c" W, e( w
  29.         USART_InitTypeDef Uart;
      }" J3 t" Y* `1 I
  30.         2 j3 n1 b9 N0 k  J, Q9 V
  31.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);8 @( A8 }! t9 _/ S. @
  32.         Uart.USART_BaudRate = 115200;4 \, j) L+ ^: m+ h( i# Q9 }, W
  33.         Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;2 f! n$ \$ K, ~2 w6 @) Q
  34.         Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    " Z0 F. h1 D+ w5 a2 o$ D# i
  35.         Uart.USART_Parity = USART_Parity_No;
    6 o! J9 s! ^* P
  36.         Uart.USART_StopBits = USART_StopBits_1;# H) E* N% @7 [" J4 ^# d
  37.         Uart.USART_WordLength = USART_WordLength_8b;
    : ~# e" @- J( h& d
  38.         USART_Init(USART1,&Uart);% E1 P6 U6 s0 I/ ]* Y
  39.        
    ; F) E- |- f( E6 l# T) T) t+ P. x
  40.         USART_Cmd(USART1,ENABLE);& L9 P" _) f/ w7 v, Z# z- \# T7 ^
  41.         USART_ClearFlag(USART1,USART_FLAG_TC); //page 540& c) d2 I1 U' B5 B
  42. }
    # Y" L0 C- D! T. U' q  w8 j- W

  43. # x# Z4 b7 w# V' x( z8 X+ i. {
  44. void sendByte(uchar character)
    3 F! R2 e% s0 H5 K+ K0 V. Z/ k
  45. {4 O/ {& k; ~# a# q* e
  46.         USART1->DR = character;
      U- ?) n8 c& O& t- i3 ?
  47.         while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
    3 B1 F/ y# J& J9 ^( f2 D7 S
  48. }
    , w6 N( b1 H# J7 y5 A; X
  49. 7 J) `9 B6 U: b) |! e9 A! i3 E
  50. int main(): S5 M$ p5 M. g) T7 D
  51. {9 x8 x5 G; k; V4 e1 {/ ^1 j* E% e% v
  52.         int count= -1;
    " t1 P. ]) G/ V/ ^
  53.         char temp= '0';6 O0 M' K$ @/ C* k5 B& r
  54.         IO_Init();* j- s+ N! i; B4 U; r
  55.         Usart1_Init();
    ! y' n' m) u7 [; o# d0 Z1 V% T
  56.         while(1){
    * ~  M  k. S. k( |7 I2 b
  57.                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
    3 v* m$ h$ X2 w& E5 i& u0 `
  58.                 {
    ; V2 \6 {' v; Q
  59.                         temp = USART1->DR;% `/ c/ I- H8 D  L+ T
  60.                         count = 10;
    # H2 P5 O1 }7 `+ t
  61.                 }        " s9 a5 F1 H8 Z$ E" o: ~
  62.                 if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))
    ; f7 \8 h& `  h2 c  w
  63.                 {
    9 ~5 n6 `- k) p! t; p: a- t7 O3 Y
  64.                         while(count >0){
    1 w9 q% i* x& T2 n- [
  65.                             sendByte(temp++);
    * z0 M' h/ ]. ^( V
  66.                             count--;6 b' ]/ G$ ~5 Y) R- Z& F* H! Q
  67.                             delay(1000);
    ! i) p' B+ }3 N! N5 R# ^
  68.                         }
    6 ~3 c- J/ b8 y  R- _* ~* q0 b
  69.                         if(count<0){* s7 M/ |- ?8 r  L$ u" T
  70.                             sendByte('\r');                                          
    7 G5 G$ @2 U5 Y! {+ b
  71.                         }
    ) }! I2 x( K9 w
  72.                 }
    / j, W0 c! [2 k+ }* @
  73.         }
    ' w8 o  h, U1 m# ]$ [
  74. }
复制代码

, c4 i5 r7 h/ r0 }  ^) l————————————————
* G0 U# c$ ^0 p' t' {2 A; d' ~6 V版权声明:家安
. o. s1 B9 M4 A* V  y' m5 R$ j" H' }$ E! t( [: N9 \0 R
3 h3 p' Q1 G7 D3 d; H; z5 t9 K6 w: v
收藏 评论0 发布时间:2023-1-5 21:11

举报

0个回答

所属标签

相似技术帖

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