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

STM32G0 FreeRTOS和FreeModbus库使用

[复制链接]
STMCU小助手 发布时间:2023-2-22 16:08
1.新建项目

! y& A2 k# Q, G. i* Y/ `
在PIO的Home页面新建项目,项目名称freertos_modbus,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;
  • 项目建立完成后在src目录下新建main.c主程序文件;
  • 修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:
    1 w0 Z( b8 A6 P  Q( T( s
  1. 1upload_protocol = cmsis-dap) `# F) b8 `, }8 S2 _7 X+ }
  2. 2debug_tool = cmsis-dap
复制代码

+ P# d1 z1 A; V8 Q/ _0 z8 B) W& K. s9 `  B
2 编写程序
2.1 添加 freeModbus 库
然后从FreeModbus源码中的 demo\BARE\port中复制文件到工程的src\modbus_port文件夹下,最后的文件夹结构如下:
这里使用RS485,因此需要对RS485使能端口进行配置,其他为串口的配置,然后在发送和接收中断时候调用modbus相关接口进行处理:
/ ?, Q7 [7 }; v% P/ a2 G
  1. 1{
    # W4 W! B# o5 j1 M$ f/ J0 y
  2. 2    "name": "FreeModbus",: g( E9 I! K& Z5 R
  3. 3    "version": "master",+ Y$ q- O5 q$ E# K" Y* V- x  i
  4. 4    "repository":{
    % l2 D$ G1 v2 |+ \# E: `% l0 Q7 k3 m
  5. 5        "type":"git",. N: U9 g/ I* @
  6. 6        "url":"https://github.com/cwalter-at/freemodbus"3 q+ V+ X/ w) h
  7. 7    },7 H! x" _. `! a4 |1 g$ t
  8. 8    "build": {" y8 u5 I' C# R/ G
  9. 9        "flags": [
    $ J# c6 [! D, I, z( t
  10. 10            "-Iascii",8 X) p* E" B% j; M, g0 f* W
  11. 11            "-Ifunctions",
    : N: J+ r5 M7 d* D0 ]6 e7 b9 d
  12. 12            "-Iinclude",/ R' _" T4 y5 l' }
  13. 13            "-Irtu",
    0 s( R* q. `/ I
  14. 14            "-Itcp"/ K5 M4 w' a7 [! f3 W1 e$ ~
  15. 15        ],
    0 S5 x8 g- S8 E8 I' b7 k& C
  16. 16        "srcFilter": [7 N( [# |2 R. L7 v# v& ^7 Z
  17. 17            "+<*>"
    / a4 u3 B# U- \' V7 U- X
  18. 18        ]( @. }3 k$ ?! `
  19. 19    }0 Q/ g4 ^  z7 ~! j* N
  20. 20}
复制代码

& U6 {! a3 S& f6 S0 Q, }$ w8 W
% q  ]% B# Z8 l  V6 Y6 ]
然后从FreeModbus源码中的 demo\BARE\port中复制文件到工程的src\modbus_port文件夹下,最后的文件夹结构如下:& J& o" o5 M- z3 ]

; Y8 |1 Z7 {8 X8 R3 p# y
. o3 ^* w$ U  Y
微信图片_20230222160807.png ) M! w4 t0 h" z' m2 Z1 \! Y' Y! K
" O9 J4 e& ^1 ~" q; ?& l
2.2移植* g5 e5 e: _" b; D8 c* H
portevent:
5 R4 K5 _! ?8 [( R* l7 K9 Q  O
  1. 1/* ----------------------- Modbus includes ----------------------------------*/
    . A& z1 O- V: v
  2. 2#include "mb.h"; {& ^3 E- Z6 W. A4 _: i6 y
  3. 3#include "mbport.h"
    3 f  c& y) u3 S! A
  4. 4#include "FreeRTOS.h"5 {/ ^$ _2 N, C) ^: o4 R/ Y
  5. 5#include "task.h"
    . q- N! Q7 i+ R
  6. 6
    8 a5 _+ d9 J) X8 m- U' Y% n* ^3 N
  7. 7/* ----------------------- Variables ----------------------------------------*/" Y0 S% Z3 C. U$ k- I
  8. 8static eMBEventType eQueuedEvent;; M' @# z% V3 q. G- i% ?/ }
  9. 9static BOOL     xEventInQueue;
    " q( y/ F2 t& s. u3 J& f& F" b
  10. 10static uint32_t modbus_last_active_time = 0;
    2 A+ f+ j( @8 x) l* K8 ?
  11. 11
    , }) H6 \4 i7 Z8 R( ~
  12. 12uint32_t get_modbus_last_active_time(void)
    3 y6 N- W) Q0 W! w4 k' A
  13. 13{
    9 E# C6 m+ ^6 ?" v
  14. 14    return modbus_last_active_time;
    8 ^8 }! J2 a& d7 q" {
  15. 15}9 l; k: @% g, x% {. |  K3 e( F( A
  16. 16
    2 y4 ^$ j; Y$ V5 K' k/ J* p9 x
  17. 17/* ----------------------- Start implementation -----------------------------*/5 V0 d; T, C9 }# i8 z2 g& T
  18. 18BOOL
    ! h# Q. r1 B$ C$ E( [8 L( h2 `( V
  19. 19xMBPortEventInit( void )
    $ [. ^3 P* x! Z  a$ d/ f5 |1 @+ u
  20. 20{# W, a0 V& y& n/ a8 |0 _0 L% j
  21. 21    xEventInQueue = FALSE;/ F& S) D$ P: {3 Z* q, O9 M1 s
  22. 22    return TRUE;4 X- _, ^9 m. O  Y5 u1 H
  23. 23}
    % x3 W% b  l  Y1 @  P. {7 C3 g
  24. 24: Y2 c0 U& R0 `2 L3 G) G
  25. 25BOOL, ^' P' B! H  V- x6 [& Q) u/ _
  26. 26xMBPortEventPost( eMBEventType eEvent )! Z3 \8 W4 {7 f& i0 |
  27. 27{
    0 d! D3 F: b, \1 F4 @2 z9 w
  28. 28    xEventInQueue = TRUE;
    * p* p6 [& }6 X; {8 f
  29. 29    eQueuedEvent = eEvent;
    / k* o% r2 j' o# C1 z& [  X
  30. 30
    " b) l! l. k! O/ r
  31. 31    if (eEvent == EV_EXECUTE) {/ D- r/ [4 I# a7 w
  32. 32        modbus_last_active_time = xTaskGetTickCount();
    5 h, t  M+ z5 I2 ]$ v/ S0 s
  33. 33    }
    " }& }: W- ~& h8 r' x0 O
  34. 34    return TRUE;
    6 O% b$ a: e- ]" u7 J" f' z" a
  35. 35}+ d) z4 g% R* Z9 G3 |. E7 {: B
  36. 36; n( y5 _1 m' i; d; ^) G
  37. 37BOOL
    - z" F5 G  Z- g6 N9 D4 M
  38. 38xMBPortEventGet( eMBEventType * eEvent ). G2 G4 J! q1 n) S
  39. 39{
    . E( [( v' P# k) j) x
  40. 40    BOOL            xEventHappened = FALSE;& \6 F" l: v/ F, L2 N) Z( d
  41. 41& W) w1 n& n" P
  42. 42    if( xEventInQueue )
    ! Q4 K1 z, o5 Y
  43. 43    {
    & J8 }, l$ C: K/ {" q: w
  44. 44        *eEvent = eQueuedEvent;3 @) _/ n9 R# q* I/ k( P  ~
  45. 45        xEventInQueue = FALSE;: i# `$ Q4 U/ r1 N3 `! J
  46. 46        xEventHappened = TRUE;; s$ y! J5 _7 ]% R! n
  47. 47    }
    3 }+ F$ w  H7 z6 i' \
  48. 48    return xEventHappened;
    . ]7 o& {: i# N. {
  49. 49}
复制代码

! S- X9 [2 C" @; c+ ?, G& O  r
portserial2 M9 y+ V& k. ^; M7 J! B, _$ x
这里使用RS485,因此需要对RS485使能端口进行配置,其他为串口的配置,然后在发送和接收中断时候调用modbus相关接口进行处理:
  p7 N0 X2 J9 f2 P5 f

; q+ ^; o# J, V+ S
  1. 1#include "port.h"+ v2 p8 _- y/ X5 K. ^" W4 Z: p
  2.   2
    1 ~. o% _" ^# G
  3.   3#include "FreeRTOS.h"# a7 z2 @( `: Q* g0 M7 p# Q
  4.   4#include "queue.h"; \* k  K: v; U3 _+ h5 o' j
  5.   5
    6 y+ c9 X  V- E5 `* b9 A8 F
  6.   6#include <libopencm3/cm3/nvic.h>7 s# c; ^  T( z
  7.   7#include <libopencm3/stm32/usart.h>
    $ i' C2 R) ]; q
  8.   8#include <libopencm3/stm32/rcc.h>5 G% C9 R5 l4 m. {7 ~
  9.   9#include <libopencm3/stm32/gpio.h>
      d" I7 j4 ]- m" J1 U% `+ v
  10. 10
    - W* o9 ?% B( |+ p' E9 w
  11. 11/* ----------------------- Modbus includes ----------------------------------*/
    ' W0 s1 v  X* i+ |( s0 u) v2 k
  12. 12#include "mb.h"
    " D2 k( r+ i; p1 z) U  m
  13. 13#include "mbport.h"5 ]: a9 f! i& p( M5 K( ]
  14. 14
    / g8 T  e4 H& L" e/ C
  15. 15/* ----------------------- static functions ---------------------------------*/* j8 w- q1 Q6 l
  16. 16
    . Z7 B5 e! d6 g" @" I, @& i
  17. 17xQueueHandle uart_queue;' \  E2 ?* H6 o) Y
  18. 18; ]  `0 o1 u; @9 L$ ~) j( w
  19. 19#define RS485_1_CLOCK        RCC_GPIOB* M. h) M* f/ a$ T  H5 N' \3 ?
  20. 20#define RS485_1_EN_PORT        GPIOB2 F* u' C* [( w7 W$ a
  21. 21#define RS485_1_EN_PIN        GPIO8
      L2 ?4 E8 P4 t: P2 W0 M
  22. 22/ k0 O" ^4 f& u8 ~' S
  23. 23static void rs485_delay(int n)3 X- n1 A  x) i- A" I8 Y
  24. 24{
    9 A: t2 p  W, ]* [
  25. 25    while (--n) {
    4 C$ c9 Y/ r; \0 e0 K3 ~
  26. 26        __asm__ volatile ("nop");0 R9 _. v7 k: B0 G' j
  27. 27    }  Q9 X4 |" R: t; W4 b
  28. 28}/ [! x2 ]; g" j9 g- }7 J
  29. 29* e2 b" I. h  V7 l
  30. 30static inline void rs485_1_rx_mode(void)5 @* T  U  |, W% H+ q
  31. 31{
    ) _' n: ?/ W/ F! n9 N( m
  32. 32    gpio_clear(RS485_1_EN_PORT, RS485_1_EN_PIN);
    * b7 @) {$ A' h
  33. 33}' n5 s8 q7 \2 T) D3 p
  34. 34, o' B# w0 w( H* D( O/ W/ R9 s
  35. 35static inline void rs485_1_tx_mode(void)( N# s, j6 a& T+ O! w* G% U6 U( f# D
  36. 36{, r" X0 S) e, i' o$ C/ N
  37. 37    gpio_set(RS485_1_EN_PORT, RS485_1_EN_PIN);
    / @* G" C! u8 C: R
  38. 38}
    1 k9 b7 g3 w0 r: W! {; H: F( E
  39. 39- G7 D, \! L, V9 a
  40. 40static inline void rs485_gpio_init(void)
    3 }, o9 i7 E! K8 D& x
  41. 41{+ G; S0 t  O% t6 p! m0 X1 o6 F
  42. 42    rcc_periph_clock_enable(RS485_1_CLOCK);1 v" w: B# \0 ?5 ?
  43. 43    gpio_mode_setup(RS485_1_EN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS485_1_EN_PIN);" e# s1 d% O0 [% D& G9 k4 U
  44. 449 G5 U2 v2 p) A
  45. 45    rs485_1_rx_mode();, Y. a1 G9 T8 P: C
  46. 46}4 i) T. e1 ~  f1 S# ^
  47. 475 K* o9 A- e6 O% u4 y" D& T
  48. 48/* ----------------------- Start implementation -----------------------------*/+ O7 l% s# z1 _9 I0 \
  49. 49void
    9 o3 Y& j9 b' m/ M. _
  50. 50vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
      n  e7 U3 M7 r* ~' v; A# f
  51. 51{* t& y0 e: ^2 v& ?) B$ T) r" n) z
  52. 52    /* If xRXEnable enable serial receive interrupts. If xTxENable enable9 n- Z0 S( y- V9 i
  53. 53     * transmitter empty interrupts.
    2 w3 J5 q0 I* K; I+ a
  54. 54     */) O0 l" I0 A1 \' _& z
  55. 55    if (xRxEnable) {& i+ _2 c! E8 k# C+ J8 ]' g, `& _- T! D5 {
  56. 56        rs485_delay(10000);
    5 E5 R" _. B! w, q7 A: b
  57. 57        rs485_1_rx_mode();
    7 B8 y) n! T; G4 ]& u6 M/ ]4 y
  58. 58        rs485_delay(10000);: ?2 B2 t3 B; E; g- J
  59. 59        usart_enable_rx_interrupt(USART1);' D; X3 l) w4 Y: W; L
  60. 60    }% L$ G, N& t( \- `
  61. 61    else {
    ) @# q$ m* G% _; Y2 p4 X
  62. 62        usart_disable_rx_interrupt(USART1);
    " p  v7 B+ V- T$ S, X. t
  63. 63    }; z7 E. d3 ]. @6 ~9 d; ]  S. h/ j9 S
  64. 64
    " s8 o& I9 X9 i
  65. 65    if (xTxEnable) {1 a' Z* P2 P( j/ O1 T) b- h- X+ y
  66. 66        rs485_delay(10000);& e& h! `" ~& D' E  g
  67. 67        rs485_1_tx_mode();0 O0 j' I+ ~3 \
  68. 68        rs485_delay(10000);# c5 |" e1 H! o) s0 y4 W
  69. 69        usart_enable_tx_interrupt(USART1);: ^$ W2 K% q8 {, g1 v$ I
  70. 70    }
    ( m, `7 u# U# {+ a4 J) J) I0 h
  71. 71    else {/ e/ z& Y5 s8 d2 u3 N
  72. 72        usart_disable_tx_interrupt(USART1);3 O3 R1 y& g8 j
  73. 73
    ; e% Q. N2 v9 ^7 \- F
  74. 74    }
    $ ^+ M' [) M% E" ]/ d) n) U) ?
  75. 75}
    + ~8 p3 j0 m- [. S4 J! H1 P) m  x
  76. 76
    3 e& H' D. m  z8 F) Z/ B& ]! G
  77. 77BOOL
    ' ?8 A: I9 I8 f0 c8 `
  78. 78xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
    ' i$ \, l! D+ ^7 s6 N& Y' E+ v6 l
  79. 79{# W# P4 t5 `1 E- u5 }
  80. 80    nvic_enable_irq(NVIC_USART1_IRQ);
    ' U0 |/ C0 O" Z; i- U9 Y
  81. 81
    8 G/ R' e& z" l( ?- i  q
  82. 82    rcc_periph_clock_enable(RCC_GPIOB);
    5 E3 K9 \  B+ v( p
  83. 83    gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6 | GPIO7);
    $ j7 L- u4 j7 ^; W" u8 L$ n( N
  84. 84    gpio_set_af(GPIOB, GPIO_AF0, GPIO6 | GPIO7);& i0 z3 e5 }, s) j/ {6 x
  85. 85! [+ l; @+ L# ~4 ^
  86. 86    rcc_periph_clock_enable(RCC_USART1);
    3 t  f% {8 g' v
  87. 87
      O; ?: g* @' K  M) C/ s2 X
  88. 88    /* Set up USART/UART parameters using the libopencm3 helper functions */* N6 q# @' Y# Z% ~
  89. 89    usart_set_baudrate(USART1, ulBaudRate);
    4 k. H9 i8 O7 l5 Z& n' {. n
  90. 90    usart_set_databits(USART1, ucDataBits);! @: F1 S# @0 \, Z. P
  91. 91    usart_set_stopbits(USART1, USART_STOPBITS_1);5 }. b! D7 P1 a$ E: {) F% P
  92. 92    usart_set_mode(USART1, USART_MODE_TX_RX);- R0 H% Z6 X! g% \0 F
  93. 93! L9 R& d, V) `) x- t8 j/ J
  94. 94    switch (eParity) {
    * m8 x- p& N- N5 d
  95. 95        case MB_PAR_ODD:8 ]- v0 T& M  O0 C) V4 b
  96. 96            usart_set_parity(USART1, USART_PARITY_ODD);+ N/ p7 \  J' k2 d
  97. 97            break;7 q. ?/ Y$ q+ @, T- x
  98. 98        case MB_PAR_EVEN:: o6 y) O/ K; ~$ j  A
  99. 99            usart_set_parity(USART1, USART_PARITY_EVEN);
    ; [$ k+ A) t% `$ k& |" P
  100. 100            break;
    $ u0 E% E+ s7 f% i
  101. 101        default:
    0 A: v4 Z" H1 z
  102. 102            usart_set_parity(USART1, USART_PARITY_NONE);
    7 b5 o: R6 n( t  t5 B
  103. 103            break;6 `( K/ `, L! w" E: ]
  104. 104    }
    " q+ L$ F' ]$ R5 S4 J/ c+ J4 y+ H, w
  105. 105
    ! Z, e  z6 N- V% F
  106. 106    usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);; C+ v( S4 T+ ]
  107. 107
    " _4 V9 j4 {% Q5 C
  108. 108    usart_enable(USART1);
    3 |! p2 c  ?+ W' L
  109. 109/ X  y/ j3 }8 T/ Y
  110. 110    rs485_gpio_init();
    $ A- b# z. W4 o$ t. \2 ]
  111. 111
    1 r( }( M2 F/ h3 [( X* e
  112. 112    return TRUE;  X0 s' j$ G* O
  113. 113}# L' W" r; x& I
  114. 114) p( k, H! a' V
  115. 115BOOL" K# U$ X' J, [
  116. 116xMBPortSerialPutByte( CHAR ucByte ). Y/ @0 h* J: w6 C: L2 ~
  117. 117{
    " E' T: `0 s, G4 a3 _' ]( U8 @8 ?
  118. 1184 s* _; w' q1 m) U& V6 c% t
  119. 119    usart_send_blocking(USART1, (uint16_t) ucByte);    3 w3 u. }3 u! \! b  p
  120. 120/ G. y$ q  ?% U
  121. 121    return TRUE;! e- G7 J7 K9 W: x8 f8 L: u( _
  122. 122}
    1 u* Y, ~/ b* Q6 R
  123. 123
    * K' c  Q* C! G+ c. z% Z
  124. 124BOOL! n( T$ q, N7 s3 Q& P- N
  125. 125xMBPortSerialGetByte( CHAR * pucByte ); l# s. X( S' G( N, n
  126. 126{" J+ m* h! Z( U9 {3 t
  127. 127    *pucByte = usart_recv(USART1);
    ; \' Y4 j' g4 j! ?3 H; ~1 |
  128. 128" m4 P* i* M0 p# Z: C* g9 b
  129. 129    return TRUE;
    # L! ?8 l0 [/ i" w$ o( h" i' a
  130. 130}$ @. W/ X$ `" L2 M
  131. 131" @7 R. _6 o. Q+ _; N% Q0 Z
  132. 132
    5 l9 B8 ]" Y% @$ A
  133. 133uint32_t uart1_isr, uart1_icr;
    $ j' T: c. a) m5 s1 _
  134. 134
    $ N/ A$ c0 ]3 t  ]
  135. 135void usart1_isr(void)
    ! I4 d* x3 r8 I7 E
  136. 136{/ U$ C0 P7 m9 W5 S
  137. 137
    # ]% p; a4 H  m$ N' f: r  n
  138. 138    /* Check if we were called because of RXNE. */
    9 o' v8 L4 k7 k7 d( ~' H/ t' `
  139. 139    if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&  j: t( a# l/ u5 X+ q2 I( D% ?/ Y
  140. 140        ((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {" s" t9 C( E# Q6 L: e8 I
  141. 141
    - K. w8 B' i! O3 s2 Q
  142. 142        /* Retrieve the data from the peripheral. */6 X# v  g& s- g/ t7 i; M$ w
  143. 143        // usart_recv(USART1);) o' z5 Q; G# ^7 C: @  Z. Z
  144. 144
    7 y% z$ O3 u: A* x" w
  145. 145        pxMBFrameCBByteReceived();
    9 N& G% [9 Z3 S( B
  146. 146  n. z1 |$ P' s* {8 \  O) c
  147. 147    }
    : n. f  ]7 L" V' A7 f1 @$ ?, w4 d
  148. 148
    % x  G' S$ R" V0 d0 Q/ V
  149. 1491 x. N& t4 T2 w+ E
  150. 150    /* Check if we were called because of TXE. */
    ) {4 s& u' d; u9 p' X
  151. 151    if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
    + ~/ q7 M( v) ?; a' w
  152. 152        ((USART_ISR(USART1) & USART_ISR_TXE) != 0)) {
    4 ^- a# y7 Y- S4 G7 S& s
  153. 153* j  |5 P8 x' T1 R7 I
  154. 154        /* Put data into the transmit register. */
    . b8 I. U" r4 o4 T1 X0 I0 m
  155. 155        //usart_send(USART1, data);1 _% f8 Z/ O% C3 \
  156. 156) c- ^% P2 s6 x+ I( W2 d
  157. 157        pxMBFrameCBTransmitterEmpty();) S# Q) L6 r$ U! X% }5 I) R
  158. 158% z3 C' |, t" t, i3 R: r5 R/ B
  159. 159    }# w3 e( ^, a- V* V
  160. 1603 x. c( C/ d( X- C, C0 Z
  161. 161}
复制代码
porttimer9 n3 _) P( w  A/ Z. P1 q  ]  t
  1. 1#include "port.h", R$ d# {3 R1 f  i
  2. 2
    # |+ T4 l: i' ]+ u/ A( o3 T
  3. 3#include <libopencm3/cm3/nvic.h>
    1 z/ P) W0 e: u, }1 H$ j2 Z, ?5 I
  4. 4#include <libopencm3/stm32/rcc.h>
    ; ~) K9 z5 M8 Z0 P% J
  5. 5#include <libopencm3/stm32/timer.h>: _( {6 Y; f( m8 d% r# y# e0 Q
  6. 6
    + ]8 v. J- q. D' E
  7. 7/* ----------------------- Modbus includes ----------------------------------*/
    * z) j: p5 O* Z$ e- Z
  8. 8#include "mb.h"0 e. U2 O  J# R" @/ U
  9. 9#include "mbport.h": A' ?  g5 X1 [
  10. 10! k1 c7 j- a8 H; U2 |1 s
  11. 11/* ----------------------- static functions ---------------------------------*/8 a# Z0 |, n4 f, w
  12. 12static void prvvTIMERExpiredISR( void );7 R& ^# F) X* M
  13. 139 z/ O. y  h$ {' X' q2 V- d+ _
  14. 14/* ----------------------- Start implementation -----------------------------*/9 l. X3 g& h% m/ ~0 y9 I" Z
  15. 15BOOL, B% L/ @$ @9 f/ T$ }; {; Q
  16. 16xMBPortTimersInit( USHORT usTim1Timerout50us )
    6 n0 ^1 A  v% m* c
  17. 17{! w$ }! C$ J6 V4 I9 E& U) [! [9 h
  18. 18    rcc_periph_clock_enable(RCC_TIM2);  w, B4 G8 C0 ?5 P1 W
  19. 19    nvic_enable_irq(NVIC_TIM2_IRQ);
    * k* p7 F6 N9 W  z' h( B; q& G
  20. 20    rcc_periph_reset_pulse(RST_TIM2);) u. m0 j% e1 g1 ~0 l, \- H
  21. 21; v! B5 h% w7 r8 f5 k
  22. 22    timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    % l0 G1 e) q1 a6 c
  23. 23: s3 n: |' T7 H# H/ p  I+ }% u
  24. 24    timer_set_prescaler(TIM2, (rcc_apb1_frequency/ 20000));7 O) Y+ {7 e, r0 i
  25. 25% v! O8 z  S: |
  26. 26    timer_disable_preload(TIM2);
    7 N+ m  l- r. U8 W$ h  F* j+ ?
  27. 27    timer_continuous_mode(TIM2);
    5 n9 W+ h! @* T( A2 K! Q- X
  28. 28- w( n' `/ [& r, A: G# G
  29. 29    timer_set_period(TIM2, usTim1Timerout50us);
    $ L& i- c( n/ _. V# _9 r, q1 p
  30. 30    timer_enable_counter(TIM2);
    6 a5 U+ [/ G6 n9 f: V
  31. 314 n4 n: z& c' q6 c
  32. 32    timer_enable_irq(TIM2, TIM_DIER_UIE);
    * r  K7 d, u- K' a$ j4 @
  33. 33+ p2 l3 A/ Q  V* j
  34. 34    return TRUE;; F5 j& v4 {% e: j$ H
  35. 35}
    + s* A$ @+ b/ w: \5 ^
  36. 36
    ( ]$ _2 K9 }( e( d
  37. 37
    ; o. O- G' m  e
  38. 38inline void
    6 _3 ]7 v9 M+ }7 e
  39. 39vMBPortTimersEnable(  )
    / ~' [- M6 L7 n: U( Z
  40. 40{- r! R& E$ T$ _6 F4 c( o  T4 V- H
  41. 41    timer_set_counter(TIM2, 0);
      Q  ^; A9 x9 N7 Y: m+ c9 n6 }0 `
  42. 42    timer_enable_counter(TIM2);
    0 S% k: O7 [6 w" |' j6 S4 T- C
  43. 43}# ^& w' m( [4 G+ J2 E1 [4 L
  44. 440 c3 Z0 T  M/ Y/ Z9 J- M
  45. 45inline void
    1 k+ c8 L) O$ C; w
  46. 46vMBPortTimersDisable(  )
    2 x! a0 _" l1 Z9 G! v
  47. 47{
    + s2 g3 F, v# p" \  ~" ^$ R
  48. 48    timer_disable_counter(TIM2);
    " K+ x, @3 G) v' s
  49. 49}" A9 R! v+ s. `- K! m) B
  50. 50
    2 D5 N1 r6 U5 @, w8 V; O! S
  51. 51/* Create an ISR which is called whenever the timer has expired. This function
    6 S& i0 }% u1 C8 e$ b
  52. 52 * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that" O, k8 e# y4 T& U
  53. 53 * the timer has expired.
    ' `" ~3 k9 p5 H' [
  54. 54 */
    ; N% K/ H8 c& V- l# [
  55. 55static void prvvTIMERExpiredISR( void )
    " ]+ U) j* Q9 b
  56. 56{
    ( H+ n( N7 c, F* R
  57. 57    ( void )pxMBPortCBTimerExpired(  );0 j2 L# A8 h' \2 O
  58. 58}
    ! m: f9 }' q2 P# r- n
  59. 598 s* x/ }( M' j2 E1 k3 i
  60. 60void
    $ j2 e6 [# ^6 H; c( h/ T4 p
  61. 61vMBPortTimersDelay( USHORT usTimeOutMS )! M5 [7 S& a4 B$ C, l
  62. 62{
    , \! b5 u! X/ H+ W; p; P! `
  63. 63    vTaskDelay(pdMS_TO_TICKS(usTimeOutMS));# z9 b7 D+ k' |& `6 P! `- H
  64. 64}# U3 `6 H1 j1 `% c' ?5 r/ b
  65. 658 h' k2 D! r% W+ q" L: H  I
  66. 66void tim2_isr(void)
    ! F, d5 F! W$ G/ X- e$ p# @0 E2 p4 O
  67. 67{+ j( u- T$ p* [+ O' T
  68. 68    if (timer_get_flag(TIM2, TIM_SR_UIF)) {
    8 n0 F1 I2 ^9 x! N5 r$ s
  69. 69
    4 D9 H5 Q# {- Y5 h6 _- D7 {. G
  70. 70        /* Clear compare interrupt flag. */
    - m5 P: K2 K% E: z6 ~" y
  71. 71        timer_clear_flag(TIM2, TIM_SR_UIF);
    " j( d% R0 G, U0 }; W
  72. 72
    ' V8 g: X8 p* ?
  73. 73        prvvTIMERExpiredISR();
    ! |" U& D; B/ W3 k& H) W* o# Q. g
  74. 74
    1 V& D# S/ F) D" a* w. t" t+ K  o
  75. 75    }
    0 K% m' L. l: B5 ^/ C7 A
  76. 76}
复制代码
开启定时器和中断,用于modbus时序控制;  y8 y3 o" p! g+ Q

$ z# x2 B! e- y" l. w
9 ~0 B* P" X+ y
2.2使用
' q5 K  o; l7 S2 x6 a9 M6 A在src目录新建 modbus_cb.h 和 modbus_cb.c 两个文件,实现寄存器、线圈的读写回调:8 b! C. s6 L$ R
  1. 1/// CMD4
    ; U5 b, z) Y9 m+ h. K
  2. 2eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs );
    7 N: P+ y( o) m9 p7 {( E6 z3 _
  3. 3
    6 L5 j; t/ t5 [8 M
  4. 4/// CMD6、3、16, L  W* d0 ?2 L
  5. 5eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode );
    9 X! \5 P' Y( x; w3 G) ~3 s' E
  6. 6
    & B$ d' A$ S& U/ z3 {0 W
  7. 7/// CMD1、5、15
    # m! V  Y' d  z, p" @& [
  8. 8eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode );3 J% v* T7 d, \
  9. 9' G' I9 V& Y+ N% c8 J& w' ?
  10. 10/// CMD4
    5 V& A+ _% }3 |5 c: S& T
  11. 11eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete );
复制代码

! Z% Q- a3 F0 {: ?& T
. V; j& A! S- X9 v1 X! q

* f) t7 k8 h% L' ^) U基本的实现示例如下:+ E0 k$ Z3 R8 h' I
  1.   1#include "modbus_cb.h"3 K7 j) u( B# t) U+ l
  2.   2#include "stdbool.h"
    , E  P2 q2 C3 G% p
  3.   3  M( ?8 K, @9 s3 k5 P
  4.   4extern log(const char* fmt, ...);
    $ ?. d. T- q! a9 N
  5.   5" u% c& n6 c7 i
  6.   6// 输入寄存器
    1 q3 r% h* X9 ?! s/ w' n4 r
  7.   7#define REG_INPUT_SIZE  328 m+ ]$ s9 j! O& y, C3 e) c
  8.   8uint16_t REG_INPUT_BUF[REG_INPUT_SIZE];) T6 _) `3 T0 i7 q
  9.   9
      @% v) I+ i2 f  Z) }0 u
  10. 10// 保持寄存器
    . Q+ {2 v2 @: v$ Q- ^
  11. 11#define REG_HOLD_SIZE   32; J( f% [* {+ o9 [! L. Z
  12. 12uint16_t REG_HOLD_BUF[REG_HOLD_SIZE];2 v9 z* [( Y# t7 `
  13. 13
    . B( U. S/ ]+ t% _$ h
  14. 14// 线圈寄存器
    / s5 z6 g% E4 d8 R1 p% v) I
  15. 15#define REG_COILS_SIZE 16
    9 v% S  ?( |4 P# F
  16. 16uint8_t REG_COILS_BUF[REG_COILS_SIZE];
    - x& K% K8 c3 C2 ]! o! L) p" I+ V
  17. 17
    * ?# N  r5 J7 ~4 X8 |0 i6 O+ W
  18. 18// 离散量
    + |- ~1 a& `7 Q+ y
  19. 19#define REG_DISC_SIZE  8
    0 ]' P+ H. A% g( C. C: y
  20. 20uint8_t REG_DISC_BUF[REG_DISC_SIZE];) K' b+ F9 ]9 Q% D
  21. 21
    ' W$ T/ v9 @5 j& R1 t! g
  22. 22/// CMD4, C  h% }+ I$ Q& I
  23. 23eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
    2 N- s- \$ i% [
  24. 24{/ z+ g. X( B7 K* S1 {4 _
  25. 25    USHORT usRegIndex = usAddress - 1; / Y% K/ G1 b5 u4 h
  26. 26
    , U# [" B1 @5 T1 L  E' Q; K
  27. 27    // 非法检测
    9 _2 Y7 K( }8 i, ^
  28. 28    if((usRegIndex + usNRegs) > REG_INPUT_SIZE)" D4 v' f) d2 ^0 f8 G( E
  29. 29    {
    & C8 H- r! h+ F' t
  30. 30        return MB_ENOREG;
    8 \! [  k7 q, d( m
  31. 31    }) A, J( }: h" [& g. P; D* d9 w: y
  32. 32
    & r+ k% l6 ?% {$ V7 d/ s
  33. 33    log(" CMD4, 寄存器输入.");* D+ ?" z+ X4 ^- f/ V% m0 \8 `
  34. 34: D5 G/ Y0 B7 u2 q1 j5 n
  35. 35    // 填充数据
    , T2 g6 S! K4 }6 `9 v$ w* W6 L% T
  36. 36    REG_INPUT_BUF[0] = 0x01;4 T6 |) o. q/ K1 s" V8 y+ ^
  37. 37    REG_INPUT_BUF[1] = 0x02;
    , ~/ H6 S( x# Z! l, q
  38. 388 G2 D0 Q5 P: Q7 b+ e% X. p! R
  39. 39    // 循环读取
    : L( T) [; z: B* H
  40. 40    while ( usNRegs > 0 ) {8 q( Q0 o( Z2 [7 i& c9 P; j
  41. 41        *pucRegBuffer++ = ( unsigned char )( REG_INPUT_BUF[usRegIndex] >> 8 );
    7 Z" j  {. s$ y" I8 V6 c) r1 k
  42. 42        *pucRegBuffer++ = ( unsigned char )( REG_INPUT_BUF[usRegIndex] & 0xFF );4 g' f; j* f( r3 \- ]- N
  43. 43        usRegIndex++;1 \8 ^0 G+ y5 Z+ }& k: ?9 }
  44. 44        usNRegs--;) Z. J( n# @0 f6 C0 f
  45. 45    }
    3 x( p% E% _; G+ {
  46. 468 L6 e) H7 }( s2 K( b) t
  47. 47    return MB_ENOERR;7 ]( W1 J# m3 X% [
  48. 48}
    1 `  A# }1 `& T& b
  49. 49, Q& {; H* u- v( G; g
  50. 50/// CMD6、3、16
    ! u- p' p: D/ q4 i
  51. 51eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )7 K( i* _# e! C9 Z! Y7 a
  52. 52{
    / L- w6 U7 E: H. \
  53. 53    USHORT usRegIndex = usAddress - 1;  
      r  t+ W: k2 L. n6 A# l( I
  54. 548 c& \* f7 x0 j2 z( p: c
  55. 55    // 非法检测
    % x" d0 N* o' m# }; u2 n
  56. 56    if((usRegIndex + usNRegs) > REG_HOLD_SIZE) {! \' H: }4 W: D# m
  57. 57        return MB_ENOREG;
    9 Q  k% G/ A/ V% S" k$ A) K
  58. 58    }( s' E( h4 e! v, s+ i
  59. 59
    + s2 b8 G( _6 o/ V0 F. u
  60. 60    log(" CMD3,6,16, 保持寄存器读写.");1 F) C8 ?% t& V; f: c: q  b: u
  61. 61
    - r5 o1 g! |- ^
  62. 62    // 写寄存器
    7 P, n  q( @; z' K+ _
  63. 63    if (eMode == MB_REG_WRITE) {" W* q" W5 b3 a! s6 X. t
  64. 64        while ( usNRegs > 0 ) {
    * d% n+ I% d7 c# i( \+ I$ Y
  65. 65            uint16_t value;
    % n1 v5 F9 z& c7 i
  66. 66. F2 S  F+ O; T
  67. 67            value = (pucRegBuffer[0] << 8) | pucRegBuffer[1];/ |8 E, ~$ P& d# e! R& @% c4 Q
  68. 68
    + w7 U( f( ]* p3 W' ]  c) y
  69. 69            log("  写寄存器值:%d", value);9 G0 a% j5 p: n* A
  70. 70
    # D) M$ q' q$ O% P% Q0 P0 x
  71. 71            pucRegBuffer += 2;
    2 s6 _% W1 \3 c! _2 h1 @
  72. 72            usRegIndex++;
    ' v2 S; w/ h9 {
  73. 73            usNRegs--;
    0 f7 d" b6 J* W4 B/ L
  74. 74% i$ F  j2 R( k4 n3 a' _' Z* _4 N
  75. 75        }3 x$ X/ m4 t- y
  76. 76
    0 h3 _, h4 X0 M1 N5 w  P1 V3 C0 u
  77. 77    }
    6 S4 P; m% R, Q( J5 j% g4 t, J' h, n
  78. 78    // 读寄存器
    & l' \/ b1 |4 V8 ]" w4 C5 \6 q
  79. 79    else {8 @' l; d7 i7 ]- L9 ^' W2 p
  80. 800 R: v, y- i% ^* H: Y( a7 z
  81. 81        log("  读寄存器.");& Y- n8 }: N' T( Y
  82. 82
    ! \' r% Y7 H; [) p
  83. 83        REG_HOLD_BUF[0] = 0x32;% S* J+ v7 l' i0 s  I+ ^1 y3 _
  84. 84        REG_HOLD_BUF[1] = 0x33;
    2 ^( ?* k7 N2 V$ \* s
  85. 850 B$ i  |2 C3 [) _* I4 O
  86. 86        while ( usNRegs > 0 ) {
    9 p+ ~' @+ D# T, D9 h0 L, k
  87. 87            *pucRegBuffer++ = ( unsigned char )( REG_HOLD_BUF[usRegIndex] >> 8 );8 N3 g9 K4 i" L% p: I
  88. 88            *pucRegBuffer++ = ( unsigned char )( REG_HOLD_BUF[usRegIndex] & 0xFF );
    ; ?# E7 B' ]$ _8 J. K" i+ T; X* g0 M
  89. 89            usRegIndex++;- }4 B$ a. G% e% C1 ^7 B+ ^& @0 v
  90. 90            usNRegs--;
    / |; G1 o: i# k; j- L  n7 p
  91. 91        }. d, F* H7 U/ ?
  92. 92    }$ \4 p; Q- Z* ]# F  k
  93. 93; _# F5 k1 c  h, X. I
  94. 94    return MB_ENOERR;* o& @+ b' N. x* Y" u. L( A
  95. 95}
    5 A% f  r+ i) G; K' E6 R  Y
  96. 96
    + Q! b- ~3 `) j$ S
  97. 97/// CMD1、5、15
    1 @3 A1 J1 |, U: @; _5 _: l- N* V
  98. 98eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )6 m3 J& B% _7 E7 Z
  99. 99{
    , S9 J  I+ i9 s* _+ V* P* g
  100. 100
    6 U. i1 h3 d" n' l
  101. 101    USHORT usRegIndex   = usAddress - 1;
    & @" H5 i" j1 t. T+ R
  102. 102    USHORT usCoilGroups = ((usNCoils - 1) / 8 + 1);- A. w# J( C' i2 T9 G& H1 b
  103. 103    UCHAR  ucStatus     = 0;
    7 I# `$ n* D% t2 \
  104. 104    UCHAR  ucBits       = 0;% h( k; x, ]: o  h& D/ l/ n' P
  105. 105    UCHAR  ucDisp       = 0;
    * J+ ^& p1 F/ A& g7 R8 j% ~
  106. 106
    6 V, H& N  _; C1 C* P. ^
  107. 107    // 非法检测, _# f! B& z! \, b
  108. 108    if ((usRegIndex + usNCoils) > REG_COILS_SIZE) {
    ) q5 ]. u5 J$ h% q# I! \
  109. 109        return MB_ENOREG;
    $ d) K/ X/ p0 U* h  W' Z/ ?, w& e
  110. 110    }5 X+ M9 ~+ v6 }" ?5 {: @
  111. 1114 R. h% [; N: s, [& w) n% i0 T! E' k5 l8 u
  112. 112    log("  CMD1,5,15, 线圈读写.");6 ?7 b4 ~5 K3 s" X" T
  113. 113
    3 m: }, t: \  w. M
  114. 114    // 写线圈
    + v+ \% l, m) I; W& P  h  ^/ Q7 s9 ^
  115. 115    if (eMode == MB_REG_WRITE) {
    * H2 e3 P' r/ |; B3 a- z
  116. 116& c# q& H1 h/ H' a3 `
  117. 117        while (usCoilGroups--) {8 X5 J3 ]4 j- j$ l! m
  118. 1186 @, Q0 @8 ]; X+ F! R: ?/ o
  119. 119            ucStatus = *pucRegBuffer++;' R, _8 S9 N' `% i+ D# ^; n/ T0 b
  120. 120            ucBits   = 8;: Q' A- J/ z' U  B4 }5 y. a0 {
  121. 1216 n4 N* Z( k7 Z( G
  122. 122            while((usNCoils) != 0 && (ucBits) != 0) {
    " E" _8 {+ B0 g, c2 v- T) r
  123. 123                bool flag = ucStatus & 0x01;2 Y0 ~, H$ ]  r! L1 m
  124. 124
    4 {0 Y7 D# B5 R% F6 ]
  125. 125                switch (usRegIndex) {. z5 x; U# `* W4 v+ s9 w
  126. 126
    ; Z; E% n2 B  r- F+ v
  127. 127                    case 0:) F4 O6 X% i/ |2 K, h
  128. 128                        log(" 线圈0 : %d", flag);//
    . l0 X0 o4 g; c# p- P$ z
  129. 129                    break;* _# G: ^; N, }
  130. 130
    $ \3 }0 A  E% o  D
  131. 131                    case 1:
    % t1 ]+ n* Z( a3 }$ v5 Z* W) l
  132. 132                        log(" 线圈1 : %d", flag);
    % D" d5 q7 m2 M: z
  133. 133                    break;
    . a3 O  {: V1 f  Z6 H
  134. 134
    : v" V& D0 c6 s; b( R3 @
  135. 135                    default:+ B: E9 S; J  ^% g
  136. 136
    0 z7 r! o4 W/ L0 N' Z5 n
  137. 137                    break;
    * N0 A- w/ {& q" C  F
  138. 138+ R1 B9 b% x& @' K& x
  139. 139                }+ ~# G6 K5 ]* c
  140. 140
    ' @4 P0 L* b  O2 H8 [. f. C
  141. 141                usRegIndex++;
    ) h/ Y8 E* C' g' \- h
  142. 142                ucStatus >>= 1;
    6 ^. Q# X  U( k2 s  B$ j4 J
  143. 143                usNCoils--;
    - J+ p# _* k& _0 h  }/ _: N
  144. 144                ucBits--;1 G9 M+ T: |2 Q1 i" C
  145. 145            }/ b* K$ A! J0 `' q5 i/ k- _: S. _
  146. 146
    / }5 b! \1 |, w# Q: P5 x9 r
  147. 147        }
    $ ?* T1 f( L  o$ k4 n7 t
  148. 148    }
    6 o, Z6 u/ e9 {
  149. 149    // 读线圈
    " t& o& l% k) C6 d1 v4 _: n6 j
  150. 150    else {3 r' h4 r' E5 k1 d$ y3 [& i! w
  151. 151
    + Z- g! M! q5 O" I6 i. X
  152. 152        REG_COILS_BUF[0]  = 1;  [. l! i( L; M
  153. 153        REG_COILS_BUF[1]  = 0;% s1 B+ V" ~! N$ `
  154. 154
    7 U$ H/ Z+ ?) q0 J
  155. 155        while (usCoilGroups--) {
    5 p) s; z2 _8 c3 J
  156. 156            ucDisp = 0;; K4 a" C/ U' \
  157. 157            ucBits = 8;
    6 \- T- Z7 S1 A  d; g$ ~
  158. 158            ucStatus = 0;
    6 F6 i: L8 i3 s3 f
  159. 159
    ) o1 {4 q% g1 \' G$ s
  160. 160            while((usNCoils) != 0 && (ucBits) != 0) {) d8 ~. i; t) g
  161. 161                ucStatus |= (REG_COILS_BUF[usRegIndex++] << (ucDisp++));- Y  j5 u& z7 L" Z$ _6 g; ]
  162. 162                usNCoils--;$ O$ r$ a+ }+ ^" Q+ V  D8 u
  163. 163                ucBits--;  |. d- K8 G3 P7 I
  164. 164            }
    5 h  ~0 J# r% [1 `9 N5 b. I
  165. 165
    % ]' r  J' w! j
  166. 166            *pucRegBuffer++ = ucStatus;
    9 G$ S& u! D% Y1 ^- @; N
  167. 167        }$ X3 b, |& S/ ?: F- ^
  168. 168    }+ {- P8 z% \! J8 r7 m
  169. 1695 M2 u/ i9 p5 P! j. B( N
  170. 170    return MB_ENOERR;  R* E; j" d% l9 u& G; L8 J0 I% G6 o
  171. 171}
    - b  c# |+ P1 |+ g4 t! y1 B+ s: d
  172. 172
    $ _" J, S5 I4 _% Z8 _
  173. 173/// CMD48 r: r+ g: E# R: K  _
  174. 174eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
      v$ @4 Y! l, l) H- \
  175. 175{  {3 u1 T; i9 N5 k; a
  176. 176    USHORT usRegIndex   = usAddress - 1;
    8 P9 `; A* {. ]7 v. ~3 b0 K
  177. 177    USHORT usCoilGroups = ((usNDiscrete - 1) / 8 + 1);
    0 g% O  w. H0 l" x
  178. 178    UCHAR  ucStatus     = 0;
    & f, q/ t- ?7 ?. i; c2 N
  179. 179    UCHAR  ucBits       = 0;
      I# `) T$ U8 E, ^7 b
  180. 180    UCHAR  ucDisp       = 0;
    + t4 S9 b2 \  l4 [, ~! k2 f: d) p3 j
  181. 181
    * c( M+ b* \9 x- B# b
  182. 182    // 非法检测
      x3 Y9 z) [4 Z- e# m6 h  b, C& Y
  183. 183    if ((usRegIndex + usNDiscrete) > REG_DISC_SIZE) {
    & U3 R2 F  I1 m, h4 q( k  W" j
  184. 184        return MB_ENOREG;$ M; k. N+ R' {/ P- v6 w
  185. 185    }) Q+ e7 D2 C- m. h: V8 ]
  186. 186
    6 M7 i4 @4 G. A. `  P0 G
  187. 187    log("  CMD4, 离散寄存器写入.");1 \! J5 O( l& ~
  188. 188" x8 P; B. ]* f1 O! Q; S3 l% A
  189. 189    // 读离散输入
    - i" K) c8 \  d4 }3 t
  190. 190    while (usCoilGroups--) {
    & F" d- W" s; l9 ^. c& `
  191. 191        ucDisp = 0;/ U2 `  C$ j% l' c
  192. 192        ucBits = 8;; c& @" x4 P5 N( H7 O7 z
  193. 193        ucStatus = 0;6 ^1 H/ r/ g# B) A! K' @) p7 Q
  194. 1947 \/ d" m5 v6 Y* [! ~
  195. 195        while((usNDiscrete != 0) && (ucBits != 0))
    3 C, r0 B& Q! z" }3 h4 @  T
  196. 196        {8 A0 Q  `) Y& V' w' Y4 J
  197. 197            switch (usRegIndex) {" w+ t0 H9 x" L3 q
  198. 198            case 0:
    & R& {4 z! j. R, P
  199. 199                ucStatus = 0x10;
    ) z2 f3 f) o: r  r; B
  200. 200                break;
    2 N$ j" z6 n  G5 R5 N. X, v% Q7 ]
  201. 201            }: t- K1 D3 w# Z! Z- d' \, G
  202. 202
    % c2 L8 I; n- I$ O# _1 M
  203. 203            usRegIndex++;
    8 A6 ]0 a) U  B( Z+ m8 z
  204. 204            ucDisp++;
    - [- i& _7 G+ k
  205. 205            usNDiscrete--;" m9 H5 ^% S! Q! F% t
  206. 206            ucBits--;& ^9 {& H( E$ D& n& |
  207. 207        }
    3 p1 F+ C: j: B+ M, K
  208. 208        *pucRegBuffer++ = ucStatus;7 b8 L! i" n5 h( B7 K
  209. 209    }
    : R9 R7 `! n  ^: `- y9 T
  210. 210
    9 {/ X6 b2 T0 m7 J) D
  211. 211        return MB_ENOERR;3 X; D; ]! w0 L& v
  212. 212}
复制代码
- ?% Y% g) I: w( ~$ J
在main中创建modbus任务:7 w8 }' O3 [( f" q
  1. 1static void task_modbus_handle(void *param)
    , {, J: C7 V4 j/ M& C
  2. 2{. }0 _+ M# F6 a
  3. 3
    4 P7 u0 ^3 r3 T6 r
  4. 4    eMBErrorCode    eStatus;  w* `# _4 }! ^6 a7 b6 _
  5. 50 D4 Y2 x0 V" a9 _5 m" ^+ w
  6. 6    log("  task modbus start.");
    " N* E+ e1 Q" T* t
  7. 7
    ' z3 ~  C0 ]) R5 w' R( r" n
  8. 8    eStatus = eMBInit( MB_RTU, 0x01, 0, 9600, MB_PAR_NONE );
    % K3 m5 \" T- @
  9. 9- d/ T9 V4 {/ K5 z$ ~/ @9 I5 `, O
  10. 10    /* Enable the Modbus Protocol Stack. */9 F3 D+ Y$ C$ m" j! ~3 K* N
  11. 11    eStatus = eMBEnable();2 T. T- K$ I' o" R9 K
  12. 12& g+ n5 A" \' V
  13. 13    (void)eStatus;
    $ [. Y- ~' d7 a' B  x. ^8 R% B; z
  14. 14) g% {  h  W5 o+ R, s' r( V
  15. 15    for( ;; ) {
    3 s; S* A( n/ d$ z  q8 c
  16. 16        ( void )eMBPoll();
    + Y; |8 Q+ {- T" F( y+ Q
  17. 17        vTaskDelay(pdMS_TO_TICKS(10));2 [6 r: ?8 t4 D7 c5 x' K
  18. 18    }
    - u4 B# C0 Z$ A. q6 T# Y# S! }
  19. 19
    ' W: \: V' A' b3 D
  20. 20}
复制代码
: x$ K  P( p2 V5 W9 y$ n/ L/ u

2 s. @1 P1 [, d; e  Q3 烧写测试* T: w9 F  _6 Z: ~7 r
将开发板连接到USB转485模块,然后使用modbus poll程序进行测试:; D) P( B& e( X1 c9 |* ?0 w. I6 d

8 E& M& J* H8 Z0 N" B
微信图片_20230222160741.png

7 y" Q3 a, V& T" y7 ^
转载自: MakerInChina.cn
$ n9 {. b- K' q1 |

2 k" p1 O: j. R. T! E+ R7 \8 B% b2 Z/ i5 u4 o
赞 收藏 评论0 发布时间:2023-2-22 16:08

举报

0个回答

所属标签

相似技术帖

官网相关资源

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