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

【经验分享】STM32串口多机通信

[复制链接]
STMCU小助手 发布时间:2022-1-23 15:26
最近在做多节点无线通信,用到STM32 USART多机串行通信。
记录下多机串行通信配置要点。
下面是我封装的会用到的函数:
  1. // .h
    1 m9 {" \0 G* O
  2. #ifndef _MULTIUSART_H
    : u# Z4 m! t+ O, t! ]
  3. #define _MULTIUSART_H; o4 F" v: y/ [3 f! L4 \
  4. #include "sys.h"
    : |$ u& K8 V+ y: u- }9 J5 Z9 i
  5. #include "stm32f10x_usart.h"3 I# u6 o& ]) Q' v: v* z3 t

  6. + X: U+ }; k0 p
  7. /** F/ w3 G% s- ]2 o4 w4 ^  Y
  8.     USART_SR状态寄存器
    # i5 l4 e/ I" ~  Y  v+ [2 D& j
  9.     USART_DR数据寄存器
    ) n2 J: s1 |& g; Q# B& R
  10.     USART_BRR波特率寄存器0 P3 Z4 Z2 J+ C8 c2 c, |; a! d
  11.    
    4 z7 N0 o1 h, a+ ~
  12.     TXD-PA9) p; g) S  k$ h! P0 H5 N# z9 H: Y6 y
  13.     RXD-PA10
    6 |( q1 O) y: O3 S2 Y# `" a
  14. *// c# }9 R: T5 D0 ]
  15. 5 |* W$ \" S' T) g, U" O6 D
  16. #define USART_REC_LEN              60      6 q+ Z% w% C7 a: _: G
  17. #define EN_USART1_RX             1        //使能(1)/禁止(0)串口1接收
    8 P: P7 I% f  a8 C
  18.           * x5 a& d" v- v2 h5 v% X! k' c' D% h
  19. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
    ! u6 |1 p/ y# H" M8 ]4 H# R
  20. extern u16 USART_RX_STA;                 //接收状态标记    + k- x0 L) W5 N+ t

  21. 2 r" b9 D3 l7 b4 W/ D
  22. extern void USART_InitEx(u32 bound);
    ) u! v6 A% U& m' u, B
  23. extern void USART_SendDataEx(USART_TypeDef* USARTx, uint16_t Data);
    , G4 [# S$ G" x; D
  24. extern void USART_SendAddr(USART_TypeDef* USARTx, uint16_t Addr);# a, n8 c1 {3 g8 x% S

  25. / R& i6 t, f2 o! ~: _
  26. 2 H+ _1 z! t* R( y7 @0 E0 H( S0 A
  27. #endif
复制代码
  1. // .c: P' ?! v) E& t8 O: ~
  2. #include "MultiUSART.h"7 o+ Y* F% M+ j) S, S

  3. . \9 N( j, i: {8 ]: `
  4. ( l+ P" Y4 [" |% l

  5. - {6 {# V0 l1 U7 C
  6. //串口1中断服务程序
    ; w% R/ X1 g! D  `
  7. //注意,读取USARTx->SR能避免莫名其妙的错误      
      z1 L& e2 F" f9 k, s9 f
  8. u8 USART_RX_BUF[USART_REC_LEN] = "";     //接收缓冲,最大USART_REC_LEN个字节.3 e' u. r- v5 v3 u+ H
  9. //接收状态
      L- m6 I- ~. i4 Q  q
  10. //bit15,    接收完成标志7 k( ]' }4 u% x8 \
  11. //bit14,    接收到0x0d  l& \- T" Z5 \9 P5 \0 t! L# i7 A
  12. //bit13~0,    接收到的有效字节数目6 o5 t( I4 J% ^/ }- K3 Q
  13. u16 USART_RX_STA=0;       //接收状态标记      
    , F& V+ v: \) r& U8 K4 e1 `

  14. " N4 c* s! j# @8 A7 W
  15. 4 Y7 O# ?4 ]- s0 r0 S

  16. 4 N- a  x7 D$ {8 n
  17. void USART_InitEx(u32 bound)+ S  r8 I  J( X. q3 q
  18. {: R- ~. v" Q2 g+ \" W) ?
  19.     GPIO_InitTypeDef GPIO_InitStructure;; u2 O% |" G0 N5 g
  20.     USART_InitTypeDef USART_InitStructure;) l4 {5 B5 [3 I" _" B8 b
  21.     NVIC_InitTypeDef NVIC_InitStructure;
    8 h+ |7 v9 t- x" l* n6 {% ~
  22.      
    1 V0 E7 {8 M0 x; _
  23.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟3 h0 I- }! y9 }. m  w
  24.      USART_DeInit(USART1);                                      //复位串口1
    & O4 r/ ^& k. Q8 N" k4 m: a7 W% N; |
  25.    
    0 H5 N7 d! f. O+ Z/ _# V% E
  26.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;         
    2 i6 O  E$ H- M! v# ]
  27.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    7 b) i: N2 B" H
  28.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //复用推挽输出" C3 W/ ]: x1 T
  29.     GPIO_Init(GPIOA, &GPIO_InitStructure);             , m' R1 k: R" _* G
  30.    
    ; }% E" [, X" F. [0 B1 u
  31.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;5 v3 \8 A# N8 }& v& i6 o6 ]
  32.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //浮空输入
    8 x. {' y4 }" c
  33.     GPIO_Init(GPIOA, &GPIO_InitStructure);          4 M$ j1 ?  G5 ^, y6 l. w

  34. % H8 w+ M9 Q1 U9 x$ ^) Y7 }
  35.    //Usart1 NVIC 配置. z+ g/ b8 l& R9 i
  36.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;* e' F8 t" H5 X; K- t4 l3 l
  37.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级34 ]& `: |8 I1 C, x; ~* F1 R8 e
  38.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    $ i# S4 G; O. M
  39.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能2 O4 X" \- x! Q; s" T! F4 x( d
  40.     NVIC_Init(&NVIC_InitStructure);    9 S# ], T3 Y0 S; c2 q4 Z+ }
  41.   
    ! M, K# A5 p- }; Z' q) m( g
  42.    //USART 初始化设置# h: i& h  q" m* J3 E" N+ v6 V
  43.     USART_InitStructure.USART_BaudRate = bound;0 q1 C8 F# @+ R! V+ ~
  44.     USART_InitStructure.USART_WordLength = USART_WordLength_9b;( ?# C6 `5 `! Z- k% i
  45.     USART_InitStructure.USART_StopBits = USART_StopBits_1;
    * J( L7 h) d" F1 @
  46.     USART_InitStructure.USART_Parity = USART_Parity_No;        6 o; K1 j- z% |% W! t7 O
  47.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;: ]! g  |, K9 j! p
  48.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    $ S0 U; o! \, O, y

  49. 6 A* h2 t' g6 M3 }
  50.     USART_Init(USART1, &USART_InitStructure);         //初始化串口: G3 ?7 S5 r  S& Y1 y/ c( B
  51.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);    //开启中断   接收中断9 d, r: L. o) w( ~2 {$ O' V
  52.     USART_Cmd(USART1, ENABLE);                        //使能串口 , R1 S# i1 o3 s, r
  53.     - y5 m4 H/ S" R
  54.    
    , s: _$ S3 w- P6 C2 l
  55.     USART_SetAddress(USART1, 0x01);                    //设置USART1节点地址; s5 j1 Q& `) @3 t8 [. z4 i+ d
  56.     //USART_WakeUpConfig(USART1, USART_WakeUp_AddressMark);//地址标记唤醒
    " o* I4 A* ~! u+ I, i3 B' y
  57.    
    4 Y5 f/ `# Y, }# |( F" _$ G- d
  58.     //USART_ReceiverWakeUpCmd(USART1,ENABLE);
    7 S8 D* k6 E$ p! R: l% [$ a/ P' \) \1 R
  59. }  }+ \* R/ |8 A5 J* n
  60. 3 N/ }+ J9 f. L- ~7 C6 a. Z4 Q) y& ?

  61. 7 Z/ w  U: l9 A- K1 l  F0 p
  62. void USART_SendDataEx(USART_TypeDef* USARTx, uint16_t Data)1 V4 ?6 k. q% o  v0 R
  63. {
    . D& B* n$ c; h3 C# ?
  64.     /* Check the parameters */2 h3 ?' y& u* H. a
  65.     assert_param(IS_USART_ALL_PERIPH(USARTx));
    7 I6 t9 V6 {- M) C( V* y
  66.     assert_param(IS_USART_DATA(Data));
    : x) w' f, @" d, T; E+ F
  67.     2 I: h: j+ K7 o5 E+ l
  68.     /* Transmit Data */$ `& X# r. g* N1 T$ q( W+ z! W; {3 Z
  69.     USARTx->DR = (Data & (uint16_t)0x01FF);
    6 t8 @. R* o& P$ T
  70.     , W3 D$ P! ?8 J0 H
  71.     //等待发送缓冲区空
    & h# ~9 }6 n- F/ v/ u
  72.     //或   等待发送结束
    ! b; V# i  w6 ~1 ~! L  a8 U
  73.     //while((USART1->SR&0X40)==0);" k  d$ Z. X2 S" K1 }/ s" ]
  74.     while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){};
    ( t4 N: w1 g4 A; h) l: `
  75. }
    & D* z3 E% t/ M& _" [1 \
  76. 2 f# n8 A8 v! h5 T1 e- `
  77. void USART_SendAddr(USART_TypeDef* USARTx, uint16_t Addr)
    1 ?) n' Z6 k0 w
  78. {) `8 h7 }4 H9 Z  d1 r& t
  79.     /* Check the parameters */
    6 Y0 Z: G0 C+ N1 q
  80.     assert_param(IS_USART_ALL_PERIPH(USARTx));
    6 k3 b; j, c0 F( _: @+ G
  81.    
      _" q$ A' O0 @, S- ~4 A1 u  ]( t
  82.     // 9位字长, 最高位为1,低四位为地址
      y3 P* G! n1 V3 O! p3 [
  83.     //USARTx->DR = (1<<8) | Addr;- x+ [0 w- ~. v1 H! t+ n
  84.     Addr |= (uint16_t)0x0100;
    + w8 f7 u% S2 h# l
  85.     USARTx->DR = (Addr & (uint16_t)0x010F);8 k, ^" P: y2 t: ~
  86. }2 I$ L& \' p" J. m0 Y* A( I0 U9 [
  87. % u; j  h$ }* {, U% b" A5 q2 L( p
  88. #if EN_USART1_RX 4 V2 b* C) A: b6 o* b
  89. void USART1_IRQHandler(void)                                //串口1中断服务程序
    " T! x! l8 G, A  \3 Q
  90. {
    . e) |( d- ?- G3 @1 C6 C
  91.     u8 Res;
    - [  i2 l8 j) I0 Y) @
  92.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)      //接收中断(接收到的数据必须是0x0d 0x0a结尾)# l$ ~  R, B. n$ j$ A
  93.     {
    3 ]- Q3 _. I" u, e* m% K6 P0 T) J  G
  94.         Res =USART_ReceiveData(USART1);//(USART1->DR);        //读取接收到的数据
      q8 z; ~4 @$ |. Q( r4 z
  95.         , O# T; m4 X1 X
  96.         if((USART_RX_STA&0x8000)==0)                        //接收未完成# \9 B3 b% m: S2 {, ?6 u* Q% s, \
  97.         {8 N. Q& w; k" a
  98.             if(USART_RX_STA&0x4000)                            //接收到了0x0d: d# c, k1 m* x3 e  Z
  99.             {
    $ E& `9 [7 f5 \2 J
  100.                 if(Res!=0x0a)
    # N* K; F, r+ V$ Q
  101.                     USART_RX_STA=0;                            //接收错误,重新开始3 S5 T, u2 W  E! T. `, E6 |
  102.                 else
    0 y% U1 R: I: k, {' N5 E
  103.                     USART_RX_STA|=0x8000;                    //接收完成了
    6 _2 G! P8 \; L9 U
  104.             }% N' \! e  u2 g0 [% j
  105.             else                                             //还没收到0X0D7 }3 o0 b; C2 g/ x
  106.             {   
    - R2 F) M! P9 t, S
  107.                 if(Res==0x0d)
    # o, n3 y" a. T4 @
  108.                     USART_RX_STA|=0x4000;
    $ u, m6 j( E; Y1 c/ O
  109.                 else
    " e( `% I0 W8 Z7 o  f# }; w
  110.                 {1 s* N. n  K# |
  111.                     USART_RX_BUF[USART_RX_STA&0X3FFF]=Res;! r) G; q' x0 }, w; @. ~8 \
  112.                     USART_RX_STA++;
    & Y9 |" O6 B/ G" F( M0 @( {# S
  113.                     if(USART_RX_STA>(USART_REC_LEN-1)), ]3 Q* P4 a+ X
  114.                         USART_RX_STA=0;                        //接收数据错误,重新开始接收      
    2 @+ C0 U7 G0 h3 t; }& ]* \6 m
  115.                 }         
    - c6 e6 z4 B' _7 K* J" ]+ N
  116.             }$ V3 X, T, O. q7 P+ ^' x
  117.         }            1 ^: ?' b7 n: M$ C
  118.      } , N( k9 D2 K9 ^( C: S% Y7 G
  119. }# m5 c* k. Q9 @  ?) h/ ?. ~
  120. #endif
复制代码
在主机端,可以写个键盘控制发送地址,类似:
switch(KeyValue)3 y3 W6 z; @; O( b
        {; s% r9 J8 ]$ A3 `' O9 E" s6 ~
            case 1: USART_SendAddr(USART1, 0x01); break;  //从机1) ]9 s; w; G4 u
            case 2: USART_SendAddr(USART1, 0x02); break;  //从机2
.............
然后即可自己设定通信协议分别处理从机发过来的数据了。
+ i! d" K+ i2 K! E* @
在从机端,由于要设为静默模式:
USART_SetAddress(USART1, 0x01);    //设置USART1节点地址 如从机1设为0x01
USART_WakeUpConfig(USART1, USART_WakeUp_AddressMark);  //地址标记唤醒
USART_ReceiverWakeUpCmd(USART1,ENABLE);  //使处于静默模式
这几句在串口初始化时要开启。
6 d3 G2 c: F4 C5 Y, s) ~
当主机发出正确地址给从机时,下面if 语句便成立可执行。
//从机被唤醒, 接收中断恢复正常   
if((USART1->CR1 &((uint16_t)0x0002)) == 0)$ j; j  a; H& U' m: G' M5 p* P
{........}
从而可在其中添加从机要给主机发送数据的程序。
( l& S9 z" V7 D$ f! ^
收藏 评论0 发布时间:2022-1-23 15:26

举报

0个回答

所属标签

相似技术帖

官网相关资源

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