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

STM32F103之UART上位机通信

[复制链接]
flyingstar 发布时间:2025-8-14 18:09
一、USART简介, f4 U, }1 W1 @$ t, x( U/ n
1.1 UART 简介, g+ _( c' o' i+ p8 k; Q/ ]
通用同步异步收发器(USART:Universal Synchronous/Asynchronous Receiver/Transmitter)9 ^/ O  j" {: Z) m5 Y
特点:串行、全双工、同步/异步通信(USART可支持同步通信,UART只支持异步通信)
) {, P! f# O9 ~* T( O# B! g/ E$ H6 B1 \- U& g
发送和接收共用的可编程波特率  i7 v9 \  G$ m9 N
可编程数据字长度(8位或9位)(常用8位)8 J: A3 v: K2 x
可配置的停止位-支持1或2个停止位(常用1位停止位)
1 k, b# o! ^+ a0 V8 ~& ]" @可配置奇偶校验位(一般不用), o5 u) ~# D' a' V* }" p

) w) A( X3 f( x/ ^6 v1.2 物理拓补图
8 d# g! s3 k/ U/ |0 O接口通过三个引脚与其他设备连接在一起。任何USART双向通信至少需要两个脚" {0 L7 W) ]4 t, |# Z
RX:接收数据输入* d6 n# D3 ^" A; }9 X7 P
TX:发送数据输出! q# I, A, g+ p+ l7 ^
GND:双方要共地,双方通过USART进行通信,两个设备必须要共地,因为逻辑1---3.3V电压(对于地的电压),如果两个设备不共地则对地电压的高电平(3.3V就可能不太一样)。共地的意义是让两个设备的通信电平对地电压相等
/ H. l) l0 M2 `* f; a7 Q; Z: g+ e! y$ m4 P7 i- n
143313vbrrl0ybxaap3skz.png.thumb.jpg   Q  J4 X' _- g9 D( \$ C4 b" b

. F8 a; B1 L$ q; P0 {" B1.3 数据帧格式
& ^8 M5 \- I9 _, i+ y一帧数据=1bit起始位[低电平]+8bit数据位+1bit奇偶校验位[可以不用]+1bit停止位[高电平]: q4 x: C; v& K- O0 M

7 h1 g' F$ c2 O: P9 eUSART总线空闲,即没有数据发生,TX线为高电平) V% G& ~. L  a; Q

  P$ r4 h+ c# U3 k4 f( {5 D* M3 {<1>数据位:USART发送的1次数据量是1Byte=8bit;[5、6、7、8]
0 t) n# r% k6 A6 u6 n' s, R7 a<2>数据字:数据位+奇偶校验位;如果不用校验位,数据字=数据位=8bit;如果使用校验位,数据字=数据位+校验位=9bit
$ i7 }5 N; M- n; G. N                    奇校验:数据位中的1的个数+校验位中的1的个数为奇数
4 x. @; h  o1 U1 h  S8 v                    偶校验:数据位中的1的个数+校验位中的1的个数为偶数
2 g0 d6 h) x( ^2 |: P( U<3>停止位:可以被配置为1bit(默认);2个停止位(可用于常规USART模式、单线模式以及调制解调器模式);0.5个停止位:在智能卡模式下接收数据时使用;1.5个停止位:在智能卡模式下发送和接收数据时使用! }( q0 P6 v( B0 z0 ~: Y
<4>发送顺序:先发送低位,再发送高位
/ O8 y% }( `0 ?7 r! F( o5 U
4 o( N8 A! A6 Q7 m' [5 H1.4 框图2 J! s5 ?# |" k" `( G

6 B, ^: v1 L" T  L3 i$ p# `  | 143305ex594sdg0xa59ahj.png.thumb.jpg
; e9 J% v0 H3 h3 |/ Y0 o' ~% K, ]. _( y4 J; ?, r" {/ F" p
对于这个框图,最关键的是两个标志位TXE(发送为空标志位),RXNE(接收不为空标志位), K/ D+ q& g9 H7 \8 @
数据通过RX端口进入MCU的UART的接收移位寄存器,随后进入接收数据寄存器(RDR),进入后RXNE被置1,表明可以读
5 T" g: K% X% ~5 J$ s4 p# SMCU通过数据总线获得数据,数据再到发送数据寄存器(TDR),若TXE=1,说明数据已经被转移到移位寄存器,表明可以发送5 s: y4 E2 V% L  ?, W  o* J7 m# X
2 K/ a' E: _; s# S1 J# [
二、串口通信3 J5 n. U9 l- ?
配置UART
3 n6 Y& @, A3 r: V' s- e3 }2 O+ C/ R7 Q1 d( [" E+ ~/ a
开启了接收中断和空闲中断
* w( x4 H9 K1 ?8 O5 ^4 f+ F' X& ~5 s$ v3 e# O
/****************************
0 U' j: J7 [3 Y5 \6 i1 z' q*@brief    uasrt1端口配置函数  q0 c+ l- @/ C+ J! \
*@param     void3 a- ]2 C0 c' u( S: C7 Q
*@return    void
  @. J* f/ C; @$ n; d*@NOTE      PA10->RX PA9->TX
8 p9 s5 E, @  N) `; h0 c. R2 I1 n            PA10,PA9位于APB2上) U4 W8 I: Q: P6 `3 U' n0 ]: Q3 p
*@time     2025-6-3  z7 {! v) _5 s' p/ ^# t
******************************/3 ]' j. K  h- ]1 t& l
void usart1_Init(uint32_t Baud_Rate)7 H" F" l  N" B6 x3 [' l
{
8 s" @0 |' M9 k& h+ Y+ V& p% a1 w        //1.打开引脚时钟PA# m; Q# E$ b  d! D6 `
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE)      ;
" Q, H+ R2 g2 \" I  @; [       7 y$ I: X4 f" R7 V
        //2.打开usart1时钟
7 ^# u1 @9 c; }/ Z9 i" t        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)    ;
% T. t1 U' _: C1 G; z      
9 j0 r, z& \  @$ m8 w        //PA9->TX推挽复用输出5 j) o8 f6 e/ ^7 J. i, V4 u
        GPIO_InitTypeDef GPIO_InitStruct_TX                      ;
; d8 d6 x3 E5 ~$ @- N: U* |' b; |        GPIO_InitStruct_TX.GPIO_Mode  = GPIO_Mode_AF_PP          ;
( `! y$ g- I2 ?$ w- y' _        GPIO_InitStruct_TX.GPIO_Pin   = GPIO_Pin_9               ;
3 M4 S  u) E1 @; |7 B3 v        GPIO_InitStruct_TX.GPIO_Speed = GPIO_Speed_10MHz         ;
0 t5 o, |0 T# H' d        GPIO_Init(GPIOA,&GPIO_InitStruct_TX)        ;) b) J, O  A/ J! f5 S
      
6 n0 f, p0 o8 }       % t  H8 l) L1 t
        //3.配置,PA10->RX浮空输入+ x5 U  |- d) N. b
        GPIO_InitTypeDef GPIO_InitStruct_RX                      ;
3 s$ z) _8 T# s4 b        GPIO_InitStruct_RX.GPIO_Mode  = GPIO_Mode_IN_FLOATING    ;4 `, l! L* F' ^* q2 b9 w4 d# C  ^
        GPIO_InitStruct_RX.GPIO_Pin   = GPIO_Pin_10              ;: s# o8 w9 ?4 B( u8 W
        GPIO_Init(GPIOA,&GPIO_InitStruct_RX)        ;
3 P  y: \8 J" n* f2 W; H) t& C* Q      
8 t" t. c4 p1 g        //4.配置usart1,9 |; g7 A) M& g. q" N. I( M1 a* F+ j
        USART_InitTypeDef USART_InitStruct                                           ;8 t% ?- a" R; i. H/ m% Q8 h8 c
        USART_InitStruct.USART_Mode                = USART_Mode_Rx|USART_Mode_Tx     ;. Y! O: l0 [6 N* @
        USART_InitStruct.USART_Parity              = USART_Parity_No                 ;
" V; I6 |2 {7 r4 W7 J% u8 e& w' V- D        USART_InitStruct.USART_StopBits            = USART_StopBits_1                ;
& Y' j' {0 x" x/ b9 c7 I% E( Z) ~3 E        USART_InitStruct.USART_BaudRate            = Baud_Rate                       ;       * E! q3 [5 X1 X# L* ?: [% P7 t/ p& J
        USART_InitStruct.USART_WordLength          = USART_WordLength_8b             ;3 B/ z9 B+ s6 y  x
        USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None  ;
0 r6 u$ D- ~, d  S        USART_Init(USART1,&USART_InitStruct)                                         ;
0 |! s- Y5 l) n8 {3 y: s8 s- a
0 Z6 L5 t; |: H                  
% n2 s+ d; B" b) Q  z4 y                  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE)                     ;//开启接收中断 RXNEIE=14 J% Q- D9 G5 o( e5 v5 s
                        USART_ITConfig(USART1,USART_IT_IDLE,ENABLE)                     ;//开启空闲中断 IDLE=1
. t2 a" p6 @2 N- q- d: G                  //初始化NVIC" t+ W5 B, e) w' D
                  NVIC_InitTypeDef  NVIC_InitStruct                               ;
/ e4 y9 N. }0 G- X7 I4 m- H5 k                  NVIC_InitStruct.NVIC_IRQChannel                   = USART1_IRQn ;//中断通道, P4 G3 E! C% W. h! C: L: ~
                  NVIC_InitStruct.NVIC_IRQChannelCmd                = ENABLE      ;//中断使能3 P- ]. D# X# P! m" u! a/ h/ \
                  NVIC_InitStruct.NVIC_IRQChannelSubPriority        = 2           ;//响应先级3 ], Z3 j3 m5 D. R8 T& Q
              NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2           ;//抢占优先级6 t; t9 v/ C4 r2 c0 l
              NVIC_Init(&NVIC_InitStruct)                                     ;. j& t" o0 s& ]7 E" |
       # ~8 Y" j$ j9 R
        //5.使能usart1$ l6 U' @  ^! q0 J9 I
        USART_Cmd(USART1,ENABLE)                                                     ;
5 ^: b2 T7 C# @1 g$ s}  ! G/ Y) d5 Y; |+ E/ W8 M3 Q
: T" M) u* s# W6 _- b# I; M6 _
: V* Q5 f3 }# [" g3 i
接收发送函数
- ^+ U1 @7 ^! c. R  W: B& S' v* B/ S# ]. O: _  x2 q; S) D
/****************************3 O' w. T" Y6 G
*@brief     发送字符函数/ X9 d4 [$ \* ~
*@param    void: G% m) o* y7 H0 S
*@return   void
- K1 P! K$ F/ h9 I1 _  X*@note     MCU会将数据发送到DR寄存器中的TDR寄存器中,6 t3 b! p6 U. a1 W
当TXE==1时,TDR寄存器会将数据加载到移位寄存器中,可以发送
5 H) K7 R4 n3 n*@time    2025-6-3/ U7 ^% o, r; @7 x. L
******************************/
$ y" x1 A1 U$ i% z- G- Cvoid usart1_sendbyte(uint8_t str)0 L4 v1 }. n( D8 s' Q, f
{2 z  ^. \+ i% S$ G
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==0);
0 j6 n8 W2 Y/ [; ?2 Z2 y" Z; S- `% |        USART_SendData(USART1,str);) B3 a# Z  i* s
}% m6 K% o- X" B- z
5 Y4 P' u8 g9 I( b+ K
/****************************4 K! \% {" C3 ~
*@brief     发送字符串函数% s5 ?  y. R6 l: a% H, E; j( U2 f
*@param   uint8_t *str
! f' E: U, Z# g  `  H, s*@return  uint16_t len
5 O! ?/ g9 }' O* j*@note    发送字符串本质上就是发送字符
% m! p. }3 @) P: x; h' O. `0 P*@time    2025-6-3
( T' Y! B; z7 C% m1 m******************************/- ?, M) R+ Y$ s: q% @1 j2 t+ ^- j- i
void usart1_sendstr(char *str,int len)3 r. ^& R; u( q6 j- R2 y4 e8 \$ c
{
9 P. Y  p% u$ Y  k: |& b% O        while(len)5 k" [: T) O/ F6 j1 v" i" I* o
   {+ g! j8 h4 r8 {$ Q- R$ J! I
                 usart1_sendbyte(*str++);
3 n3 `2 `0 t* ^& ?! q4 a+ G' j) h                 len--;; n; ?& j2 C$ g* a+ m  `# H
         }4 b' d4 T% W8 f3 p6 p+ ~3 i1 t# i5 z
}3 i8 ], m- n6 q3 ^6 F+ s
& D! M9 \9 D& g' }) \# O4 F
/****************************
8 ]6 {  P# x. i8 v1 H2 \*@brief    接收字符
9 Z5 s# Y/ p1 c/ q5 \  D) I1 v) N*@param    void! {2 x$ z7 u3 g5 ^+ A
*@return   void
) `! K8 w* }$ `1 d*@note    MCU接收到数据后先放在DR寄存器的接收移位寄存器
  Z6 C1 [$ j! p" W4 q* F          数据会到RDR寄存器中,当RXNE==1时,说明RDR有数据,可以读
2 _& T2 Q- Q/ h; j7 q. h*@time     2025-6-3  r1 b2 i- R9 I
******************************/
1 z- U* W/ f6 O9 suint16_t usart1_receivebyte(); c* K9 R' V. T6 d  \& v
{* V9 P- \1 x' ?9 f) `7 q1 O
        while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==0);4 [# q: u! ?6 z6 z" w* }( }
        return  USART_ReceiveData(USART1);
0 _# F3 G* a) j! H- o9 P, f}
, t7 Y2 N5 \6 U* n( P- w/****************************
+ p5 `  l- l( B5 Y' [5 p*@brief    接收字符串函数(idle标志位)
' T; e" A4 ?8 K% x1 x*@param  void
% d3 y5 u) M0 I& d+ u*@return   void
2 R: V2 H9 _# ?8 I# D) R*@note     void
. l5 [- b! C2 o+ w*@time    2025-6-3
' |  D; s* Z7 J2 c******************************/
, y& C8 r( r3 Evoid usart1_receivestr(char*buff)' T# |3 I) Y, x
{
' X3 o0 o' I2 V        uint8_t flag;5 P  m$ v/ ^6 X
        while(1)4 S! d) D2 R4 P2 k; f: [) L
   {
/ ]# {- ]/ r' ?* ^                 if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==1)( v6 I7 G& t& T- y" H
       {
) u. Y$ j: t( J                                 *buff=USART_ReceiveData(USART1);" }5 X- ~# g; I* O/ g
                                 buff++;
; I+ y& A+ \+ j                                 flag=1;7 }# `& Y1 v, h, U5 s4 N
                         }. |( q8 L+ t2 ]* ~" e% T# d- S& D; s
                        if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==1&&flag)
4 S# @0 O2 N$ t, c       {' X- H+ G% Q1 M
                                 *buff='\0'; //当发送时 发送结束标志
8 f# k# M+ E2 a! o, v) P                                 //先读SR,再读DR将置IDLE位置0
  m& s6 ?. m7 N& r, [                                 USART1->SR;
( i2 T4 I/ q) ?* N3 _& T0 M/ g. c                                 USART1->DR;4 b8 n  x& C, F
                                 break;" K( j+ w1 w0 A8 m5 s- b9 W1 M
                         }5 @4 \) |9 }, z
         }- A' M4 s' {% G0 C; V
}0 Z  |0 ^: O5 s) a1 h
( y- E. A, r+ m7 b1 A. T

# s( K; e. f: j" _, [打印函数* T$ F/ y+ J5 e- G

0 f- E8 ?- w; r- L' ?7 C% b记得勾选微库,printf函数不涉及到中断,它是将内存中的数据输出到上位机5 R+ d, Q0 o3 c, p7 m
0 z, _; I* h% G5 l( a- c" e. z
//printf()的底层借助fputc函数进行输出
% g+ \' A3 |2 V( s* B& Z# nint fputc(int ch,FILE*stream)
' z$ I7 T4 ^& p' Q{! @8 `$ J) g) W4 K- w& ~% ^
        usart1_sendbyte(ch);
. K/ o8 P# c0 J9 R        return ch;- f  R  g- o$ J) z; S5 Q4 D9 [
}' w5 R# |0 v/ D( y. Z% ~& J
) L9 r3 G* W# Z, t5 b4 q2 @
1 Z$ B1 P! P$ {) E4 m
143243jrwwvnvkww4wvrto.png . y: S/ c! ^+ E! ~2 w! o

% E  ]8 {* }2 q* W  T中断函数8 z3 ]8 T$ P* C( i
MCU接收到数据时,进入接收中断函数,将数据存到rx_buff[100]数组里;当上位机不发送数据时,说明空闲状态,进入空闲中断,将 rx_buff[100]数组里面的数据发到上位机
3 _, t+ X2 Z5 e% M' @' K: L) Q, _6 Z; N
/****************************
9 T6 A8 {# `" A  c! |*@brief    usart1中断实验6 T' Z6 p+ a- L$ {/ ~
*@param  void8 c4 Z* D; B6 z! u
*@return   void
: I' ], L& S/ y; e9 G! k! c) R*@note     void; F( o& n8 Q# P2 k! {
*@time   2025-6-4
! f, W- |/ i/ W/ o9 M******************************/
8 p% `/ x# w1 P/ z6 Achar rx_buff[1000]={0};
- T! ?% M7 Z' o8 m* F$ z; Rchar cnt=0;
5 j# ?5 i' Q4 K& _$ bvoid USART1_IRQHandler(void). V5 s, h, j) G: R- M6 h
{
+ \4 k3 Q5 r: A! S2 W/ X   //当RXNE=1时,有数据接收
9 k9 Q* I, a, K5 y( D; d        if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)3 W' I5 {/ ?- e6 Y
   {
( i! B" O* O- A* t& U1 [$ t9 o; t                 rx_buff[cnt++]=USART_ReceiveData(USART1);
- S6 j! J8 o3 T! [. E. s                 USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除标志位5 ]7 }9 b8 h$ T% d
         }# ?/ f% {' f& M/ C) J) g4 u/ V) a
         
! I8 p& [+ z, b' S         //当IDLE=1时,
) E! x! C$ g( i! |1 D        if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)9 b& |/ J3 ^: R5 ?9 g
   {
$ n/ V% B- A* N( w5 H7 F) k                 usart1_sendstr(rx_buff,strlen(rx_buff));
  Q/ p3 w- T( S; b0 C6 G                 cnt=0;: p, j- ?. \- h4 {
                 USART1->SR;
0 Z- A: C3 H$ ^9 h                 USART1->DR;                                  //清除标志位5 I3 m( D' T- [5 S
         }
: c) H1 V- l8 p7 T' r5 G' y}- l' z+ w- w$ f, ?! m) d) s

5 @) P' g& f4 W5 v! ?
8 C) P2 M0 o$ d% P. ~7 }" g' `  i& T————————————————6 d5 J, Z. C% k( G
收藏 评论0 发布时间:2025-8-14 18:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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