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

STM32 串口通信UART代码实现——基于STM32F103C8T6

[复制链接]
攻城狮Melo 发布时间:2022-11-8 22:08
通过串口与上位机通信是经常用到的调试方法。! u! u) r! T: g% H
6 y3 \8 ]# g$ ?  ?; L* j
STM32上外设USART引脚配置
) a. ^! B5 _0 G* t. A3 GTX(默认PA9):复用推挽输出* B5 R8 j) e! [7 d; `( T
RX(默认PA10):浮空输入或上拉输入
) {3 ~+ l" N1 d# [9 X9 ~
8 X1 Z/ j3 a! B; h在写代码前需要检查硬件是否满足要求,使用串口通信时一般需要安装CH340驱动或者CP210x等,这取决于你的电平转换芯片是什么。* Q) J( g! L! v. ^/ G& ~

5 M) m8 a! Q4 T" x8 L串口设置的步骤一般为:
6 d- a( ^( a2 _; [1.使能串口时钟,使能GPIO时钟;
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA);
复制代码
4 Y5 D$ [" @) D5 H
需要同时打开GPIO和外设时钟。, @8 b( `7 o. v/ J( m) M& N# m
2. 设置GPIO端口模式;! K8 ~9 f" ]" ]2 L3 ^, e1 K

' f/ a$ U; E! t' @  ^
  1. GPIO_InitTypeDef   GPIO_InitStructure;
    * A0 W; w4 o, i2 ^# ^5 v
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;4 m% I' l) r- W9 w3 t2 _
  3. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    * }8 P' Q8 t9 j  x2 G, V, }  {: a6 ~
  4. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    6 A/ z5 z, \" I4 y. e/ L
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);0 l# s0 m  t8 y9 E% ?7 V
  6. # E5 B5 S3 x) X
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    6 z! M- D3 i  X
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      A1 \# D6 A) I, V$ \; r
  9. GPIO_Init(GPIOA, &GPIO_InitStructure);
复制代码
8 \: O# r( I) y7 O& T, D
PA9:复用推挽模式   PA10:浮空输入# d# N, `. N3 k+ {5 E& \1 ^# X

! n/ u. K2 w3 W4 E9 \3. 初始化串口参数;: }" _  t% F, P* T0 a

( n, Y) C4 I+ K: v. o9 K$ i: C. D  d
  1. USART_InitTypeDef USART_InitStructure;
    - _. a( y: g- p" a
  2. USART_InitStructure.USART_BaudRate = 115200; //设置波特率;  `5 `6 p# K' R) S! W" A
  3. USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
    8 g- a4 z0 W! d; Z) p& c2 i# o+ x
  4. USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位) p/ t& V/ a; k
  5. USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
    ( I/ g% a1 J1 ~; \  F
  6. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
    ! W. _: J5 v$ {% Q" i
  7. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式- P( U: f- [& H. R. B
  8. USART_Init(USART1, &USART_InitStructure); //初始化串口
复制代码
& O4 Z: D" V5 w5 M. P" F4 N3 I) X
4. 开启中断并初始化NVIC(如果需要开启中断才需要这个步骤);; `: B$ ~$ O$ F/ _+ b9 ]% s
0 g# E8 K  x+ g  _6 P* g, W4 J1 r* P
  1. NVIC_Init(&NVIC_InitStructure);8 O' n! K, @1 P6 S
  2. USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);2 H9 b8 A$ K0 ]  `3 C* ~2 J
  3. USART_ITConfig(USART1, USART_IT_TXE,ENABLE);
复制代码
5 @5 x1 ?8 V7 _  _
RXNE是“准备好读取到的数据”事件标志,TXE是“发送数据寄存器为空”事件标志。& t; k) u* G5 y$ T. R. Q3 _0 T
5. 使能串口;+ v" F: n" n9 {$ t( Y6 v3 g- t& \

7 H. m0 e7 ]" f
  1. USART_Cmd(USART1, ENABLE);
复制代码

" ?/ O5 L7 U" C" V6. 编写中断处理函数;
" H6 F( p# F) |( r% b2 \& P2 U- y" s3 Z' w+ r2 V; E9 Q9 P$ E0 G
  1. void USART1_IRQHandler(void)! X8 E1 i. D( ~9 F, d( F
  2. {
    + `+ J% r! h( C) ~6 F8 C0 _9 Y
  3.     if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    2 \) K7 `; h5 D1 \2 U% h
  4.     {
    3 \1 W+ l! o# n+ l: ]( P: e( E
  5.         //编写处理程序
    * E8 S* {; O" V5 K3 `
  6.     }
    ; B- x' P  Z0 t0 J
  7. }
复制代码
# w7 p/ r* u7 Y% E; P
可以根据特定的中断事件,比如判断是否发生串口发送完成中断(如代码所示)。# }) a. Q- ?0 L& `: c

/ r! N. I  ~& K! b) _& x+ \- t7. 发送接收数据。
+ z# ~1 @$ }& ]# p. p: _# e( l6 Y! U3 r8 A) O% @
利用发送数据函数USART_SendData(USARTx,ch);  可以发送一个字节到串口,并利用USART_GetFlagStatus() 读取发送数据寄存器的状态来 等待发送寄存器将数据成功发送。/ x) h6 }/ [+ V

+ b; ?2 V& d% b5 ~
  1. void USART1_IRQHandler(void)
    $ f; Y, w; b6 d8 p- l+ p) g
  2. {
    : e; V% X- O6 M0 `7 s0 v' C+ r
  3.     if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)* G4 m, S; C  |4 I
  4.     {4 x; a& G# Q! P9 U" y2 X, h* T
  5.         /* 发送一个字节数据到USART */ * H& M* w1 N& H+ [/ i
  6.         USART_SendData(USART1,ch); ! e& H2 s: R" q$ V$ m
  7.         /* 等待发送数据寄存器为空 */+ D3 c: \% v' }
  8.         while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);: j+ Y( n* j$ t/ O3 V
  9.     }" d; z( `) W8 l) v" H
  10. }
复制代码

; E- h5 a! c9 f接收数据利用函数USART_ReceiveData();  从DR寄存器读取接收到的数据;在中断处理函数中通过if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)判断是否是接收中断,如果是,则读取串口接收到的数据:Result=USART_ReceiveData(USART1);
& B7 M+ Y# T& G) M' Q5 ~: b( z; F/ {( t! T* l
  1. void USART1_IRQHandler(void)
    $ K, m! S4 {! @2 Q
  2. {4 I5 ?: d7 {4 P4 C6 m3 r
  3.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    9 L# \5 y* C) T3 j# c; D
  4.     {- A: k: r. c$ h; o& z! z# U
  5.         Result = USART_ReceiveData(USART1,ch);
    ; {  q8 j6 V) b  |, g  G
  6.         while (USART_GetFlagStatus(USART1, USART_IT_RXNE) == RESET);. |* w' E4 @  q$ T3 C. ^$ _/ H! Z
  7.     }
    + n$ \  I# N, h  D% H1 d: q" Y7 `
  8. }
复制代码

! }+ |0 J. s/ [! S' ]根据USART_SendData(USARTx,ch);和USART_ReceiveData();两个函数,每次发送或接收一个字节数据,以此为基础,可编写一次发送或接收一个字符串的函数,但这样还是不够方便,为了能像C语言那样使用printf语句输出,需要重定向printf函数发送字符串。* J. h- Y# J3 O
printf()函数实际上是一个宏,最终调用的是 fputc()这个函数来执行输出的,所以如果重新定义了这个函数,就能使函数向串口输出。6 f- E' K; t1 `& S, q/ Z" K( I

2 I! A8 ?! N6 d% d# ~) T7 o0 }
  1. /* 重定向printf函数 */+ _/ e% M9 F" w5 S6 |  }
  2. int fputc(int ch, FILE *f) 0 M3 H) o( I9 Y' G5 ?
  3. {
    * b2 F3 |9 t( |& N
  4.      USART_SendData(USART1, (uint8_t) ch);
    ) p/ \5 p- L8 G7 P
  5.      /* 等待发送完毕 */ 2 d1 B3 f! v% s$ B8 ]
  6.      while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);2 R: C+ Z' ~$ A+ r: F4 w' r( e
  7.      return ch;
    / G  f; s- n. p  i. X# i
  8. }
复制代码

+ U5 T6 ]" i/ y2 k2 \$ q5 @! V同时也可以重定向scanf()函数接收字符串:
* Z4 ]& A4 b. E- y+ M/ j( l) r
9 T+ |  u: O: u- R5 U
  1. int fgetc(FILE *f)
    ! l) |4 r7 j0 @. A  A% o. Z
  2. {
    ) T. Q6 f0 p4 j# R4 p6 A7 k
  3.    /* 等待串口输入数据 */
    9 v& p& S; ?+ a
  4.    while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);0 J  F' Q# @3 d" q$ J" m
  5.    return (int)USART_ReceiveData(USART1);
    . \. `5 y$ ?; ^; B) E8 x$ O6 w
  6. }
复制代码
& N7 p1 i& |. ^8 U5 r1 u
————————————————. W) g# u- A" h" z4 I; f1 p( F- C
版权声明:云缙
/ d5 u- p3 c/ X1 R( e9 p2 g, t
, n+ o/ P5 i' v% ?" Z& {5 m1 K" ?
7 [# m" f6 q$ p5 y% N
赞 收藏 评论0 发布时间:2022-11-8 22:08

举报

0个回答

所属标签

相似技术帖

官网相关资源

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