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

【经验分享】STM32:Modbus-RTU通讯协议——CRC校验

[复制链接]
STMCU小助手 发布时间:2022-5-3 15:45
循环冗余校验(Cyclic Redundancy Check,CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。6 Z# y/ |3 d9 d# @; D6 F/ W
! F4 ?  y1 `/ ]% ?
一、16位CRC校验计算方法
& v+ J0 a( v, ^1 w2 u  E$ I1、 预置1个16位的寄存器为十六进制FFFF(全1),此寄存器为CRC寄存器。
2 O6 Y. _8 k2 f  }# \( m$ A
8 L" _9 H# f3 b' Z4 D& g2、 把第一个8位二进制数据(即通讯信息帧的第一个字节)与16位的CRC寄存器的低八位相异或,吧结果存放于CRC寄存器。: _6 ~6 K( y( @5 q7 s
9 C! O, w. l1 _/ R0 \
3、 把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检测右移后的移出位。: d' u  t0 x. E1 H( ?" V
6 C* e6 V7 k/ i6 R
4、 如果移出位为零,则重复第三步(再次右移一位);如果移出位为1,CRC寄存器与多项式A001进行异或。- A# X$ |: `8 E6 m) l. L

; c% Z$ Q# b" \5 A; k4 u9 z9 K4 u5 Q5、 重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理。
! F/ l* J2 }+ V3 t  o& {2 b$ n
0 i4 [9 s+ Z% n, [' {, T5 b3 M5 ]6 t6、 重复步骤2和5,进行通讯信息帧下一个字节的处理。
8 i; u" R2 b! O, B+ g. e! ~. t0 {7 e3 P
7、 将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换。
6 Z9 ~- Y# m1 `  M
, _/ a' Y) l6 Z  Y: [8、 最后得到的CRC寄存器内容即为:CRC校验码。! s8 O0 r  x' M' D" t: b

( k" ]4 z3 H3 Z0 s8 I1 C3 _$ D二、16位CRC校验程序代码
0 y  J# t( M" ], x1. 计算法

' w& n7 l$ W* _& a' V具体程序如下:  ], z! e2 O8 U

  T% @  s6 S. w9 e  \3 b. d
  1. uint16_t GetModbusCRC16_Cal(uint8_t *data, uint32_t len)//Modbus-CRC校验-----计算法
    + h5 \+ w+ \6 w8 h# H+ m
  2. {& l& L4 `5 K- c" P. w- C
  3.         uint8_t temp;; M$ _  ], M' k1 D% \# [
  4.         uint16_t wcrc = 0XFFFF;//16位crc寄存器预置
    7 p1 t) ~' Y" M# \* u; q) z' n
  5.         uint32_t i = 0, j = 0;//计数3 `! q& I) Y- s: t3 s
  6.         for (i = 0; i < len; i++)//循环计算每个数据, R- K5 c9 [4 t: R1 O$ L4 y7 Y1 T% j
  7.         {" M# O2 S* X0 z0 p# D0 J$ j, c4 |4 j
  8.                 temp = data<i> & 0X00FF;//将八位数据与crc寄存器亦或, C1 E4 F% v( t0 u: M
  9.                 wcrc ^= temp;                                                //将数据存入crc寄存器
    1 B  l+ d- N  {/ G  G$ |
  10.                 for (j = 0; j < 8; j++)        //循环计算数据的
    , r% W: J& U6 y. R* Z
  11.                 {
    ; o1 P- F; v5 i- @1 Q0 H# `6 V
  12.                         if (wcrc & 0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。
    $ s6 u4 Y+ M2 ]7 _
  13.                         {
    + S, f, `4 R6 s: i
  14.                                 wcrc >>= 1;//先将数据右移一位
    ! H' k; ^: x/ z- w1 |$ J$ t: d
  15.                                 wcrc ^= 0XA001;//与上面的多项式进行异或
    1 P" X  X' B1 s) }- Y$ ^' }8 }/ q
  16.                         }
    6 h- K( V/ g9 x& I$ R9 b# q
  17.                         else//如果不是1,则直接移出1 Y: ~( V7 d5 T% j1 E( a  H" H
  18.                         {
    - f5 z) t2 k3 ~0 y# |8 @) g! H; W) m, v
  19.                                 wcrc >>= 1;//直接移出
    ) S# C8 Z0 R- {. E
  20.                         }
    3 e9 `: R1 N) U: I) v- {5 ~1 o
  21.                 }
    , K/ o2 b6 V% p; y
  22.         }
    ; f. f# b  `$ [' e2 o
  23. 1 U  B0 }* l; G0 h9 s
  24.   return ((wcrc << 8)|(wcrc>>8));//高低位置换
    / h& V4 C& T2 E3 c* r% p, U# v0 y
  25. }</i>
复制代码

) A0 i( H" ~9 I2. 查表法
& A0 h- ]  W6 N具体程序如下:1 k  e) d( Z& m' T% z: L1 X; l

# [$ y# n* p0 r( Z* G
  1. uint16_t GetModbusCRC16_Tab(uint8_t *data, uint32_t len)//Modbus-CRC校验-----查表法0 t$ R: `$ m4 w% ^6 b" b
  2. {4 Q9 o7 b+ Z, R
  3.     unsigned int index;
    . r3 O* }6 G4 U
  4.     unsigned char crcH = 0xFF;  //高CRC字节" p% c+ K! ]* V, q
  5.     unsigned char crcL = 0xFF;  //低CRC字节' R8 T, p4 n# ]+ e9 e
  6.     const unsigned char TabH[] = {  //CRC高位字节值表9 a, z. e  ~; o
  7.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  # q  @! C2 [3 `0 `  C4 |: I
  8.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  7 W' h$ L* F- T- f& q
  9.         0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  , p. q' H; e; M: S& Q9 M6 ^
  10.         0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  / T+ z' q3 ]8 ^( J2 J. J* ?6 f
  11.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  , v2 c5 f( b$ Y% W2 l' w
  12.         0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,    l0 u7 d8 _- m" C
  13.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
    3 h! w, H, N* l9 T$ @! m- V
  14.         0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
    & G0 o( v% l0 P  w
  15.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  : d* x* T) r% Y, j2 `  \) _7 M
  16.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
    9 B. _8 Y/ ]# K  ?
  17.         0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
    & C2 K$ C9 A, K5 S, C0 h
  18.         0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  ' k. ]& x# P& ]
  19.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  % }0 K3 |! D: |! I) M' {
  20.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  ; Y& T  U+ j, e. }" W( Q' C
  21.         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  " ]7 G# x( w6 s# b2 D3 w) |% m- I
  22.         0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  
    0 V( ?1 `% E( p; L1 h4 Z
  23.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  + G3 t% Q3 a% W. Q- r" e& ^
  24.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
    " E' P. h7 e/ F
  25.         0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  " ~! }0 R' y: R, r
  26.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
    ; n6 @3 q5 a! o- W0 J, I
  27.         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  4 O, }# \5 ?5 ~# x. _
  28.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  
    7 H; p1 Y7 I- T. U1 I# a: {
  29.         0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  
    . V7 S, _; v4 @) e1 ?: k
  30.         0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  
    / o, y% }+ I4 J
  31.         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  ' f7 u0 H2 S$ a& S7 c
  32.         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  
    / y$ d2 `7 j6 }  S; V( w
  33.     } ;  ; j8 B7 F( H$ S4 {$ x
  34.     const unsigned char TabL[] = {  //CRC低位字节值表
    2 ~0 y6 Q+ X, j" g6 t4 p7 V6 D
  35.         0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  6 c2 `5 |3 B% @
  36.         0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  
    * p% j3 }- r$ u
  37.         0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  2 ^1 N0 k, m* Y9 m8 p  [2 f
  38.         0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  
    & O7 ]* e" y2 y2 _' F, L7 H
  39.         0x1E, 0xDE, 0xDF, 0x1F, 0**, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  
    - B& H- i2 _& ]" K
  40.         0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  2 M/ K. U/ H- R
  41.         0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  & r( r( E- Y% R( O+ q! f6 K, R
  42.         0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  
    : t$ K: B8 T/ K1 b
  43.         0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  
    , |. q$ O7 L  H# R# V6 L+ M& P1 P
  44.         0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  ! ]+ l; |6 Q$ z
  45.         0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  ; F6 q% C' O' H7 M1 K$ B8 f
  46.         0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  
    8 l+ I2 H  s+ z: X
  47.         0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  ! ~3 Y) X3 L; |8 x( O& Y
  48.         0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  " b& J& h9 Y2 V5 `2 K9 }1 Y
  49.         0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  
    ! i* ^, P$ b) n$ `
  50.         0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  
    7 m4 m: _  @" T. |
  51.         0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  7 n3 w( t8 {( f
  52.         0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  / ~. t9 b' U- f4 U. ~' D
  53.         0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  5 V) k! @9 E+ p) D+ f& w
  54.         0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  
    " s9 f8 M0 y) O7 {) l) d( {' L3 G" t
  55.         0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,    K' @  e" q( S0 A: j! u5 n& D
  56.         0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  
    " ?- o- h. x! A3 X+ A
  57.         0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  5 Z/ i5 J; r( q6 N6 \, [& {! f
  58.         0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  
    0 R) z! ^6 z( k; T3 @1 X8 d8 O: |* z
  59.         0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  2 \* M, L. i" N; T7 ?- R3 V
  60.         0x43, 0x83, 0x41, 0x81, 0x80, 0x40  2 A6 ]9 z% j: I! T  }$ H! s
  61.     } ;
    ! ~3 s; j; f: O% v$ Q1 y! s& b
  62.     while (len--)  //计算指定长度的CRC
    6 S" t+ H3 p* T, n& Y
  63.     {
    8 m+ ]+ H/ S! k. |; J4 V  n; E
  64.         index = crcL ^ *data++;
    4 ~/ ^0 w9 d, I6 n( X
  65.         crcL = crcH        ^ TabH[ index];
    ; v% ?) e& V# {, Y" p
  66.         crcH = TabL[ index];
    & y( n, f- Z8 F  u6 v+ |
  67.     }' o& J# h' r/ [; U% S
  68.                 return crcL<<8|crcH;//高低位置换
    ! Z8 M5 v/ }& R
  69. }  
    2 O; y( R+ I& I8 G' i3 n! K5 C

  70. 9 [1 _) S: [9 Q

  71. 6 m6 _1 _' V! i+ N& H

  72. + n; K2 a2 r2 M  n
复制代码
7 E- Y  T% {9 K, w# a- j& n  l
赞 收藏 评论0 发布时间:2022-5-3 15:45

举报

0个回答

所属标签

相似技术帖

官网相关资源

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