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

关于类ModBus协议的例程分享

[复制链接]
cuyebiren 发布时间:2020-8-15 17:25
哎,长久不玩,基本的ADC、Time模块都不会用了。。。, S/ q+ L+ y. E; ~' L6 j( \5 \2 Q
大家应该遇到过类似:头、地址、命令、数据长度、数据、校验 这种格式的协议,比如 刷卡器模块、电表模块、串口屏等基本都是采用这种格式的协议——我称之为类ModBus协议,因为它不是严格的ModBus协议
* z( i2 o+ I. B/ N; x# t1 r" L. C& d, f# C# J9 Y
本例程所用开发板:普中PZ6806L
+ }! Z$ X' K" |6 K9 Q7 t' s# p本例程功能:通过UART控制数码管显示 0~9, h+ w- j, P5 J. L0 Q; U
本例程所用的协议:
1 T0 Q) |# D' W* E. ?% h协议格式:head     address    cmd     length    datas    check
5 g' X7 v1 W2 D" @bytes     :      1           1           1           1          n          1
% [9 x3 e" p! p说明:9 n1 j; R- s* I/ v: g
1、length = datas 的长度,本历程固定为 18 {/ Q0 }* t4 t
2、check  = address、 cmd、length、datas 的异或值& [1 B6 w1 @& }# a2 y" @6 f
3、cmd 取值范围:0,1,2,3, ... 10,
+ j" V8 {/ [0 l$ ~      对应功能分别为:cmd = 0, 显示字符 0、cmd = 1,显示字符 1、。。。cmd = 9,显示字符 9,cmd = 10,循环显示 字符 0~9,间隔500ms
. |$ S6 Y- p$ a( M* Q, J4、datas 字段未使用,可为任意值
, O5 S1 F/ r2 E8 I6 K5、一般接收到报文后,应当返回应答信息,本例程为报文原样返回* C0 n" i& r0 g. Z" X
3 N8 M+ U# O+ H" s4 ~0 q* H
CubeMx配置过程:
9 E! U" ]* m7 L# G; @0 ~配置过程附件里也有

; \: u6 s8 L( D% ^/ \' J 1.JPG 2.JPG 3.JPG 4.JPG 6.JPG
  z4 Z# i4 V' G# |4 r3 d2 V7 ]; c$ D9 H: j! X7 o
5.JPG 7.JPG 8.JPG 9.JPG $ t6 T. M7 z8 W& |% `( r; u" D( S( p
  w$ T4 i4 o8 i* q
3 J/ I$ g+ B7 H) y/ L4 N
编写测试代码:
6 I! l6 v! |$ F: P这里主要说两点:& ?4 u! ?: J" U% Y1 S
1、HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/ l9 ?1 h/ Y4 A 12.JPG
. u3 ^' c" |5 R' f
0 l( a4 K5 R. N0 I& K2 Y- s   我发现,使用HAL库按标准库的方式处理UART通信也是可以的,这里把 Size 设为 1 即可,然后需要在UART回调函数中重复调用此函数;——我没有经过长时间大数据测试,不能保证这样做没有问题。
( Z- J' V/ ~( }6 r  {9 T$ m* e1 l2、善用 状态机。
5 Z3 g& g5 R2 u( y' F& S  个人感觉 C语言 的难点就这4个:结构体、指针、状态机、软件寄存器(位域)4 R; U: Z4 ]6 G: l5 z
  接收状态机:/ p/ t4 ~* Q3 f
   2640509f7e3037aeaa32da80832b1ef.jpg * I( ]  m/ N& F8 y# t$ l' X
  1. switch(uart_rec.state) // 状态机-接收协议处理
    2 `9 U2 o% Y* R0 c) U* C! ^- k
  2. {            // 协议格式: head(1byte)/address(1byte)/cmd(1byte)/length(1byte)/datas(length byte)/check(1byte)
    2 j5 y* ~5 k$ N  G: y
  3. case UART_Idle:
    % Z  N- z9 G7 z
  4.   if (uart_rec_tmp == uart_rec.head) // UART_Idle ==> UART_Head
    : k! Q" E0 \* U
  5.    uart_rec.state = UART_Head;
    * a5 m9 J2 M2 v) k8 i
  6.   break;
    5 J, G8 r! R/ F* i& j+ c
  7. case UART_Head:4 J( ]5 P4 M2 v2 p( k$ T; B
  8.   if (uart_rec_tmp == uart_rec.addr) // UART_Head ==> UART_Addr$ q  ^% a: S/ P( @
  9.    uart_rec.state = UART_Addr;. v. A2 u) c: R
  10.   else if (uart_rec_tmp != uart_rec.head) // UART_Head ==> UART_Idle
    + }  Z& \3 C7 f9 f
  11.    uart_rec.state = UART_Idle;5 n! e6 v+ d" B! J3 i
  12.   break;7 |& Z* j- t6 l
  13. case UART_Addr:
    , g8 _% J/ Z8 J0 V: p) Z) E
  14.   if (isValidCMD(uart_rec_tmp)) // UART_Addr ==> UART_CMD/ C$ K/ d9 C& @: c" `/ T1 X: U
  15.   {
    : a) b2 w' ], [( V( W: C
  16.    uart_rec.cmd = uart_rec_tmp;
    " G8 |! b$ ?. x9 |
  17.    uart_rec.state = UART_CMD;3 w6 B7 o+ V8 e( Z5 q7 J: H, p
  18.   }
    / S7 N. F: g' F$ F; l  O6 s
  19.   else if (uart_rec_tmp == uart_rec.head) // UART_Addr ==> UART_Head. W( w! m. R6 a7 p9 U
  20.    uart_rec.state = UART_Head;7 B) I9 ]6 ]5 {+ ~$ f/ h" C$ c7 @
  21.   else             // UART_Addr ==> UART_Idle. J1 F7 X, @3 x# @" U7 V- [! i1 U
  22.    uart_rec.state = UART_Idle;- H  w9 q' d* A' v1 C
  23.   break;1 a/ N$ h2 m) ^& O# K8 y
  24. case UART_CMD:% G9 J* V- K$ K; X$ U
  25.   if (isValidLen(uart_rec_tmp))
    " p6 v/ j$ t* {& \9 R
  26.   {
    # Z! V2 ?2 y2 G" T* m# h4 Y
  27.    uart_rec.len = uart_rec_tmp;
    ; X& _" @# U( x( I2 A8 c
  28.    uart_rec.cnt = 0;
    7 Z/ Z2 w- @* j' D- c. e$ i
  29.    
    , l1 Y) j* S9 o! x. O5 Q, l
  30.    if (uart_rec_tmp == 0)  // UART_CMD ==> UART_Datas
      X! Y! X, ~. b8 ]" y+ k& M
  31.     uart_rec.state = UART_Datas;
    / N6 s3 F6 g3 r" m: ^
  32.    else           // UART_CMD ==> UART_Len* a$ [: |  N. M& r- d9 F
  33.     uart_rec.state = UART_Len;7 {" x  g+ C" Z% V. q; l7 |7 E' g# D+ k& d
  34.   }
    % g3 |  w, J8 B
  35.   else if (uart_rec_tmp == uart_rec.head) // UART_CMD ==> UART_Head
    . G4 \# G! T. @) P& @0 s
  36.    uart_rec.state = UART_Head;4 i2 k* C* Z7 ~9 w
  37.   else             // UART_CMD ==> UART_Idle# Q5 M8 b, V. u& |. y
  38.    uart_rec.state = UART_Idle;6 H- j- @5 f# R% I* @* U3 t0 R# O- a
  39.   break;; q3 B  l8 Y6 U: P
  40. case UART_Len:7 x( u, v9 R) T& g  ]
  41.   uart_rec.buf[uart_rec.cnt] = uart_rec_tmp;6 D6 ~3 x) M$ M+ v
  42.   uart_rec.cnt++;# H6 [& Q5 {  J+ L$ W) J  C) J
  43.   " f9 |& z) u& N  C2 ?
  44.   if (uart_rec.cnt == uart_rec.len)  // UART_Len ==> UART_Datas
    3 P7 B! v, \. B  k  b
  45.    uart_rec.state = UART_Datas;
    " y4 a6 n. Q" o  g7 }
  46.   break;
    . ~/ d3 k+ m* V0 X* N: A' `
  47. case UART_Datas:$ b3 O% {% M3 ]+ L
  48.   if (uart_rec_tmp == checkUartBuf(&uart_rec)) // UART_Datas ==> UART_Complete
    7 q7 y, V4 \1 {0 _- P  Z  `% X
  49.    uart_rec.state = UART_Complete;. |. W6 v* r7 ^! X# i( r7 Q
  50.   else if (uart_rec_tmp == uart_rec.head) // UART_Datas ==> UART_Head  D7 W  V/ n6 w) Y  u- L0 j8 P
  51.    uart_rec.state = UART_Head;7 t0 x5 R3 q5 w. C* q8 p
  52.   else                // UART_Datas ==> UART_Idle; ?0 O, u' s3 H- ?0 I
  53.    uart_rec.state = UART_Idle;
    $ {  S5 B0 {! \
  54.   break;
    / [) O1 d+ ]& W4 B
  55. case UART_Complete:  // 在 uart_recHandle() 中 UART_Complete ==> UART_Idle
    ! ^0 f9 u# M2 Y4 t3 I3 f: T
  56.   break;# S5 B4 @/ S! B: K
  57. default: uart_rec.state = UART_Idle; break;  P; h5 g1 _/ T$ R
  58. }
      `. f8 }7 V8 Y% L: ^: ], A# A8 w
复制代码
( Y" k2 }* G; X0 j. W- x. H; O
测试:(测试视频请查看附件)* E2 e. n  E  F  k6 [) o! A/ B
13.JPG 6 X. c! q0 D% ?; B0 W+ S2 ~9 f
" j+ G+ }& q/ }& S. n( K0 }* c
3 ^+ h1 r  C8 a& Y9 R
奉上全部工程和文件:- U0 q8 Q7 y( ?" L
modbus_fake.rar (18.69 MB, 下载次数: 72)
2 收藏 2 评论2 发布时间:2020-8-15 17:25

举报

2个回答
mfc4143 回答时间:2020-8-17 08:19:44
赞一个
lee00120 回答时间:2020-10-29 20:50:09
顶一个

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版