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

STM32学习笔记17—485通信实验

[复制链接]
STMCU小助手 发布时间:2021-3-10 13:31
STM32学习笔记17—485通信实验

- H4 C2 n4 F. o7 b+ j6 M+ r
17.1 485协议概述
# N+ t9 Z' p) M" |
485是属于OSI模型物理层的电气标准,属于2线制,半双工,多点通信标准,485总线采用两根线路的电压差来传递信号,485两根线路名称为A和B,当线路A与线路B的电压差为+2~+6V时表示逻辑电平1,当线路A与线路B的电压差为-2~-6V时表示逻辑电平0,485与232协议都属于串口通信协议,都是采用转换芯片将USART接口电平转换为485电平或者232电平,485协议传输速率在10米时候可达35Mbps,在1200米是可达到100Kbps,最大支持总线挂载32个节点,如果采用特制的芯片可以达到400个节点。

& a0 j  T  u; t- g
485电气连接中,为了进行阻抗匹配,需要在两根线路中并联一个120Ω的电阻,一般是一个设备并联一个,所以485协议只是之前USART协议的另一种表现形式,通过之前掌握的USART配置,借助485转换芯片就可以完成485通信线路的搭建。

- Y! I  M( v5 p* u) f. S$ ]6 `
17.2 实验例程

9 K8 g; P0 ]: i0 l1 x* h7 {3 t# }! p
采用STM32F103ZET6芯片的PA2(USART2_TXD)和PA3(USART2_RXD)和一个485转换芯片SP485来实现RS485通信。其中SP485引脚描述如下图所示。
6 U  Z" d0 e1 z3 x+ \1 @6 I: G- z
4.1.png

: o8 A5 X. `( b$ S. l9 @* f# z) u
4.2.png

. M2 \; r* ]9 W) i+ [' ?- u
4.3.png

, K$ P. m* g9 G" V4 j
(1)创建rs485.h文件,输入以下代码。
  1. /*********************************************************************************************************
    * A2 O( L& j$ G* v  V. e" _
  2.                   RS485    驱    动    文    件" j8 A/ D3 j. A: }% b% \
  3. *********************************************************************************************************/4 y% d% |! n+ o
  4. #ifndef _RS485_H_
    " v2 E8 D( J) ?. k7 T9 B  c! F
  5. #define _RS485_H_
    ; X4 B& ^6 ]. w- n

  6. 2 Y! \1 A0 K5 P  e4 I7 k  B
  7. #include "sys.h"
    3 `9 y* w1 V. e3 L) \  K. c' z+ ^4 T) {
  8. /*********************************************************************************************************
    ( Z' c9 P% x( r
  9.                 硬    件    端    口    定    义
    * T  ^! ~# B2 ?3 J3 I/ G
  10. *********************************************************************************************************/
    ! g. j6 |- k" K# C
  11. #define RS485_EN  PDout( 7 )
    8 R- B. c3 z. f) Q4 Q
  12. /*********************************************************************************************************
    , r* N2 Z0 `( |/ L8 K- }
  13.                 数    据    结    构    定    义
    7 s: u! R- s. ]3 i) \$ W
  14. *********************************************************************************************************/
    % @! |2 d" R4 E2 |
  15. typedef struct/ [. b; S/ \6 c# s
  16. {, F4 [' B6 T" s) `
  17.   u8 Buffer[ 255 ] ;
    # G2 H7 \: x( l$ b2 W+ Z
  18.   u8 Len ;/ b) M# z3 Y( C& ~* e$ z. A, M
  19. }Communication_Data;, z$ n4 F- H. r' x
  20. extern Communication_Data RS485_Data;
    ; j& X* B: c" T! f" |+ R
  21. /*********************************************************************************************************6 A0 }: ?/ q, [5 d( C  U' c
  22.                     函    数    列    表7 v1 D4 ~  I$ ~8 e$ a) l& \
  23. *********************************************************************************************************/2 {$ ^$ b% G+ @4 d! P1 \2 `
  24. void RS485_Init( u32 pclk1,u32 bound ) ;                                //RS485初始化
    # I- |! v5 s, F7 p/ \
  25. void RS485_Send_Data( u8 *buf, u8 len ) ;                                //发送n个字节) b$ l/ J+ P/ h0 P+ q/ i
  26. void RS485_Receive_Data( u8 *buf, u8 *len ) ;                              //接收n个字节
    + o. ]3 T. Q8 E3 X- L5 I
  27. # f* c6 u, H6 Y
  28. #endif
复制代码
$ Q; t7 t! `. g( R% `4 o- B( ^
(2)创建rs485.c文件,输入以下代码。
  1. #include "rs485.h"
    ! y( v; T) [5 i0 H; [# F
  2. #include "delay.h"
    . h6 p2 p. e0 ]- s

  3. " \6 X2 S- s$ H' `% j7 U+ [
  4. Communication_Data RS485_Data;: Y  W$ Z' x# i$ d% P- W7 n
  5. /***************************************************
    & K! e' T. ?! q6 f+ o* S
  6. Name    :USART2_IRQHandler( ?! u# F2 _9 \; S
  7. Function  :串口2中断服务函数
    ' ~! V. ]4 y; o0 g# D. |
  8. Paramater  :None" V6 h8 A. t: |/ |
  9. Return    :None: V4 X- O9 C6 }7 F3 }+ n2 _
  10. ***************************************************/8 E, m& w0 ^9 U% X
  11. void USART2_IRQHandler()2 C- ~# g; G- _  m4 [/ W! ^
  12. {4 Y9 o0 M4 q2 a( y- ^+ z0 e& y
  13.   //接收到数据) ?$ t% x+ ]3 e1 u* Y+ |6 O9 p
  14.   if( USART2->SR&( 1<<5 ) )+ W0 m+ x6 N9 J! @
  15.   {
      F7 q& L  O' G. |1 p/ O- \
  16.     RS485_Data.Buffer[ RS485_Data.Len ] = USART2->DR ;                        //记录接收到的值4 s# |1 U5 X/ n. D
  17.     RS485_Data.Len ++ ;                                        //接收数据增加1
    " b! K4 P, L+ W4 s  X2 `
  18.   }$ V# R1 S9 J) J: Y
  19. }
    ' b! {3 V" r1 H, E  A
  20. /***************************************************7 a; P4 ]5 \2 l9 ?9 d
  21. Name    :RS485_Send_Data- U) A' ^' z! u7 h& u3 f- y
  22. Function  :接收n个字节) n6 k$ n2 ^0 x  ?
  23. Paramater  :! B' J# F$ V6 ?1 H3 Q- D# F, N7 r; \
  24.       *buf:接收区首地址
    ( D) r& r5 }3 j. U( B( s6 r. r
  25.       len:读取的字节数
    % y6 i4 I2 R9 F
  26. Return    :None
    & M' D+ s9 w" w% L( m2 |
  27. ***************************************************/
    1 j& P* U3 `6 w8 k
  28. void RS485_Receive_Data( u8 *buf, u8 *len )
    . E, N) }; W) I. q) N
  29. {
    % e* j4 H4 M3 \3 m' ~( @8 G6 m( B* O" e
  30.   u8 i, rxlen=RS485_Data.Len ;
    & P% w) l2 [& Y
  31.   delay_ms( 10 ) ;                                          //连续超过10ms没有接收到一个数据,则认为接收结束! n+ J1 U& G) |
  32.   //接收到了数据,且接收完成了
    ; W( r- S/ {0 b/ N3 B4 t# W4 }
  33.   if( ( rxlen==RS485_Data.Len )&&( rxlen!=0 ) )
    5 @: }0 g& k# f1 n
  34.   {) w+ e, a/ P* k! t
  35.     for( i=0; i<rxlen; i++ )
    - a& B! c2 W+ k9 q" x  g! b7 F
  36.       buf[ i ] = RS485_Data.Buffer[ i ] ;% ]: V4 `# k. P* f6 c2 h1 p
  37.     *len = RS485_Data.Len ;                                      //记录本次数据长度
    / t4 Y' [' N1 `' K
  38.     RS485_Data.Len = 0 ;                                      //清零3 i$ J' _! o4 K* L% D
  39.   }
    # b& m6 A% `* M. C7 [$ q
  40. }
    ; O2 W' y" {9 e; A4 Q
  41. /***************************************************' V! T3 |9 k! z8 |
  42. Name    :RS485_Send_Data0 @( u: N% y9 w8 V% T2 T
  43. Function  :发送n个字节* Z9 o3 K. ~3 U+ \
  44. Paramater  :
    * H; ^) O" ]2 o4 A, U+ ?; [
  45.       *buf:发送区首地址& _$ d& P; g5 q- u, `0 A
  46.       len:发送的字节数2 @+ M; u% \/ C" |1 w9 F. v% J5 j
  47. Return    :None
    1 i8 ]' i. z6 |% o8 C8 Y
  48. ***************************************************/
    - x- t5 A3 c) W0 f  ~, J
  49. void RS485_Send_Data( u8 *buf, u8 len )3 U1 T! g+ z4 x, d& P
  50. {
    " o' {7 P  ]! L  N2 L+ ~5 u
  51.   u8 t ;) I( T; B+ \% i
  52.   RS485_EN = 1 ;                                            //设置为发送模式( q! [% D8 W2 k- J
  53.   //循环发送数据
    ! K- Q, R. _9 D2 F: x  k3 x3 C. ~: c
  54.     for( t=0; t<len; t++ ). Z% s* B) O; [- Q3 G
  55.   {( A8 S" |  o& Y; ]
  56.     while( ( USART2->SR&0x40 )==0 ) ;//等待发送结束5 Z, t) A% I8 C; y: |
  57.     USART2->DR = buf[ t ] ;* V9 B* [  {0 D6 ^( h* W- ?
  58.   }   
    ! \7 O6 C$ C% b4 [
  59.   while( ( USART2->SR&0x40 )==0 ) ;                                  //等待发送结束  & Y+ N1 E8 Y- y: S9 t. T
  60.   RS485_Data.Len = 0 ;/ z) |% i- G6 b$ q/ [
  61.   RS485_EN = 0 ;                                            //设置为接收模式. X8 S% }4 V$ l2 @- v( p
  62. }
    , h4 j# b5 ?1 N7 X1 C
  63. /***************************************************' C. C! L5 `/ M! D7 t. U0 R
  64. Name    :RS485_Init7 g% }7 o7 Y1 T5 t+ o
  65. Function  :RS485初始化
    3 s& F7 ~' i+ k4 H) j4 c6 S
  66. Paramater  :
    3 O, d+ O1 \* Q2 B$ x/ }) }5 n
  67.       pclk1:PCLK1时钟频率
    " G! N8 K7 k( _* z2 P6 c+ n
  68.       bound:波特率
    " W3 K5 f* q) n/ O9 C
  69. Return    :None/ c  \6 L; b, m% z) v
  70. ***************************************************/+ F; g! _5 M/ U6 f) S) ~2 L$ g6 r* V
  71. void RS485_Init( u32 pclk1, u32 bound )
    ( a8 E" l6 z4 \7 p- V2 s0 G
  72. {8 Z$ Q- F2 t' V: G
  73.   float temp ;
      V# L! H" ]& S6 Y) v
  74.   u16 mantissa, fraction ;
    5 g8 h* X% {& |
  75.   temp = ( float )( pclk1*1000000 )/( bound*16 ) ;                          //得到USARTDIV
    " u6 Y0 |, l0 g: w4 T3 J
  76.   mantissa = temp ;                                          //得到整数部分
    & B% q# d7 S3 ~  o3 I
  77.   fraction = ( temp-mantissa )*16 ; //得到小数部分   
    ) P( V6 u) r' ]
  78.     mantissa <<= 4 ;4 e4 M7 [, a, y
  79.   mantissa += fraction ;* W- b6 \( F) Y/ |
  80.   RCC->APB2ENR |= 1<<5 ;                                        //使能PD口
    9 r) T7 |* U% u
  81.    GPIOD->CRL &= 0x0FFFFFFF ;# N9 R; G2 w; B2 ]
  82.   GPIOD->CRL |= 0x30000000 ;8 R& w* w" b( t* G: B$ H8 R
  83. - R; w  `) ]- m: w
  84.   RCC->APB2ENR |= 1<<2 ;                                        //使能PA口" S( C. [1 g2 m% X2 `2 G& U
  85.   GPIOA->CRL &= 0xFFFF00FF ;                                      //IO状态设置
    , m$ W; U( E; n# a+ ^$ U! N
  86.   GPIOA->CRL |= 0x00008B00 ;                                      //IO状态设置0 w2 G: v! m( v8 c% S" l' ?
  87.   RCC->APB1ENR |= 1<<17 ;                                        //使能串口时钟
    1 ?1 ?7 l) S" M+ t/ Z  q
  88.   RCC->APB1RSTR |= 1<<17 ;                                      //复位串口2
      T9 k- A! _. D! C: R' A# J- A
  89.   RCC->APB1RSTR &= ~( 1<<17 ) ;                                    //停止复位7 ~4 X( k9 T% u( ^
  90.   //波特率设置
    5 w9 A5 t6 Q3 z& Z
  91.    USART2->BRR = mantissa ;                                      //波特率设置& v8 S( f, j/ X- [$ ^2 C
  92.   USART2->CR1 |= 0x200C ;                                        //1位停止,无校验位3 Q, W. r; a. v7 K7 I
  93.   USART2->CR1 |= 1<<8 ;                                        //PE中断使能
    + K( L+ Q; Q, j  @- B, k: Y2 \
  94.   USART2->CR1 |= 1<<5 ;                                        //接收缓冲区非空中断使能
    + J( u5 J; {0 g5 i- C6 f8 w
  95.   NVIC_Init( 3, 3, USART2_IRQn, 2 ) ;                                  //组27 a  M! |4 w0 y$ \8 g9 a6 L
  96.   RS485_EN = 0 ;                                            //默认为接收模式5 G  J! J- P% F
  97. }
复制代码
' k" S/ i/ Y( O! ~: |4 r
(3)创建1.c文件,输入以下代码。
  1. #include "sys.h"; Q) `9 y1 \- ~' l! ~
  2. #include "delay.h"
    / E: C) A& a3 g
  3. #include "usart1.h"8 ~" M3 S: P; q' c+ |; r$ q% F
  4. #include "rs485.h"( S' ]* P8 F( v3 a. [1 S- N
  5. 9 S7 `4 V8 @2 n' d) q4 v  ~' v
  6. int main()0 |3 x+ R! [" F& j6 }, X
  7. {
    $ I. p, p) K+ H8 h0 }! n0 ?
  8.   u8 len, datatemp[ 10 ] ;
    ! k( U4 g, @- ]# H
  9.   STM32_Clock_Init( 9 ) ;                                        //STM32时钟初始化8 N5 z$ r5 n+ S) ?1 i' r. x/ D
  10.   SysTick_Init( 72 ) ;                                        //SysTick初始化4 n( ?" o, D; E7 T4 a
  11.   USART1_Init( 72, 115200 ) ;                                      //初始化串口1波特率1152002 ]5 x7 j; e. p# Y" O" D/ h1 q
  12.   RS485_Init( 36, 9600 ) ;                                      //初始化RS485
    3 G; i  b5 B) v, c
  13.   RS485_Send_Data( "RS485 Test", 10 ) ;                                //发送数据
    ) U' L. I9 Z( S. b5 H3 K
  14.   while( 1 )
    8 h# {% k/ s9 @! N/ \' ~! Y1 Q! E
  15.   {
    ! d4 `% ?, t* a) Y" j% M
  16.     RS485_Receive_Data( datatemp, &len ) ;8 D: }! `7 _4 p, F6 C6 Q
  17.     delay_ms( 10 ) ;
    ; V( n' c0 \2 x2 f0 p* y: |
  18.   }
    : J- X& T; }% y& j% e, Q
  19. }
复制代码

4 n* V6 Z) U4 ?3 Q; _( `6 V" j
文章出处: 滑小稽笔记
/ K0 [( S0 P8 s3 F! I
赞 收藏 评论0 发布时间:2021-3-10 13:31

举报

0个回答

所属标签

相似技术帖

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