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

STM32F103之UART上位机通信

[复制链接]
flyingstar 发布时间:2025-8-14 18:09
一、USART简介' |* b6 Y) }! k$ ^6 u0 Y
1.1 UART 简介" ]5 `+ p: ^, L" d0 e
通用同步异步收发器(USART:Universal Synchronous/Asynchronous Receiver/Transmitter)( E( N: _' K! F! q5 m+ I  u
特点:串行、全双工、同步/异步通信(USART可支持同步通信,UART只支持异步通信)
; H1 {6 `" I  n. y9 r2 @" X4 E- J& o. F. e
& B  G2 F- E4 \5 |- D$ B! }发送和接收共用的可编程波特率5 J& \3 R$ [  c
可编程数据字长度(8位或9位)(常用8位)" m; D' Y/ e! h) k9 t8 X
可配置的停止位-支持1或2个停止位(常用1位停止位)
/ J% s, G  z: p' {% T可配置奇偶校验位(一般不用)  Y& h4 @' l" Y5 }2 D8 Y
6 P2 n3 V' x6 V
1.2 物理拓补图
) E8 J4 z& V" f2 y% ~接口通过三个引脚与其他设备连接在一起。任何USART双向通信至少需要两个脚
1 m# Y1 Q0 }& |2 I  L& `# Q+ eRX:接收数据输入: l& d% W4 u4 d* H+ V4 |4 Z
TX:发送数据输出
$ ^9 c) P- P, c# u! M7 z4 BGND:双方要共地,双方通过USART进行通信,两个设备必须要共地,因为逻辑1---3.3V电压(对于地的电压),如果两个设备不共地则对地电压的高电平(3.3V就可能不太一样)。共地的意义是让两个设备的通信电平对地电压相等8 Y3 v. Q( K4 k1 ?/ n7 v
5 o1 d) C, ?2 ]6 U  z6 o0 K
143313vbrrl0ybxaap3skz.png.thumb.jpg 3 s" h. R& u, V2 k  l

. u: s( W: P5 Y* e  r' A1.3 数据帧格式7 H% h+ b8 R2 h% P: w' {
一帧数据=1bit起始位[低电平]+8bit数据位+1bit奇偶校验位[可以不用]+1bit停止位[高电平]6 {& e7 C* e/ C) E

% e$ ~$ u% t, `9 P4 x' Y& \USART总线空闲,即没有数据发生,TX线为高电平# I" ]8 d# }) ]7 }% }; B5 n

' p6 F- A8 k6 W3 K<1>数据位:USART发送的1次数据量是1Byte=8bit;[5、6、7、8]
9 V% s9 F0 W# T# W: o, A, C<2>数据字:数据位+奇偶校验位;如果不用校验位,数据字=数据位=8bit;如果使用校验位,数据字=数据位+校验位=9bit. O2 r  V! K3 v% ?* ~# Z" Y
                    奇校验:数据位中的1的个数+校验位中的1的个数为奇数
- p9 J$ W$ C% c$ T, i+ c' q$ H2 B5 f                    偶校验:数据位中的1的个数+校验位中的1的个数为偶数
% }" \3 ^) y, p  ~<3>停止位:可以被配置为1bit(默认);2个停止位(可用于常规USART模式、单线模式以及调制解调器模式);0.5个停止位:在智能卡模式下接收数据时使用;1.5个停止位:在智能卡模式下发送和接收数据时使用2 h7 Y5 Z9 |( r+ G
<4>发送顺序:先发送低位,再发送高位
, f9 y, C% R& s! T+ y' i
& |( Q: N: U! k5 U1.4 框图- D/ v& }9 b& N! H4 F* x

& t0 F: O: G) z7 O7 i# E" q 143305ex594sdg0xa59ahj.png.thumb.jpg
9 f$ O- h6 S/ L9 r
7 f8 g( r  m( B对于这个框图,最关键的是两个标志位TXE(发送为空标志位),RXNE(接收不为空标志位)' _8 L* M* Y) F9 O% L# `
数据通过RX端口进入MCU的UART的接收移位寄存器,随后进入接收数据寄存器(RDR),进入后RXNE被置1,表明可以读5 I9 |0 A6 e4 q8 F
MCU通过数据总线获得数据,数据再到发送数据寄存器(TDR),若TXE=1,说明数据已经被转移到移位寄存器,表明可以发送5 C  W/ c! B3 u. y7 |$ b

0 f9 [; [2 c: a% v# \; U二、串口通信
- [& _! d! I, h& }  f* u  _% o2 U( \配置UART
6 D; D  G7 c2 W2 T# @" ~; q* X4 P# g6 s8 Q! V4 X7 a3 o
开启了接收中断和空闲中断6 A) t3 H- _0 k1 m5 p0 ]1 B7 y+ S
4 R7 S+ }; Y3 Y+ y$ q) u
/****************************" W" k2 Y4 C5 Y
*@brief    uasrt1端口配置函数, F! {7 u' I' L* d9 ^3 G- D
*@param     void
& u# u, b" {  l*@return    void! d. B+ I: ?' {4 J9 L6 W. s
*@NOTE      PA10->RX PA9->TX' I' k( k5 i' I6 |
            PA10,PA9位于APB2上0 y  D0 p  A5 _: v% k0 O
*@time     2025-6-3& ^/ X3 l7 v" c+ ?7 {
******************************/' s$ q$ _5 n1 q: Q# B0 q: R
void usart1_Init(uint32_t Baud_Rate)' N. `4 e  t; W- B
{0 H: ]9 {* ?7 `4 L$ |# l1 W
        //1.打开引脚时钟PA
* `* Z2 o' {+ H        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE)      ;1 L* ]/ V+ ]: b, g. G: J
       8 S8 @' _1 N( b3 T' D
        //2.打开usart1时钟
  @+ W! C7 ]; c3 x9 x( y. O        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)    ;/ _( f  F) K# @
      
8 a% X8 B( k) a$ P+ E. C        //PA9->TX推挽复用输出2 h+ P8 g9 R8 S$ a" j- ^, F6 P6 ?8 z! X/ q
        GPIO_InitTypeDef GPIO_InitStruct_TX                      ;+ ?3 b4 r: }+ R
        GPIO_InitStruct_TX.GPIO_Mode  = GPIO_Mode_AF_PP          ;' y8 w# D% X; h5 D
        GPIO_InitStruct_TX.GPIO_Pin   = GPIO_Pin_9               ;
: C. p9 t8 ^1 ]# [  Q8 ~" i3 s        GPIO_InitStruct_TX.GPIO_Speed = GPIO_Speed_10MHz         ;7 d: `8 J4 d8 u+ L* }& Y
        GPIO_Init(GPIOA,&GPIO_InitStruct_TX)        ;
/ P# |8 b6 n) t/ V: v. Q      
, J% M# V2 d% H2 d$ u       2 }9 n& _" Y/ F: [8 t) t1 _
        //3.配置,PA10->RX浮空输入; S  q; e) V7 ^! B6 i% k( R
        GPIO_InitTypeDef GPIO_InitStruct_RX                      ;
6 [- P0 E% g: X. ?; ?4 h4 ~        GPIO_InitStruct_RX.GPIO_Mode  = GPIO_Mode_IN_FLOATING    ;
7 {: l7 `: T, T0 s; B" s        GPIO_InitStruct_RX.GPIO_Pin   = GPIO_Pin_10              ;+ Y5 r/ [1 q, F" N/ j
        GPIO_Init(GPIOA,&GPIO_InitStruct_RX)        ;0 X  ]8 @! |# l$ Y. Z
      
5 O, g6 ~3 x' ]        //4.配置usart1,! f. f; a( W3 w4 R) w" C
        USART_InitTypeDef USART_InitStruct                                           ;
% T3 h- {" m9 n        USART_InitStruct.USART_Mode                = USART_Mode_Rx|USART_Mode_Tx     ;: @4 n5 T' N9 `* D
        USART_InitStruct.USART_Parity              = USART_Parity_No                 ;
- T) n/ ?6 P8 s        USART_InitStruct.USART_StopBits            = USART_StopBits_1                ;; }! e5 o4 ?" x
        USART_InitStruct.USART_BaudRate            = Baud_Rate                       ;      
% G, I/ X* @3 ]9 T, |/ q2 b% j' U. z        USART_InitStruct.USART_WordLength          = USART_WordLength_8b             ;
0 S$ m' e+ q4 o, b+ k* r        USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None  ;
6 s* Z7 U7 Z! L% U2 U% R        USART_Init(USART1,&USART_InitStruct)                                         ;5 l6 y" M8 p0 A& P6 Y6 s. k
8 E; D. B" B1 T. k9 `3 J
                  / ?6 l+ E2 j6 N$ M
                  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE)                     ;//开启接收中断 RXNEIE=1: L6 U* Q8 k- u) y2 W. C
                        USART_ITConfig(USART1,USART_IT_IDLE,ENABLE)                     ;//开启空闲中断 IDLE=1
0 Q+ J1 p; Y1 |3 k                  //初始化NVIC5 l* i% o+ y1 G6 W( A% \" T! V! c
                  NVIC_InitTypeDef  NVIC_InitStruct                               ;' i, M, d) v- u9 H: E4 J5 i; x
                  NVIC_InitStruct.NVIC_IRQChannel                   = USART1_IRQn ;//中断通道
! T& ?5 g0 g+ K+ K/ L3 |0 k& Z                  NVIC_InitStruct.NVIC_IRQChannelCmd                = ENABLE      ;//中断使能* v$ C, j2 h8 k
                  NVIC_InitStruct.NVIC_IRQChannelSubPriority        = 2           ;//响应先级: g* \% S# q5 G. s6 A
              NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2           ;//抢占优先级: m& q$ w' D2 k
              NVIC_Init(&NVIC_InitStruct)                                     ;
, ?6 @1 j; T* E9 q7 H. C      
2 v0 D: S. ~2 h8 D& F        //5.使能usart18 N3 U7 b$ Y* K3 P# Q3 U9 P
        USART_Cmd(USART1,ENABLE)                                                     ;
/ d( W( P( d' Y}  ) n. m% j/ M7 A$ @- B3 z1 G

2 y- l5 h5 M) k( w8 a. q
9 Q/ _# [1 v2 ?% R5 t接收发送函数
9 a5 G' o; U# h6 U+ {( V3 l' B: m+ N) X2 V- p
/****************************
+ J, s. G6 x/ a5 l9 Q. _1 S*@brief     发送字符函数
# N; `4 q8 U! ^, e3 Y. k% X% K*@param    void
# ^0 i, V) ]% m, P) L- s, m*@return   void" B% R6 }0 q, i& a6 K( B
*@note     MCU会将数据发送到DR寄存器中的TDR寄存器中,: O, k& U1 ^# `& h
当TXE==1时,TDR寄存器会将数据加载到移位寄存器中,可以发送
4 a0 A3 J% s0 l4 Z; P/ I*@time    2025-6-3
" G1 J; J5 b+ A' ]8 n******************************/3 ~; b# F/ D( w$ x
void usart1_sendbyte(uint8_t str)
1 p6 g, ~. j6 D  l1 ^+ C$ w& z+ B{
2 ^0 `9 f0 m5 A+ u2 j        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==0);
( e; {& p6 d' I" t/ I        USART_SendData(USART1,str);, ~' {( ]. P7 [9 V; L# e
}2 Y! t% i% O0 c/ z
5 y9 P/ N* }1 ]2 ~% i7 D
/****************************; \+ V+ [( w! U- {1 R/ m/ z
*@brief     发送字符串函数" O8 S2 W, k! F  J
*@param   uint8_t *str
2 c5 ~( P2 t& B: q: [1 v1 B( |*@return  uint16_t len) d- u- B% J) ]; l( ?  A
*@note    发送字符串本质上就是发送字符
$ K9 V! C& V: p! D6 j' m* T& g: U*@time    2025-6-3. o( `8 E- i( g0 j7 T! [
******************************/% R9 F1 f  Z( H4 U' ^
void usart1_sendstr(char *str,int len)$ O: {; H+ v7 K' ~- ^8 v% t& r
{, f4 u+ ~) d1 o9 L. l, I
        while(len)* t; R7 ?* x5 v$ W2 Q
   {
6 T& ^- B* Q( Y  Q" R" }( g2 A                 usart1_sendbyte(*str++);
5 ]; |  g) C( M                 len--;
+ [( l9 ?  E' E& V: F         }* U+ U/ J4 ]2 h2 V, I7 d4 ~# a
}
: o4 c0 Z" B8 R2 J$ d
: I) z. e: C" s' e; v% x* W1 D1 j/****************************
+ u& _+ O1 ]! l% N  d*@brief    接收字符
$ J( k# U# F: Q" z9 M* a3 v2 U*@param    void
) {+ z, n  p, @, F+ o# g  }+ e*@return   void
1 K( H) ], m/ r. }" k4 w" [*@note    MCU接收到数据后先放在DR寄存器的接收移位寄存器
. J* `+ x# K4 N% Z$ U          数据会到RDR寄存器中,当RXNE==1时,说明RDR有数据,可以读
2 t  X: s) N/ Z*@time     2025-6-3) F' F$ C3 V2 w
******************************/
0 x1 r7 z6 W% e! e/ ~uint16_t usart1_receivebyte()
4 g$ w3 f; V2 m{; D% J% u+ Q( N& r! i# K, l: R! J
        while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==0);
4 I1 z3 A( p2 X/ c, m        return  USART_ReceiveData(USART1);! u1 k4 u1 B8 E' j0 h$ K: t4 F9 f1 E' k8 s
}
4 ?3 _9 ~$ X3 Q) e# B# f9 l8 S' ]/****************************
5 x) v: p0 h6 Z4 ?. B*@brief    接收字符串函数(idle标志位)4 G) B2 ]2 b3 r# A1 V
*@param  void7 W3 e( f3 R, D' g/ o6 w
*@return   void
/ X+ y! U; T- @1 c4 l/ f& J*@note     void% X; F$ t1 |/ Q/ M" x
*@time    2025-6-3# @1 D1 E3 O5 h3 C
******************************/
! k3 V! @2 c  U* d+ b% bvoid usart1_receivestr(char*buff)4 e8 k5 V# W) i) C9 a  n3 Y
{0 z) i6 {! H. G
        uint8_t flag;
+ k3 n7 l! Q! M4 m) L        while(1). J' t' R1 H! J- h: q4 E
   {8 F3 w: n( E4 X9 `
                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==1)6 }/ x  |  Q  x+ Y1 w: {
       {
* f  }) N2 m6 P! P& B* o                                 *buff=USART_ReceiveData(USART1);& C8 C2 p0 K$ x3 w, N5 t+ n/ H( w
                                 buff++;/ n6 c. F- p5 f3 j
                                 flag=1;
- q4 H/ H- I. _; m. H; Z6 Y                         }/ I2 E% t6 H. V- ^: p8 x9 e9 R
                        if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==1&&flag); X! y5 m" c3 ^2 q, c4 L3 k6 z% }* I# @
       {
& s1 Q1 `( ]4 F- `4 X) ^, L                                 *buff='\0'; //当发送时 发送结束标志
) F1 X7 t" e$ Q" d* G! O                                 //先读SR,再读DR将置IDLE位置0
6 z/ w2 d" n. x; A- r* `                                 USART1->SR;8 D. ^5 Y, m- h; u  w
                                 USART1->DR;
3 {8 k/ X) Y8 i9 s. s; v                                 break;3 K- V' _# E  \# n
                         }
' c3 j( Y9 I7 D6 X8 I4 ^- Q2 u         }: y) `& }- w/ X8 h9 g( _
}
+ h5 p# o  M& B- J+ u% V
& K7 Q2 I5 s2 S, S( M2 T# f  {/ }, v& M2 j' b
打印函数
6 {+ w+ y7 k5 X, a# z2 l$ q8 D" T/ ]  |% h6 h4 n
记得勾选微库,printf函数不涉及到中断,它是将内存中的数据输出到上位机. m7 Z* J. v2 k% x8 _2 }3 v" j3 |4 I

: C! t( G9 s1 V; v//printf()的底层借助fputc函数进行输出+ N/ O$ k2 \0 H+ p0 }. s" M
int fputc(int ch,FILE*stream)2 z* t( S5 u+ {% ^8 p
{0 i, ]* D) P/ d( u7 ^$ J
        usart1_sendbyte(ch);2 d9 z" \, }7 p
        return ch;( X2 P- U) h# v- ~; E( x  S( y
}
# @# |+ G4 K5 C7 _, g7 e. n+ o2 z+ ]9 J' b& o
9 V3 k% B% Q5 ^/ P7 R
143243jrwwvnvkww4wvrto.png & [/ P: F& h4 I, Q) u0 S" h1 U4 K  V

. A' a' {5 d0 Q/ T8 ^9 w中断函数9 [# R! T* ~8 I5 D9 p7 t
MCU接收到数据时,进入接收中断函数,将数据存到rx_buff[100]数组里;当上位机不发送数据时,说明空闲状态,进入空闲中断,将 rx_buff[100]数组里面的数据发到上位机
' A* }$ d; y! e" `
6 \1 d, u$ V. c  |& u: M; I/****************************: l2 w# O1 P4 H7 u8 S
*@brief    usart1中断实验
/ O7 G, F8 q, g- ~. s# i& N) @*@param  void7 d. L3 }( O7 |9 j0 [: A
*@return   void, R  L9 J7 t, ^+ ]
*@note     void) b, s8 j- T; r: r# X! E
*@time   2025-6-4
4 {: x7 U- A; L/ m# V******************************/7 F* M. A2 s0 j1 b  \- G
char rx_buff[1000]={0};: d0 K/ N% G5 l1 Y7 Q
char cnt=0;5 G9 d  @8 \- @
void USART1_IRQHandler(void)
0 g# S) [4 J# d, T! ]# H{$ @( H- k! p0 [3 a4 p. M
   //当RXNE=1时,有数据接收
0 V1 ]2 z" P! q8 D; P0 M        if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
0 B5 x) }2 S& M  E1 O   {+ h, d; J  H! a/ I2 ^7 m$ y( _
                 rx_buff[cnt++]=USART_ReceiveData(USART1);
8 G5 L6 ~0 n1 F# T                 USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除标志位
  k2 c) q, t: j$ C4 x, h" ]. E8 y3 d) w         }4 T( L) z' B+ H9 ~
         9 |) Q8 `  h8 V$ O5 T4 w
         //当IDLE=1时,0 _. s% R0 c- M( R
        if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)9 y2 Y7 U% o$ L+ i0 R/ M
   {
# W3 n' v& p8 D  `" w1 S                 usart1_sendstr(rx_buff,strlen(rx_buff));
4 P8 f2 R) a* _& ]4 v# P                 cnt=0;/ f" W( J, p1 g9 b& D% W* U
                 USART1->SR;
5 E! Q6 g7 E/ n                 USART1->DR;                                  //清除标志位
$ I3 q9 L' P; d& \8 B% V         }9 z1 K: H# d/ ^) t8 ^
}& i$ S) p  V& |9 ^  D+ O
) E! |: d# W: |; `1 c0 F
! c! l* Z( O1 m' _- a2 e3 u# E
————————————————6 i& H. ]4 F; ^- G
收藏 评论0 发布时间:2025-8-14 18:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版