├── Inc
├── main.h
├── stm32f1xx_hal_conf.h
└── stm32f1xx_it.h
├── README.md
├── Src
├── main.c
├── stm32f1xx_hal_msp.c
├── stm32f1xx_it.c
└── system_stm32f1xx.c
└── modbus
├── ascii
├── mbascii.c
└── mbascii.h
├── functions
├── mbfunccoils.c
├── mbfuncdiag.c
├── mbfuncdisc.c
├── mbfuncholding.c
├── mbfuncinput.c
├── mbfuncother.c
└── mbutils.c
├── include
├── mb.h
├── mbconfig.h
├── mbframe.h
├── mbfunc.h
├── mbport.h
├── mbproto.h
└── mbutils.h
├── mb.c
├── port
├── assert.h
├── port.c
├── port.h
├── portevent.c
├── portserial.c
└── porttimer.c
├── rtu
├── mbcrc.c
├── mbcrc.h
├── mbrtu.c
└── mbrtu.h
└── tcp
├── mbtcp.c
└── mbtcp.h
/Inc/main.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file : main.h
4 | * @brief : Header for main.c file.
5 | * This file contains the common defines of the application.
6 | ******************************************************************************
7 | ** This notice applies to any and all portions of this file
8 | * that are not between comment pairs USER CODE BEGIN and
9 | * USER CODE END. Other portions of this file, whether
10 | * inserted by the user or by software development tools
11 | * are owned by their respective copyright owners.
12 | *
13 | * COPYRIGHT(c) 2018 STMicroelectronics
14 | *
15 | * Redistribution and use in source and binary forms, with or without modification,
16 | * are permitted provided that the following conditions are met:
17 | * 1. Redistributions of source code must retain the above copyright notice,
18 | * this list of conditions and the following disclaimer.
19 | * 2. Redistributions in binary form must reproduce the above copyright notice,
20 | * this list of conditions and the following disclaimer in the documentation
21 | * and/or other materials provided with the distribution.
22 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
23 | * may be used to endorse or promote products derived from this software
24 | * without specific prior written permission.
25 | *
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 | *
37 | ******************************************************************************
38 | */
39 |
40 | /* Define to prevent recursive inclusion -------------------------------------*/
41 | #ifndef __MAIN_H__
42 | #define __MAIN_H__
43 |
44 | /* Includes ------------------------------------------------------------------*/
45 |
46 | /* USER CODE BEGIN Includes */
47 |
48 | /* USER CODE END Includes */
49 |
50 | /* Private define ------------------------------------------------------------*/
51 |
52 | #define SPI1_ADC_CS_Pin GPIO_PIN_3
53 | #define SPI1_ADC_CS_GPIO_Port GPIOA
54 | #define USART1_DIR_Pin GPIO_PIN_11
55 | #define USART1_DIR_GPIO_Port GPIOA
56 | #define LED1_Pin GPIO_PIN_8
57 | #define LED1_GPIO_Port GPIOB
58 |
59 | /* ########################## Assert Selection ############################## */
60 | /**
61 | * @brief Uncomment the line below to expanse the "assert_param" macro in the
62 | * HAL drivers code
63 | */
64 | /* #define USE_FULL_ASSERT 1U */
65 |
66 | /* USER CODE BEGIN Private defines */
67 |
68 | /* USER CODE END Private defines */
69 |
70 | #ifdef __cplusplus
71 | extern "C" {
72 | #endif
73 | void _Error_Handler(char *, int);
74 |
75 | #define Error_Handler() _Error_Handler(__FILE__, __LINE__)
76 | #ifdef __cplusplus
77 | }
78 | #endif
79 |
80 | #endif /* __MAIN_H__ */
81 |
82 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
83 |
--------------------------------------------------------------------------------
/Inc/stm32f1xx_hal_conf.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file stm32f1xx_hal_conf.h
4 | * @brief HAL configuration file.
5 | ******************************************************************************
6 | * @attention
7 | *
8 | *
© COPYRIGHT(c) 2018 STMicroelectronics
9 | *
10 | * Redistribution and use in source and binary forms, with or without modification,
11 | * are permitted provided that the following conditions are met:
12 | * 1. Redistributions of source code must retain the above copyright notice,
13 | * this list of conditions and the following disclaimer.
14 | * 2. Redistributions in binary form must reproduce the above copyright notice,
15 | * this list of conditions and the following disclaimer in the documentation
16 | * and/or other materials provided with the distribution.
17 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
18 | * may be used to endorse or promote products derived from this software
19 | * without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | *
32 | ******************************************************************************
33 | */
34 |
35 | /* Define to prevent recursive inclusion -------------------------------------*/
36 | #ifndef __STM32F1xx_HAL_CONF_H
37 | #define __STM32F1xx_HAL_CONF_H
38 |
39 | #ifdef __cplusplus
40 | extern "C" {
41 | #endif
42 |
43 | #include "main.h"
44 | /* Exported types ------------------------------------------------------------*/
45 | /* Exported constants --------------------------------------------------------*/
46 |
47 | /* ########################## Module Selection ############################## */
48 | /**
49 | * @brief This is the list of modules to be used in the HAL driver
50 | */
51 |
52 | #define HAL_MODULE_ENABLED
53 | /*#define HAL_ADC_MODULE_ENABLED */
54 | /*#define HAL_CRYP_MODULE_ENABLED */
55 | /*#define HAL_CAN_MODULE_ENABLED */
56 | /*#define HAL_CEC_MODULE_ENABLED */
57 | /*#define HAL_CORTEX_MODULE_ENABLED */
58 | /*#define HAL_CRC_MODULE_ENABLED */
59 | /*#define HAL_DAC_MODULE_ENABLED */
60 | #define HAL_DMA_MODULE_ENABLED
61 | /*#define HAL_ETH_MODULE_ENABLED */
62 | /*#define HAL_FLASH_MODULE_ENABLED */
63 | #define HAL_GPIO_MODULE_ENABLED
64 | /*#define HAL_I2C_MODULE_ENABLED */
65 | /*#define HAL_I2S_MODULE_ENABLED */
66 | /*#define HAL_IRDA_MODULE_ENABLED */
67 | /*#define HAL_IWDG_MODULE_ENABLED */
68 | /*#define HAL_NOR_MODULE_ENABLED */
69 | /*#define HAL_NAND_MODULE_ENABLED */
70 | /*#define HAL_PCCARD_MODULE_ENABLED */
71 | /*#define HAL_PCD_MODULE_ENABLED */
72 | /*#define HAL_HCD_MODULE_ENABLED */
73 | /*#define HAL_PWR_MODULE_ENABLED */
74 | /*#define HAL_RCC_MODULE_ENABLED */
75 | /*#define HAL_RTC_MODULE_ENABLED */
76 | /*#define HAL_SD_MODULE_ENABLED */
77 | /*#define HAL_MMC_MODULE_ENABLED */
78 | /*#define HAL_SDRAM_MODULE_ENABLED */
79 | /*#define HAL_SMARTCARD_MODULE_ENABLED */
80 | #define HAL_SPI_MODULE_ENABLED
81 | /*#define HAL_SRAM_MODULE_ENABLED */
82 | #define HAL_TIM_MODULE_ENABLED
83 | #define HAL_UART_MODULE_ENABLED
84 | /*#define HAL_USART_MODULE_ENABLED */
85 | /*#define HAL_WWDG_MODULE_ENABLED */
86 |
87 | #define HAL_CORTEX_MODULE_ENABLED
88 | #define HAL_DMA_MODULE_ENABLED
89 | #define HAL_FLASH_MODULE_ENABLED
90 | #define HAL_GPIO_MODULE_ENABLED
91 | #define HAL_PWR_MODULE_ENABLED
92 | #define HAL_RCC_MODULE_ENABLED
93 |
94 | /* ########################## Oscillator Values adaptation ####################*/
95 | /**
96 | * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
97 | * This value is used by the RCC HAL module to compute the system frequency
98 | * (when HSE is used as system clock source, directly or through the PLL).
99 | */
100 | #if !defined (HSE_VALUE)
101 | #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
102 | #endif /* HSE_VALUE */
103 |
104 | #if !defined (HSE_STARTUP_TIMEOUT)
105 | #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
106 | #endif /* HSE_STARTUP_TIMEOUT */
107 |
108 | /**
109 | * @brief Internal High Speed oscillator (HSI) value.
110 | * This value is used by the RCC HAL module to compute the system frequency
111 | * (when HSI is used as system clock source, directly or through the PLL).
112 | */
113 | #if !defined (HSI_VALUE)
114 | #define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/
115 | #endif /* HSI_VALUE */
116 |
117 | /**
118 | * @brief Internal Low Speed oscillator (LSI) value.
119 | */
120 | #if !defined (LSI_VALUE)
121 | #define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */
122 | #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
123 | The real value may vary depending on the variations
124 | in voltage and temperature. */
125 |
126 | /**
127 | * @brief External Low Speed oscillator (LSE) value.
128 | * This value is used by the UART, RTC HAL module to compute the system frequency
129 | */
130 | #if !defined (LSE_VALUE)
131 | #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
132 | #endif /* LSE_VALUE */
133 |
134 | #if !defined (LSE_STARTUP_TIMEOUT)
135 | #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
136 | #endif /* LSE_STARTUP_TIMEOUT */
137 |
138 | /* Tip: To avoid modifying this file each time you need to use different HSE,
139 | === you can define the HSE value in your toolchain compiler preprocessor. */
140 |
141 | /* ########################### System Configuration ######################### */
142 | /**
143 | * @brief This is the HAL system configuration section
144 | */
145 | #define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
146 | #define TICK_INT_PRIORITY ((uint32_t)0) /*!< tick interrupt priority (lowest by default) */
147 | #define USE_RTOS 0
148 | #define PREFETCH_ENABLE 1
149 |
150 | /* ########################## Assert Selection ############################## */
151 | /**
152 | * @brief Uncomment the line below to expanse the "assert_param" macro in the
153 | * HAL drivers code
154 | */
155 | /* #define USE_FULL_ASSERT 1U */
156 |
157 | /* ################## Ethernet peripheral configuration ##################### */
158 |
159 | /* Section 1 : Ethernet peripheral configuration */
160 |
161 | /* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
162 | #define MAC_ADDR0 2
163 | #define MAC_ADDR1 0
164 | #define MAC_ADDR2 0
165 | #define MAC_ADDR3 0
166 | #define MAC_ADDR4 0
167 | #define MAC_ADDR5 0
168 |
169 | /* Definition of the Ethernet driver buffers size and count */
170 | #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
171 | #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
172 | #define ETH_RXBUFNB ((uint32_t)8) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
173 | #define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
174 |
175 | /* Section 2: PHY configuration section */
176 |
177 | /* DP83848_PHY_ADDRESS Address*/
178 | #define DP83848_PHY_ADDRESS 0x01U
179 | /* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
180 | #define PHY_RESET_DELAY ((uint32_t)0x000000FF)
181 | /* PHY Configuration delay */
182 | #define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF)
183 |
184 | #define PHY_READ_TO ((uint32_t)0x0000FFFF)
185 | #define PHY_WRITE_TO ((uint32_t)0x0000FFFF)
186 |
187 | /* Section 3: Common PHY Registers */
188 |
189 | #define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */
190 | #define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */
191 |
192 | #define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */
193 | #define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */
194 | #define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */
195 | #define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */
196 | #define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */
197 | #define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */
198 | #define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */
199 | #define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */
200 | #define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */
201 | #define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */
202 |
203 | #define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
204 | #define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */
205 | #define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */
206 |
207 | /* Section 4: Extended PHY Registers */
208 | #define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
209 |
210 | #define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
211 | #define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
212 |
213 | /* Includes ------------------------------------------------------------------*/
214 | /**
215 | * @brief Include module's header file
216 | */
217 |
218 | #ifdef HAL_RCC_MODULE_ENABLED
219 | #include "stm32f1xx_hal_rcc.h"
220 | #endif /* HAL_RCC_MODULE_ENABLED */
221 |
222 | #ifdef HAL_GPIO_MODULE_ENABLED
223 | #include "stm32f1xx_hal_gpio.h"
224 | #endif /* HAL_GPIO_MODULE_ENABLED */
225 |
226 | #ifdef HAL_DMA_MODULE_ENABLED
227 | #include "stm32f1xx_hal_dma.h"
228 | #endif /* HAL_DMA_MODULE_ENABLED */
229 |
230 | #ifdef HAL_ETH_MODULE_ENABLED
231 | #include "stm32f1xx_hal_eth.h"
232 | #endif /* HAL_ETH_MODULE_ENABLED */
233 |
234 | #ifdef HAL_CAN_MODULE_ENABLED
235 | #include "stm32f1xx_hal_can.h"
236 | #endif /* HAL_CAN_MODULE_ENABLED */
237 |
238 | #ifdef HAL_CEC_MODULE_ENABLED
239 | #include "stm32f1xx_hal_cec.h"
240 | #endif /* HAL_CEC_MODULE_ENABLED */
241 |
242 | #ifdef HAL_CORTEX_MODULE_ENABLED
243 | #include "stm32f1xx_hal_cortex.h"
244 | #endif /* HAL_CORTEX_MODULE_ENABLED */
245 |
246 | #ifdef HAL_ADC_MODULE_ENABLED
247 | #include "stm32f1xx_hal_adc.h"
248 | #endif /* HAL_ADC_MODULE_ENABLED */
249 |
250 | #ifdef HAL_CRC_MODULE_ENABLED
251 | #include "stm32f1xx_hal_crc.h"
252 | #endif /* HAL_CRC_MODULE_ENABLED */
253 |
254 | #ifdef HAL_DAC_MODULE_ENABLED
255 | #include "stm32f1xx_hal_dac.h"
256 | #endif /* HAL_DAC_MODULE_ENABLED */
257 |
258 | #ifdef HAL_FLASH_MODULE_ENABLED
259 | #include "stm32f1xx_hal_flash.h"
260 | #endif /* HAL_FLASH_MODULE_ENABLED */
261 |
262 | #ifdef HAL_SRAM_MODULE_ENABLED
263 | #include "stm32f1xx_hal_sram.h"
264 | #endif /* HAL_SRAM_MODULE_ENABLED */
265 |
266 | #ifdef HAL_NOR_MODULE_ENABLED
267 | #include "stm32f1xx_hal_nor.h"
268 | #endif /* HAL_NOR_MODULE_ENABLED */
269 |
270 | #ifdef HAL_I2C_MODULE_ENABLED
271 | #include "stm32f1xx_hal_i2c.h"
272 | #endif /* HAL_I2C_MODULE_ENABLED */
273 |
274 | #ifdef HAL_I2S_MODULE_ENABLED
275 | #include "stm32f1xx_hal_i2s.h"
276 | #endif /* HAL_I2S_MODULE_ENABLED */
277 |
278 | #ifdef HAL_IWDG_MODULE_ENABLED
279 | #include "stm32f1xx_hal_iwdg.h"
280 | #endif /* HAL_IWDG_MODULE_ENABLED */
281 |
282 | #ifdef HAL_PWR_MODULE_ENABLED
283 | #include "stm32f1xx_hal_pwr.h"
284 | #endif /* HAL_PWR_MODULE_ENABLED */
285 |
286 | #ifdef HAL_RTC_MODULE_ENABLED
287 | #include "stm32f1xx_hal_rtc.h"
288 | #endif /* HAL_RTC_MODULE_ENABLED */
289 |
290 | #ifdef HAL_PCCARD_MODULE_ENABLED
291 | #include "stm32f1xx_hal_pccard.h"
292 | #endif /* HAL_PCCARD_MODULE_ENABLED */
293 |
294 | #ifdef HAL_SD_MODULE_ENABLED
295 | #include "stm32f1xx_hal_sd.h"
296 | #endif /* HAL_SD_MODULE_ENABLED */
297 |
298 | #ifdef HAL_MMC_MODULE_ENABLED
299 | #include "stm32f1xx_hal_mmc.h"
300 | #endif /* HAL_MMC_MODULE_ENABLED */
301 |
302 | #ifdef HAL_NAND_MODULE_ENABLED
303 | #include "stm32f1xx_hal_nand.h"
304 | #endif /* HAL_NAND_MODULE_ENABLED */
305 |
306 | #ifdef HAL_SPI_MODULE_ENABLED
307 | #include "stm32f1xx_hal_spi.h"
308 | #endif /* HAL_SPI_MODULE_ENABLED */
309 |
310 | #ifdef HAL_TIM_MODULE_ENABLED
311 | #include "stm32f1xx_hal_tim.h"
312 | #endif /* HAL_TIM_MODULE_ENABLED */
313 |
314 | #ifdef HAL_UART_MODULE_ENABLED
315 | #include "stm32f1xx_hal_uart.h"
316 | #endif /* HAL_UART_MODULE_ENABLED */
317 |
318 | #ifdef HAL_USART_MODULE_ENABLED
319 | #include "stm32f1xx_hal_usart.h"
320 | #endif /* HAL_USART_MODULE_ENABLED */
321 |
322 | #ifdef HAL_IRDA_MODULE_ENABLED
323 | #include "stm32f1xx_hal_irda.h"
324 | #endif /* HAL_IRDA_MODULE_ENABLED */
325 |
326 | #ifdef HAL_SMARTCARD_MODULE_ENABLED
327 | #include "stm32f1xx_hal_smartcard.h"
328 | #endif /* HAL_SMARTCARD_MODULE_ENABLED */
329 |
330 | #ifdef HAL_WWDG_MODULE_ENABLED
331 | #include "stm32f1xx_hal_wwdg.h"
332 | #endif /* HAL_WWDG_MODULE_ENABLED */
333 |
334 | #ifdef HAL_PCD_MODULE_ENABLED
335 | #include "stm32f1xx_hal_pcd.h"
336 | #endif /* HAL_PCD_MODULE_ENABLED */
337 |
338 | #ifdef HAL_HCD_MODULE_ENABLED
339 | #include "stm32f1xx_hal_hcd.h"
340 | #endif /* HAL_HCD_MODULE_ENABLED */
341 |
342 |
343 | /* Exported macro ------------------------------------------------------------*/
344 | #ifdef USE_FULL_ASSERT
345 | /**
346 | * @brief The assert_param macro is used for function's parameters check.
347 | * @param expr: If expr is false, it calls assert_failed function
348 | * which reports the name of the source file and the source
349 | * line number of the call that failed.
350 | * If expr is true, it returns no value.
351 | * @retval None
352 | */
353 | #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
354 | /* Exported functions ------------------------------------------------------- */
355 | void assert_failed(uint8_t* file, uint32_t line);
356 | #else
357 | #define assert_param(expr) ((void)0U)
358 | #endif /* USE_FULL_ASSERT */
359 |
360 | #ifdef __cplusplus
361 | }
362 | #endif
363 |
364 | #endif /* __STM32F1xx_HAL_CONF_H */
365 |
366 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
367 |
--------------------------------------------------------------------------------
/Inc/stm32f1xx_it.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file stm32f1xx_it.h
4 | * @brief This file contains the headers of the interrupt handlers.
5 | ******************************************************************************
6 | *
7 | * COPYRIGHT(c) 2018 STMicroelectronics
8 | *
9 | * Redistribution and use in source and binary forms, with or without modification,
10 | * are permitted provided that the following conditions are met:
11 | * 1. Redistributions of source code must retain the above copyright notice,
12 | * this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
17 | * may be used to endorse or promote products derived from this software
18 | * without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | ******************************************************************************
32 | */
33 |
34 | /* Define to prevent recursive inclusion -------------------------------------*/
35 | #ifndef __STM32F1xx_IT_H
36 | #define __STM32F1xx_IT_H
37 |
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 |
42 | /* Includes ------------------------------------------------------------------*/
43 | #include "stm32f1xx_hal.h"
44 | #include "main.h"
45 | /* Exported types ------------------------------------------------------------*/
46 | /* Exported constants --------------------------------------------------------*/
47 | /* Exported macro ------------------------------------------------------------*/
48 | /* Exported functions ------------------------------------------------------- */
49 |
50 | void NMI_Handler(void);
51 | void HardFault_Handler(void);
52 | void MemManage_Handler(void);
53 | void BusFault_Handler(void);
54 | void UsageFault_Handler(void);
55 | void SVC_Handler(void);
56 | void DebugMon_Handler(void);
57 | void PendSV_Handler(void);
58 | void SysTick_Handler(void);
59 | void DMA1_Channel4_IRQHandler(void);
60 | void TIM1_CC_IRQHandler(void);
61 | void USART1_IRQHandler(void);
62 |
63 | #ifdef __cplusplus
64 | }
65 | #endif
66 |
67 | #endif /* __STM32F1xx_IT_H */
68 |
69 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Reliable DMA implementation of Modbus (library FreeModbus with STM32, Keil 5)
2 |
3 | `#modbus #reliable #high-rate-modbus #serial_DMA`
4 |
5 | DMA based free Modbus implementation and port to newest stm32cube software.
6 |
7 | This design works on the half-duplex EIA-485 interface.
8 |
9 | Modbus has an important role in many industrial applications. In this work, we concentrate on implementation issues that occurred when porting such library to a new microcontroller.
10 |
11 | This code has these **benefits**:
12 |
13 | 1. porting to a known library
14 | 2. **DMA implementation of serial** reduce the overhead in high data-rate
15 | 3. ***High reliability due to interrupt reduction***
16 | 4. using the last version of the STM32 support package for implementation
17 |
18 | DMA implementation of such application meets higher baud-rate in the communication link. many known implementation uses interrupt. Interrupt reduction has a big influence on the reliability of code. DMA as a section of hardware reduces interrupt overhead extremely.
19 |
20 | One interrupt will be used in last version, that is occurred when a packet is not complete or with a nested packet.
21 |
22 | version 1: in this version DMA just transfer TX data
23 |
24 | version 2: (coming soon) RX , TX with DMA
25 |
--------------------------------------------------------------------------------
/Src/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file : main.c
4 | * @brief : Main program body
5 | ******************************************************************************
6 | ** This notice applies to any and all portions of this file
7 | * that are not between comment pairs USER CODE BEGIN and
8 | * USER CODE END. Other portions of this file, whether
9 | * inserted by the user or by software development tools
10 | * are owned by their respective copyright owners.
11 | *
12 | * COPYRIGHT(c) 2018 STMicroelectronics
13 | *
14 | * Redistribution and use in source and binary forms, with or without modification,
15 | * are permitted provided that the following conditions are met:
16 | * 1. Redistributions of source code must retain the above copyright notice,
17 | * this list of conditions and the following disclaimer.
18 | * 2. Redistributions in binary form must reproduce the above copyright notice,
19 | * this list of conditions and the following disclaimer in the documentation
20 | * and/or other materials provided with the distribution.
21 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
22 | * may be used to endorse or promote products derived from this software
23 | * without specific prior written permission.
24 | *
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 | *
36 | ******************************************************************************
37 | */
38 | /* Includes ------------------------------------------------------------------*/
39 | #include "main.h"
40 | #include "stm32f1xx_hal.h"
41 |
42 | /* USER CODE BEGIN Includes */
43 | #include "mb.h"
44 | #include "mbport.h"
45 | #include "port.h"
46 | /* USER CODE END Includes */
47 |
48 | /* Private variables ---------------------------------------------------------*/
49 | SPI_HandleTypeDef hspi1;
50 | TIM_HandleTypeDef htim1;
51 | UART_HandleTypeDef huart1;
52 | DMA_HandleTypeDef hdma_usart1_tx;
53 |
54 | /* USER CODE BEGIN PV */
55 | /* Private variables ---------------------------------------------------------*/
56 | /* ----------------------- Defines ------------------------------------------*/
57 |
58 |
59 |
60 | /* ----------------------- Static variables ---------------------------------*/
61 | volatile USHORT usRegInputStart = REG_INPUT_START;
62 | volatile USHORT usRegInputBuf[REG_INPUT_NREGS];
63 | volatile USHORT usRegHoldingStart = REG_HOLDING_START;
64 | volatile USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
65 | static USHORT temp;
66 | volatile uint32_t TimingDelay;
67 | //#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
68 | /* USER CODE END PV */
69 |
70 | /* Private function prototypes -----------------------------------------------*/
71 | void SystemClock_Config(void);
72 | static void MX_GPIO_Init(void);
73 | static void MX_DMA_Init(void);
74 | static void MX_USART1_UART_Init(void);
75 | static void MX_SPI1_Init(void);
76 | static void MX_TIM1_Init(void);
77 |
78 | /* USER CODE BEGIN PFP */
79 | /* Private function prototypes -----------------------------------------------*/
80 | /* USER CODE END PFP */
81 |
82 | /* USER CODE BEGIN 0 */
83 |
84 | /* USER CODE END 0 */
85 |
86 | /**
87 | * @brief The application entry point.
88 | *
89 | * @retval None
90 | */
91 | int main(void)
92 | {
93 | /* USER CODE BEGIN 1 */
94 | static uint16_t counter_test = 0;
95 | /* USER CODE END 1 */
96 |
97 | /* MCU Configuration----------------------------------------------------------*/
98 |
99 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
100 | HAL_Init();
101 |
102 | /* USER CODE BEGIN Init */
103 |
104 | /* USER CODE END Init */
105 |
106 | /* Configure the system clock */
107 | SystemClock_Config();
108 |
109 | /* USER CODE BEGIN SysInit */
110 |
111 | /* USER CODE END SysInit */
112 |
113 | /* Initialize all configured peripherals */
114 | MX_GPIO_Init();
115 | MX_DMA_Init();
116 | MX_USART1_UART_Init();
117 | MX_SPI1_Init();
118 | MX_TIM1_Init();
119 | /* USER CODE BEGIN 2 */
120 |
121 | /*delay for best performance*/
122 | HAL_Delay(1000);
123 |
124 | //printf("\n\rUSART1 IS READY!\n\r");
125 | eMBInit(MB_RTU, 0x01, 1, 115200, MB_PAR_NONE);
126 | eMBEnable();
127 |
128 | /* USER CODE END 2 */
129 |
130 | /* Infinite loop */
131 | /* USER CODE BEGIN WHILE */
132 | while (1)
133 | {
134 | /* USER CODE END WHILE */
135 |
136 | /* USER CODE BEGIN 3 */
137 | counter_test++;
138 | usRegInputBuf[2] = counter_test; /*change buffer 1 input register modbus to a test counter*/
139 | HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); /*change led state*/
140 | eMBPoll(); /*Modbus poll update in each run*/
141 | }
142 | /* USER CODE END 3 */
143 |
144 | }
145 |
146 | /**
147 | * @brief System Clock Configuration
148 | * @retval None
149 | */
150 | void SystemClock_Config(void)
151 | {
152 |
153 | RCC_OscInitTypeDef RCC_OscInitStruct;
154 | RCC_ClkInitTypeDef RCC_ClkInitStruct;
155 |
156 | /**Initializes the CPU, AHB and APB busses clocks
157 | */
158 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
159 | RCC_OscInitStruct.HSEState = RCC_HSE_ON;
160 | RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
161 | RCC_OscInitStruct.HSIState = RCC_HSI_ON;
162 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
163 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
164 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL3;
165 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
166 | {
167 | _Error_Handler(__FILE__, __LINE__);
168 | }
169 |
170 | /**Initializes the CPU, AHB and APB busses clocks
171 | */
172 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
173 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
174 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
175 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
176 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
177 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
178 |
179 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
180 | {
181 | _Error_Handler(__FILE__, __LINE__);
182 | }
183 |
184 | /**Configure the Systick interrupt time
185 | */
186 | HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
187 |
188 | /**Configure the Systick
189 | */
190 | HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
191 |
192 | /* SysTick_IRQn interrupt configuration */
193 | HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
194 | }
195 |
196 | /* SPI1 init function */
197 | static void MX_SPI1_Init(void)
198 | {
199 |
200 | /* SPI1 parameter configuration*/
201 | hspi1.Instance = SPI1;
202 | hspi1.Init.Mode = SPI_MODE_MASTER;
203 | hspi1.Init.Direction = SPI_DIRECTION_2LINES;
204 | hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
205 | hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
206 | hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
207 | hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
208 | hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
209 | hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
210 | hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
211 | hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
212 | hspi1.Init.CRCPolynomial = 10;
213 | if (HAL_SPI_Init(&hspi1) != HAL_OK)
214 | {
215 | _Error_Handler(__FILE__, __LINE__);
216 | }
217 |
218 | }
219 |
220 | /* TIM1 init function */
221 | static void MX_TIM1_Init(void)
222 | {
223 |
224 | TIM_ClockConfigTypeDef sClockSourceConfig;
225 | TIM_MasterConfigTypeDef sMasterConfig;
226 | TIM_OC_InitTypeDef sConfigOC;
227 | TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
228 |
229 | htim1.Instance = TIM1;
230 | htim1.Init.Prescaler = 1199;
231 | htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
232 | htim1.Init.Period = 1000;
233 | htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
234 | htim1.Init.RepetitionCounter = 0;
235 | htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
236 | if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
237 | {
238 | _Error_Handler(__FILE__, __LINE__);
239 | }
240 |
241 | sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
242 | if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
243 | {
244 | _Error_Handler(__FILE__, __LINE__);
245 | }
246 |
247 | if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
248 | {
249 | _Error_Handler(__FILE__, __LINE__);
250 | }
251 |
252 | sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;
253 | sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
254 | if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
255 | {
256 | _Error_Handler(__FILE__, __LINE__);
257 | }
258 |
259 | sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
260 | sConfigOC.Pulse = 3;
261 | sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
262 | sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
263 | sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
264 | sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
265 | if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
266 | {
267 | _Error_Handler(__FILE__, __LINE__);
268 | }
269 |
270 | sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
271 | sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
272 | sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
273 | sBreakDeadTimeConfig.DeadTime = 0;
274 | sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
275 | sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
276 | sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
277 | if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
278 | {
279 | _Error_Handler(__FILE__, __LINE__);
280 | }
281 |
282 | }
283 |
284 | /* USART1 init function */
285 | static void MX_USART1_UART_Init(void)
286 | {
287 |
288 | huart1.Instance = USART1;
289 | huart1.Init.BaudRate = 115200;
290 | huart1.Init.WordLength = UART_WORDLENGTH_8B;
291 | huart1.Init.StopBits = UART_STOPBITS_1;
292 | huart1.Init.Parity = UART_PARITY_NONE;
293 | huart1.Init.Mode = UART_MODE_TX_RX;
294 | huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
295 | huart1.Init.OverSampling = UART_OVERSAMPLING_16;
296 | if (HAL_UART_Init(&huart1) != HAL_OK)
297 | {
298 | _Error_Handler(__FILE__, __LINE__);
299 | }
300 |
301 | }
302 |
303 | /**
304 | * Enable DMA controller clock
305 | */
306 | static void MX_DMA_Init(void)
307 | {
308 | /* DMA controller clock enable */
309 | __HAL_RCC_DMA1_CLK_ENABLE();
310 |
311 | /* DMA interrupt init */
312 | /* DMA1_Channel4_IRQn interrupt configuration */
313 | HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
314 | HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
315 |
316 | }
317 |
318 | /** Configure pins as
319 | * Analog
320 | * Input
321 | * Output
322 | * EVENT_OUT
323 | * EXTI
324 | */
325 | static void MX_GPIO_Init(void)
326 | {
327 |
328 | GPIO_InitTypeDef GPIO_InitStruct;
329 |
330 | /* GPIO Ports Clock Enable */
331 | __HAL_RCC_GPIOD_CLK_ENABLE();
332 | __HAL_RCC_GPIOA_CLK_ENABLE();
333 | __HAL_RCC_GPIOB_CLK_ENABLE();
334 |
335 | /*Configure GPIO pin Output Level */
336 | HAL_GPIO_WritePin(SPI1_ADC_CS_GPIO_Port, SPI1_ADC_CS_Pin, GPIO_PIN_RESET);
337 |
338 | /*Configure GPIO pin Output Level */
339 | HAL_GPIO_WritePin(USART1_DIR_GPIO_Port, USART1_DIR_Pin, GPIO_PIN_SET);
340 |
341 | /*Configure GPIO pin Output Level */
342 | HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
343 |
344 | /*Configure GPIO pins : SPI1_ADC_CS_Pin USART1_DIR_Pin */
345 | GPIO_InitStruct.Pin = SPI1_ADC_CS_Pin|USART1_DIR_Pin;
346 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
347 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
348 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
349 |
350 | /*Configure GPIO pin : LED1_Pin */
351 | GPIO_InitStruct.Pin = LED1_Pin;
352 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
353 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
354 | HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
355 |
356 | }
357 |
358 | /* USER CODE BEGIN 4 */
359 |
360 | /**
361 | * @brief Retargets the C library printf function to the USART.
362 | * @param None
363 | * @retval None
364 | */
365 | //PUTCHAR_PROTOTYPE
366 | //{
367 | // /* Place your implementation of fputc here */
368 | // /* e.g. write a character to the USART */
369 | // HAL_UART_Transmit(&huart1,(uint8_t *) &ch, 1,1000);
370 | // return ch;
371 | //}
372 |
373 | /**
374 | * @brief Inserts a delay time.
375 | * @param nTime: specifies the delay time length, in milliseconds.
376 | * @retval None
377 | */
378 | void Delay(__IO uint32_t nTime)
379 | {
380 | TimingDelay = nTime;
381 |
382 | while(TimingDelay != 0);
383 | }
384 |
385 |
386 | /**
387 | * @brief Decrements the TimingDelay variable.
388 | * @param None
389 | * @retval None
390 | */
391 | void TimingDelay_Decrement(void)
392 | {
393 | if (TimingDelay != 0x00)
394 | {
395 | TimingDelay--;
396 | }
397 | }
398 |
399 |
400 | void Usart1Pass(void)
401 | {
402 | printf("\n\rUSART1 Pass!\n\r");
403 | }
404 | /* USER CODE END 4 */
405 |
406 | /**
407 | * @brief This function is executed in case of error occurrence.
408 | * @param file: The file name as string.
409 | * @param line: The line in file as a number.
410 | * @retval None
411 | */
412 | void _Error_Handler(char *file, int line)
413 | {
414 | /* USER CODE BEGIN Error_Handler_Debug */
415 | /* User can add his own implementation to report the HAL error return state */
416 | while(1)
417 | {
418 | }
419 | /* USER CODE END Error_Handler_Debug */
420 | }
421 |
422 | #ifdef USE_FULL_ASSERT
423 | /**
424 | * @brief Reports the name of the source file and the source line number
425 | * where the assert_param error has occurred.
426 | * @param file: pointer to the source file name
427 | * @param line: assert_param error line source number
428 | * @retval None
429 | */
430 | void assert_failed(uint8_t* file, uint32_t line)
431 | {
432 | /* USER CODE BEGIN 6 */
433 | /* User can add his own implementation to report the file name and line number,
434 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
435 | /* USER CODE END 6 */
436 | }
437 | #endif /* USE_FULL_ASSERT */
438 |
439 | /**
440 | * @}
441 | */
442 |
443 | /**
444 | * @}
445 | */
446 |
447 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
448 |
--------------------------------------------------------------------------------
/Src/stm32f1xx_hal_msp.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * File Name : stm32f1xx_hal_msp.c
4 | * Description : This file provides code for the MSP Initialization
5 | * and de-Initialization codes.
6 | ******************************************************************************
7 | ** This notice applies to any and all portions of this file
8 | * that are not between comment pairs USER CODE BEGIN and
9 | * USER CODE END. Other portions of this file, whether
10 | * inserted by the user or by software development tools
11 | * are owned by their respective copyright owners.
12 | *
13 | * COPYRIGHT(c) 2018 STMicroelectronics
14 | *
15 | * Redistribution and use in source and binary forms, with or without modification,
16 | * are permitted provided that the following conditions are met:
17 | * 1. Redistributions of source code must retain the above copyright notice,
18 | * this list of conditions and the following disclaimer.
19 | * 2. Redistributions in binary form must reproduce the above copyright notice,
20 | * this list of conditions and the following disclaimer in the documentation
21 | * and/or other materials provided with the distribution.
22 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
23 | * may be used to endorse or promote products derived from this software
24 | * without specific prior written permission.
25 | *
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 | *
37 | ******************************************************************************
38 | */
39 | /* Includes ------------------------------------------------------------------*/
40 | #include "stm32f1xx_hal.h"
41 |
42 | extern DMA_HandleTypeDef hdma_usart1_tx;
43 |
44 | extern void _Error_Handler(char *, int);
45 | /* USER CODE BEGIN 0 */
46 |
47 | /* USER CODE END 0 */
48 | /**
49 | * Initializes the Global MSP.
50 | */
51 | void HAL_MspInit(void)
52 | {
53 | /* USER CODE BEGIN MspInit 0 */
54 |
55 | /* USER CODE END MspInit 0 */
56 |
57 | __HAL_RCC_AFIO_CLK_ENABLE();
58 |
59 | HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
60 |
61 | /* System interrupt init*/
62 | /* MemoryManagement_IRQn interrupt configuration */
63 | HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
64 | /* BusFault_IRQn interrupt configuration */
65 | HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
66 | /* UsageFault_IRQn interrupt configuration */
67 | HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
68 | /* SVCall_IRQn interrupt configuration */
69 | HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0);
70 | /* DebugMonitor_IRQn interrupt configuration */
71 | HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
72 | /* PendSV_IRQn interrupt configuration */
73 | HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0);
74 | /* SysTick_IRQn interrupt configuration */
75 | HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
76 |
77 | /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled
78 | */
79 | __HAL_AFIO_REMAP_SWJ_NOJTAG();
80 |
81 | /* USER CODE BEGIN MspInit 1 */
82 |
83 | /* USER CODE END MspInit 1 */
84 | }
85 |
86 | void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
87 | {
88 |
89 | GPIO_InitTypeDef GPIO_InitStruct;
90 | if(hspi->Instance==SPI1)
91 | {
92 | /* USER CODE BEGIN SPI1_MspInit 0 */
93 |
94 | /* USER CODE END SPI1_MspInit 0 */
95 | /* Peripheral clock enable */
96 | __HAL_RCC_SPI1_CLK_ENABLE();
97 |
98 | /**SPI1 GPIO Configuration
99 | PA4 ------> SPI1_NSS
100 | PA5 ------> SPI1_SCK
101 | PA6 ------> SPI1_MISO
102 | PA7 ------> SPI1_MOSI
103 | */
104 | GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;
105 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
106 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
107 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
108 |
109 | GPIO_InitStruct.Pin = GPIO_PIN_6;
110 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
111 | GPIO_InitStruct.Pull = GPIO_NOPULL;
112 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
113 |
114 | /* USER CODE BEGIN SPI1_MspInit 1 */
115 |
116 | /* USER CODE END SPI1_MspInit 1 */
117 | }
118 |
119 | }
120 |
121 | void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
122 | {
123 |
124 | if(hspi->Instance==SPI1)
125 | {
126 | /* USER CODE BEGIN SPI1_MspDeInit 0 */
127 |
128 | /* USER CODE END SPI1_MspDeInit 0 */
129 | /* Peripheral clock disable */
130 | __HAL_RCC_SPI1_CLK_DISABLE();
131 |
132 | /**SPI1 GPIO Configuration
133 | PA4 ------> SPI1_NSS
134 | PA5 ------> SPI1_SCK
135 | PA6 ------> SPI1_MISO
136 | PA7 ------> SPI1_MOSI
137 | */
138 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
139 |
140 | /* USER CODE BEGIN SPI1_MspDeInit 1 */
141 |
142 | /* USER CODE END SPI1_MspDeInit 1 */
143 | }
144 |
145 | }
146 |
147 | void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
148 | {
149 |
150 | if(htim_base->Instance==TIM1)
151 | {
152 | /* USER CODE BEGIN TIM1_MspInit 0 */
153 |
154 | /* USER CODE END TIM1_MspInit 0 */
155 | /* Peripheral clock enable */
156 | __HAL_RCC_TIM1_CLK_ENABLE();
157 | /* TIM1 interrupt Init */
158 | HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
159 | HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
160 | /* USER CODE BEGIN TIM1_MspInit 1 */
161 |
162 | /* USER CODE END TIM1_MspInit 1 */
163 | }
164 |
165 | }
166 |
167 | void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
168 | {
169 |
170 | if(htim_base->Instance==TIM1)
171 | {
172 | /* USER CODE BEGIN TIM1_MspDeInit 0 */
173 |
174 | /* USER CODE END TIM1_MspDeInit 0 */
175 | /* Peripheral clock disable */
176 | __HAL_RCC_TIM1_CLK_DISABLE();
177 |
178 | /* TIM1 interrupt DeInit */
179 | HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
180 | /* USER CODE BEGIN TIM1_MspDeInit 1 */
181 |
182 | /* USER CODE END TIM1_MspDeInit 1 */
183 | }
184 |
185 | }
186 |
187 | void HAL_UART_MspInit(UART_HandleTypeDef* huart)
188 | {
189 |
190 | GPIO_InitTypeDef GPIO_InitStruct;
191 | if(huart->Instance==USART1)
192 | {
193 | /* USER CODE BEGIN USART1_MspInit 0 */
194 |
195 | /* USER CODE END USART1_MspInit 0 */
196 | /* Peripheral clock enable */
197 | __HAL_RCC_USART1_CLK_ENABLE();
198 |
199 | /**USART1 GPIO Configuration
200 | PA9 ------> USART1_TX
201 | PA10 ------> USART1_RX
202 | */
203 | GPIO_InitStruct.Pin = GPIO_PIN_9;
204 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
205 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
206 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
207 |
208 | GPIO_InitStruct.Pin = GPIO_PIN_10;
209 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
210 | GPIO_InitStruct.Pull = GPIO_NOPULL;
211 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
212 |
213 | /* USART1 DMA Init */
214 | /* USART1_TX Init */
215 | hdma_usart1_tx.Instance = DMA1_Channel4;
216 | hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
217 | hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
218 | hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
219 | hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
220 | hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
221 | hdma_usart1_tx.Init.Mode = DMA_NORMAL;
222 | hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
223 | if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
224 | {
225 | _Error_Handler(__FILE__, __LINE__);
226 | }
227 |
228 | __HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);
229 |
230 | /* USART1 interrupt Init */
231 | HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
232 | HAL_NVIC_EnableIRQ(USART1_IRQn);
233 | /* USER CODE BEGIN USART1_MspInit 1 */
234 |
235 | /* USER CODE END USART1_MspInit 1 */
236 | }
237 |
238 | }
239 |
240 | void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
241 | {
242 |
243 | if(huart->Instance==USART1)
244 | {
245 | /* USER CODE BEGIN USART1_MspDeInit 0 */
246 |
247 | /* USER CODE END USART1_MspDeInit 0 */
248 | /* Peripheral clock disable */
249 | __HAL_RCC_USART1_CLK_DISABLE();
250 |
251 | /**USART1 GPIO Configuration
252 | PA9 ------> USART1_TX
253 | PA10 ------> USART1_RX
254 | */
255 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
256 |
257 | /* USART1 DMA DeInit */
258 | HAL_DMA_DeInit(huart->hdmatx);
259 |
260 | /* USART1 interrupt DeInit */
261 | HAL_NVIC_DisableIRQ(USART1_IRQn);
262 | /* USER CODE BEGIN USART1_MspDeInit 1 */
263 |
264 | /* USER CODE END USART1_MspDeInit 1 */
265 | }
266 |
267 | }
268 |
269 | /* USER CODE BEGIN 1 */
270 |
271 | /* USER CODE END 1 */
272 |
273 | /**
274 | * @}
275 | */
276 |
277 | /**
278 | * @}
279 | */
280 |
281 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
282 |
--------------------------------------------------------------------------------
/Src/stm32f1xx_it.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file stm32f1xx_it.c
4 | * @brief Interrupt Service Routines.
5 | ******************************************************************************
6 | *
7 | * COPYRIGHT(c) 2018 STMicroelectronics
8 | *
9 | * Redistribution and use in source and binary forms, with or without modification,
10 | * are permitted provided that the following conditions are met:
11 | * 1. Redistributions of source code must retain the above copyright notice,
12 | * this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
17 | * may be used to endorse or promote products derived from this software
18 | * without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | *
31 | ******************************************************************************
32 | */
33 | /* Includes ------------------------------------------------------------------*/
34 | #include "stm32f1xx_hal.h"
35 | #include "stm32f1xx.h"
36 | #include "stm32f1xx_it.h"
37 |
38 | /* USER CODE BEGIN 0 */
39 | #include "mb.h"
40 | uint8_t usart1_tx_data_buff[1]={0};
41 | uint8_t usart1_rx_data_buff[1]={0};
42 |
43 | extern void TimingDelay_Decrement(void);
44 | extern void prvvTIMERExpiredISR( void );
45 | extern void prvvUARTTxReadyISR(void);
46 | extern void prvvUARTRxISR(void);
47 |
48 | /* USER CODE END 0 */
49 |
50 | /* External variables --------------------------------------------------------*/
51 | extern TIM_HandleTypeDef htim1;
52 | extern DMA_HandleTypeDef hdma_usart1_tx;
53 | extern UART_HandleTypeDef huart1;
54 |
55 | /******************************************************************************/
56 | /* Cortex-M3 Processor Interruption and Exception Handlers */
57 | /******************************************************************************/
58 |
59 | /**
60 | * @brief This function handles Non maskable interrupt.
61 | */
62 | void NMI_Handler(void)
63 | {
64 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
65 |
66 | /* USER CODE END NonMaskableInt_IRQn 0 */
67 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
68 |
69 | /* USER CODE END NonMaskableInt_IRQn 1 */
70 | }
71 |
72 | /**
73 | * @brief This function handles Hard fault interrupt.
74 | */
75 | void HardFault_Handler(void)
76 | {
77 | /* USER CODE BEGIN HardFault_IRQn 0 */
78 |
79 | /* USER CODE END HardFault_IRQn 0 */
80 | while (1)
81 | {
82 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */
83 | /* USER CODE END W1_HardFault_IRQn 0 */
84 | }
85 | /* USER CODE BEGIN HardFault_IRQn 1 */
86 |
87 | /* USER CODE END HardFault_IRQn 1 */
88 | }
89 |
90 | /**
91 | * @brief This function handles Memory management fault.
92 | */
93 | void MemManage_Handler(void)
94 | {
95 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */
96 |
97 | /* USER CODE END MemoryManagement_IRQn 0 */
98 | while (1)
99 | {
100 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
101 | /* USER CODE END W1_MemoryManagement_IRQn 0 */
102 | }
103 | /* USER CODE BEGIN MemoryManagement_IRQn 1 */
104 |
105 | /* USER CODE END MemoryManagement_IRQn 1 */
106 | }
107 |
108 | /**
109 | * @brief This function handles Prefetch fault, memory access fault.
110 | */
111 | void BusFault_Handler(void)
112 | {
113 | /* USER CODE BEGIN BusFault_IRQn 0 */
114 |
115 | /* USER CODE END BusFault_IRQn 0 */
116 | while (1)
117 | {
118 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */
119 | /* USER CODE END W1_BusFault_IRQn 0 */
120 | }
121 | /* USER CODE BEGIN BusFault_IRQn 1 */
122 |
123 | /* USER CODE END BusFault_IRQn 1 */
124 | }
125 |
126 | /**
127 | * @brief This function handles Undefined instruction or illegal state.
128 | */
129 | void UsageFault_Handler(void)
130 | {
131 | /* USER CODE BEGIN UsageFault_IRQn 0 */
132 |
133 | /* USER CODE END UsageFault_IRQn 0 */
134 | while (1)
135 | {
136 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
137 | /* USER CODE END W1_UsageFault_IRQn 0 */
138 | }
139 | /* USER CODE BEGIN UsageFault_IRQn 1 */
140 |
141 | /* USER CODE END UsageFault_IRQn 1 */
142 | }
143 |
144 | /**
145 | * @brief This function handles System service call via SWI instruction.
146 | */
147 | void SVC_Handler(void)
148 | {
149 | /* USER CODE BEGIN SVCall_IRQn 0 */
150 |
151 | /* USER CODE END SVCall_IRQn 0 */
152 | /* USER CODE BEGIN SVCall_IRQn 1 */
153 |
154 | /* USER CODE END SVCall_IRQn 1 */
155 | }
156 |
157 | /**
158 | * @brief This function handles Debug monitor.
159 | */
160 | void DebugMon_Handler(void)
161 | {
162 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */
163 |
164 | /* USER CODE END DebugMonitor_IRQn 0 */
165 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */
166 |
167 | /* USER CODE END DebugMonitor_IRQn 1 */
168 | }
169 |
170 | /**
171 | * @brief This function handles Pendable request for system service.
172 | */
173 | void PendSV_Handler(void)
174 | {
175 | /* USER CODE BEGIN PendSV_IRQn 0 */
176 |
177 | /* USER CODE END PendSV_IRQn 0 */
178 | /* USER CODE BEGIN PendSV_IRQn 1 */
179 |
180 | /* USER CODE END PendSV_IRQn 1 */
181 | }
182 |
183 | /**
184 | * @brief This function handles System tick timer.
185 | */
186 | void SysTick_Handler(void)
187 | {
188 | /* USER CODE BEGIN SysTick_IRQn 0 */
189 | TimingDelay_Decrement();
190 | /* USER CODE END SysTick_IRQn 0 */
191 | HAL_IncTick();
192 | HAL_SYSTICK_IRQHandler();
193 | /* USER CODE BEGIN SysTick_IRQn 1 */
194 |
195 | /* USER CODE END SysTick_IRQn 1 */
196 | }
197 |
198 | /******************************************************************************/
199 | /* STM32F1xx Peripheral Interrupt Handlers */
200 | /* Add here the Interrupt Handlers for the used peripherals. */
201 | /* For the available peripheral interrupt handler names, */
202 | /* please refer to the startup file (startup_stm32f1xx.s). */
203 | /******************************************************************************/
204 |
205 | /**
206 | * @brief This function handles DMA1 channel4 global interrupt.
207 | */
208 | void DMA1_Channel4_IRQHandler(void)
209 | {
210 | /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */
211 |
212 | /* USER CODE END DMA1_Channel4_IRQn 0 */
213 | HAL_DMA_IRQHandler(&hdma_usart1_tx);
214 | /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */
215 |
216 | /* USER CODE END DMA1_Channel4_IRQn 1 */
217 | }
218 |
219 | /**
220 | * @brief This function handles TIM1 capture compare interrupt.
221 | */
222 | void TIM1_CC_IRQHandler(void)
223 | {
224 | /* USER CODE BEGIN TIM1_CC_IRQn 0 */
225 |
226 | /* USER CODE END TIM1_CC_IRQn 0 */
227 | HAL_TIM_IRQHandler(&htim1);
228 | /* USER CODE BEGIN TIM1_CC_IRQn 1 */
229 |
230 | /* USER CODE END TIM1_CC_IRQn 1 */
231 | }
232 |
233 | /**
234 | * @brief This function handles USART1 global interrupt.
235 | */
236 | void USART1_IRQHandler(void)
237 | {
238 | /* USER CODE BEGIN USART1_IRQn 0 */
239 |
240 | /* USER CODE END USART1_IRQn 0 */
241 | HAL_UART_IRQHandler(&huart1);
242 | /* USER CODE BEGIN USART1_IRQn 1 */
243 |
244 | /* USER CODE END USART1_IRQn 1 */
245 | }
246 |
247 | /* USER CODE BEGIN 1 */
248 | void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
249 | {
250 | if(huart->Instance == USART1)
251 | {
252 | prvvUARTRxISR();
253 | HAL_UART_Receive_IT(&huart1, usart1_rx_data_buff, 1);
254 | }
255 | }
256 |
257 | void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
258 | {
259 | volatile int i =0;
260 | if(huart->Instance == USART1)
261 | {
262 | HAL_GPIO_WritePin(USART1_DIR_GPIO_Port, USART1_DIR_Pin, GPIO_PIN_RESET);
263 | prvvUARTTxReadyISR();
264 | }
265 | }
266 |
267 | void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
268 | {
269 | if(htim->Instance == TIM1)
270 | {
271 | prvvTIMERExpiredISR( );
272 | }
273 | }
274 | /* USER CODE END 1 */
275 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
276 |
--------------------------------------------------------------------------------
/Src/system_stm32f1xx.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file system_stm32f1xx.c
4 | * @author MCD Application Team
5 | * @version V4.2.0
6 | * @date 31-March-2017
7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
8 | *
9 | * 1. This file provides two functions and one global variable to be called from
10 | * user application:
11 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
12 | * factors, AHB/APBx prescalers and Flash settings).
13 | * This function is called at startup just after reset and
14 | * before branch to main program. This call is made inside
15 | * the "startup_stm32f1xx_xx.s" file.
16 | *
17 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
18 | * by the user application to setup the SysTick
19 | * timer or configure other parameters.
20 | *
21 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
22 | * be called whenever the core clock is changed
23 | * during program execution.
24 | *
25 | * 2. After each device reset the HSI (8 MHz) is used as system clock source.
26 | * Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to
27 | * configure the system clock before to branch to main program.
28 | *
29 | * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on
30 | * the product used), refer to "HSE_VALUE".
31 | * When HSE is used as system clock source, directly or through PLL, and you
32 | * are using different crystal you have to adapt the HSE value to your own
33 | * configuration.
34 | *
35 | ******************************************************************************
36 | * @attention
37 | *
38 | * © COPYRIGHT(c) 2017 STMicroelectronics
39 | *
40 | * Redistribution and use in source and binary forms, with or without modification,
41 | * are permitted provided that the following conditions are met:
42 | * 1. Redistributions of source code must retain the above copyright notice,
43 | * this list of conditions and the following disclaimer.
44 | * 2. Redistributions in binary form must reproduce the above copyright notice,
45 | * this list of conditions and the following disclaimer in the documentation
46 | * and/or other materials provided with the distribution.
47 | * 3. Neither the name of STMicroelectronics nor the names of its contributors
48 | * may be used to endorse or promote products derived from this software
49 | * without specific prior written permission.
50 | *
51 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
52 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
57 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
58 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
59 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 | *
62 | ******************************************************************************
63 | */
64 |
65 | /** @addtogroup CMSIS
66 | * @{
67 | */
68 |
69 | /** @addtogroup stm32f1xx_system
70 | * @{
71 | */
72 |
73 | /** @addtogroup STM32F1xx_System_Private_Includes
74 | * @{
75 | */
76 |
77 | #include "stm32f1xx.h"
78 |
79 | /**
80 | * @}
81 | */
82 |
83 | /** @addtogroup STM32F1xx_System_Private_TypesDefinitions
84 | * @{
85 | */
86 |
87 | /**
88 | * @}
89 | */
90 |
91 | /** @addtogroup STM32F1xx_System_Private_Defines
92 | * @{
93 | */
94 |
95 | #if !defined (HSE_VALUE)
96 | #define HSE_VALUE 8000000U /*!< Default value of the External oscillator in Hz.
97 | This value can be provided and adapted by the user application. */
98 | #endif /* HSE_VALUE */
99 |
100 | #if !defined (HSI_VALUE)
101 | #define HSI_VALUE 8000000U /*!< Default value of the Internal oscillator in Hz.
102 | This value can be provided and adapted by the user application. */
103 | #endif /* HSI_VALUE */
104 |
105 | /*!< Uncomment the following line if you need to use external SRAM */
106 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
107 | /* #define DATA_IN_ExtSRAM */
108 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
109 |
110 | /*!< Uncomment the following line if you need to relocate your vector Table in
111 | Internal SRAM. */
112 | /* #define VECT_TAB_SRAM */
113 | #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
114 | This value must be a multiple of 0x200. */
115 |
116 |
117 | /**
118 | * @}
119 | */
120 |
121 | /** @addtogroup STM32F1xx_System_Private_Macros
122 | * @{
123 | */
124 |
125 | /**
126 | * @}
127 | */
128 |
129 | /** @addtogroup STM32F1xx_System_Private_Variables
130 | * @{
131 | */
132 |
133 | /*******************************************************************************
134 | * Clock Definitions
135 | *******************************************************************************/
136 | #if defined(STM32F100xB) ||defined(STM32F100xE)
137 | uint32_t SystemCoreClock = 24000000U; /*!< System Clock Frequency (Core Clock) */
138 | #else /*!< HSI Selected as System Clock source */
139 | uint32_t SystemCoreClock = 72000000U; /*!< System Clock Frequency (Core Clock) */
140 | #endif
141 |
142 | const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
143 | const uint8_t APBPrescTable[8U] = {0, 0, 0, 0, 1, 2, 3, 4};
144 |
145 | /**
146 | * @}
147 | */
148 |
149 | /** @addtogroup STM32F1xx_System_Private_FunctionPrototypes
150 | * @{
151 | */
152 |
153 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
154 | #ifdef DATA_IN_ExtSRAM
155 | static void SystemInit_ExtMemCtl(void);
156 | #endif /* DATA_IN_ExtSRAM */
157 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
158 |
159 | /**
160 | * @}
161 | */
162 |
163 | /** @addtogroup STM32F1xx_System_Private_Functions
164 | * @{
165 | */
166 |
167 | /**
168 | * @brief Setup the microcontroller system
169 | * Initialize the Embedded Flash Interface, the PLL and update the
170 | * SystemCoreClock variable.
171 | * @note This function should be used only after reset.
172 | * @param None
173 | * @retval None
174 | */
175 | void SystemInit (void)
176 | {
177 | /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
178 | /* Set HSION bit */
179 | RCC->CR |= 0x00000001U;
180 |
181 | /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
182 | #if !defined(STM32F105xC) && !defined(STM32F107xC)
183 | RCC->CFGR &= 0xF8FF0000U;
184 | #else
185 | RCC->CFGR &= 0xF0FF0000U;
186 | #endif /* STM32F105xC */
187 |
188 | /* Reset HSEON, CSSON and PLLON bits */
189 | RCC->CR &= 0xFEF6FFFFU;
190 |
191 | /* Reset HSEBYP bit */
192 | RCC->CR &= 0xFFFBFFFFU;
193 |
194 | /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
195 | RCC->CFGR &= 0xFF80FFFFU;
196 |
197 | #if defined(STM32F105xC) || defined(STM32F107xC)
198 | /* Reset PLL2ON and PLL3ON bits */
199 | RCC->CR &= 0xEBFFFFFFU;
200 |
201 | /* Disable all interrupts and clear pending bits */
202 | RCC->CIR = 0x00FF0000U;
203 |
204 | /* Reset CFGR2 register */
205 | RCC->CFGR2 = 0x00000000U;
206 | #elif defined(STM32F100xB) || defined(STM32F100xE)
207 | /* Disable all interrupts and clear pending bits */
208 | RCC->CIR = 0x009F0000U;
209 |
210 | /* Reset CFGR2 register */
211 | RCC->CFGR2 = 0x00000000U;
212 | #else
213 | /* Disable all interrupts and clear pending bits */
214 | RCC->CIR = 0x009F0000U;
215 | #endif /* STM32F105xC */
216 |
217 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
218 | #ifdef DATA_IN_ExtSRAM
219 | SystemInit_ExtMemCtl();
220 | #endif /* DATA_IN_ExtSRAM */
221 | #endif
222 |
223 | #ifdef VECT_TAB_SRAM
224 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
225 | #else
226 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
227 | #endif
228 | }
229 |
230 | /**
231 | * @brief Update SystemCoreClock variable according to Clock Register Values.
232 | * The SystemCoreClock variable contains the core clock (HCLK), it can
233 | * be used by the user application to setup the SysTick timer or configure
234 | * other parameters.
235 | *
236 | * @note Each time the core clock (HCLK) changes, this function must be called
237 | * to update SystemCoreClock variable value. Otherwise, any configuration
238 | * based on this variable will be incorrect.
239 | *
240 | * @note - The system frequency computed by this function is not the real
241 | * frequency in the chip. It is calculated based on the predefined
242 | * constant and the selected clock source:
243 | *
244 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
245 | *
246 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
247 | *
248 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
249 | * or HSI_VALUE(*) multiplied by the PLL factors.
250 | *
251 | * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value
252 | * 8 MHz) but the real value may vary depending on the variations
253 | * in voltage and temperature.
254 | *
255 | * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value
256 | * 8 MHz or 25 MHz, depending on the product used), user has to ensure
257 | * that HSE_VALUE is same as the real frequency of the crystal used.
258 | * Otherwise, this function may have wrong result.
259 | *
260 | * - The result of this function could be not correct when using fractional
261 | * value for HSE crystal.
262 | * @param None
263 | * @retval None
264 | */
265 | void SystemCoreClockUpdate (void)
266 | {
267 | uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U;
268 |
269 | #if defined(STM32F105xC) || defined(STM32F107xC)
270 | uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U;
271 | #endif /* STM32F105xC */
272 |
273 | #if defined(STM32F100xB) || defined(STM32F100xE)
274 | uint32_t prediv1factor = 0U;
275 | #endif /* STM32F100xB or STM32F100xE */
276 |
277 | /* Get SYSCLK source -------------------------------------------------------*/
278 | tmp = RCC->CFGR & RCC_CFGR_SWS;
279 |
280 | switch (tmp)
281 | {
282 | case 0x00U: /* HSI used as system clock */
283 | SystemCoreClock = HSI_VALUE;
284 | break;
285 | case 0x04U: /* HSE used as system clock */
286 | SystemCoreClock = HSE_VALUE;
287 | break;
288 | case 0x08U: /* PLL used as system clock */
289 |
290 | /* Get PLL clock source and multiplication factor ----------------------*/
291 | pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
292 | pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
293 |
294 | #if !defined(STM32F105xC) && !defined(STM32F107xC)
295 | pllmull = ( pllmull >> 18U) + 2U;
296 |
297 | if (pllsource == 0x00U)
298 | {
299 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */
300 | SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
301 | }
302 | else
303 | {
304 | #if defined(STM32F100xB) || defined(STM32F100xE)
305 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
306 | /* HSE oscillator clock selected as PREDIV1 clock entry */
307 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
308 | #else
309 | /* HSE selected as PLL clock entry */
310 | if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
311 | {/* HSE oscillator clock divided by 2 */
312 | SystemCoreClock = (HSE_VALUE >> 1U) * pllmull;
313 | }
314 | else
315 | {
316 | SystemCoreClock = HSE_VALUE * pllmull;
317 | }
318 | #endif
319 | }
320 | #else
321 | pllmull = pllmull >> 18U;
322 |
323 | if (pllmull != 0x0DU)
324 | {
325 | pllmull += 2U;
326 | }
327 | else
328 | { /* PLL multiplication factor = PLL input clock * 6.5 */
329 | pllmull = 13U / 2U;
330 | }
331 |
332 | if (pllsource == 0x00U)
333 | {
334 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */
335 | SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
336 | }
337 | else
338 | {/* PREDIV1 selected as PLL clock entry */
339 |
340 | /* Get PREDIV1 clock source and division factor */
341 | prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
342 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
343 |
344 | if (prediv1source == 0U)
345 | {
346 | /* HSE oscillator clock selected as PREDIV1 clock entry */
347 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
348 | }
349 | else
350 | {/* PLL2 clock selected as PREDIV1 clock entry */
351 |
352 | /* Get PREDIV2 division factor and PLL2 multiplication factor */
353 | prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U;
354 | pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U;
355 | SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
356 | }
357 | }
358 | #endif /* STM32F105xC */
359 | break;
360 |
361 | default:
362 | SystemCoreClock = HSI_VALUE;
363 | break;
364 | }
365 |
366 | /* Compute HCLK clock frequency ----------------*/
367 | /* Get HCLK prescaler */
368 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
369 | /* HCLK clock frequency */
370 | SystemCoreClock >>= tmp;
371 | }
372 |
373 | #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
374 | /**
375 | * @brief Setup the external memory controller. Called in startup_stm32f1xx.s
376 | * before jump to __main
377 | * @param None
378 | * @retval None
379 | */
380 | #ifdef DATA_IN_ExtSRAM
381 | /**
382 | * @brief Setup the external memory controller.
383 | * Called in startup_stm32f1xx_xx.s/.c before jump to main.
384 | * This function configures the external SRAM mounted on STM3210E-EVAL
385 | * board (STM32 High density devices). This SRAM will be used as program
386 | * data memory (including heap and stack).
387 | * @param None
388 | * @retval None
389 | */
390 | void SystemInit_ExtMemCtl(void)
391 | {
392 | __IO uint32_t tmpreg;
393 | /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is
394 | required, then adjust the Register Addresses */
395 |
396 | /* Enable FSMC clock */
397 | RCC->AHBENR = 0x00000114U;
398 |
399 | /* Delay after an RCC peripheral clock enabling */
400 | tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN);
401 |
402 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */
403 | RCC->APB2ENR = 0x000001E0U;
404 |
405 | /* Delay after an RCC peripheral clock enabling */
406 | tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);
407 |
408 | (void)(tmpreg);
409 |
410 | /* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/
411 | /*---------------- SRAM Address lines configuration -------------------------*/
412 | /*---------------- NOE and NWE configuration --------------------------------*/
413 | /*---------------- NE3 configuration ----------------------------------------*/
414 | /*---------------- NBL0, NBL1 configuration ---------------------------------*/
415 |
416 | GPIOD->CRL = 0x44BB44BBU;
417 | GPIOD->CRH = 0xBBBBBBBBU;
418 |
419 | GPIOE->CRL = 0xB44444BBU;
420 | GPIOE->CRH = 0xBBBBBBBBU;
421 |
422 | GPIOF->CRL = 0x44BBBBBBU;
423 | GPIOF->CRH = 0xBBBB4444U;
424 |
425 | GPIOG->CRL = 0x44BBBBBBU;
426 | GPIOG->CRH = 0x444B4B44U;
427 |
428 | /*---------------- FSMC Configuration ---------------------------------------*/
429 | /*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/
430 |
431 | FSMC_Bank1->BTCR[4U] = 0x00001091U;
432 | FSMC_Bank1->BTCR[5U] = 0x00110212U;
433 | }
434 | #endif /* DATA_IN_ExtSRAM */
435 | #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
436 |
437 | /**
438 | * @}
439 | */
440 |
441 | /**
442 | * @}
443 | */
444 |
445 | /**
446 | * @}
447 | */
448 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
449 |
--------------------------------------------------------------------------------
/modbus/ascii/mbascii.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbascii.c,v 1.17 2010/06/06 13:47:07 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbconfig.h"
41 | #include "mbascii.h"
42 | #include "mbframe.h"
43 |
44 | #include "mbcrc.h"
45 | #include "mbport.h"
46 |
47 | #if MB_ASCII_ENABLED > 0
48 |
49 | /* ----------------------- Defines ------------------------------------------*/
50 | #define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */
51 | #define MB_ASCII_DEFAULT_LF '\n' /*!< Default LF character for Modbus ASCII. */
52 | #define MB_SER_PDU_SIZE_MIN 3 /*!< Minimum size of a Modbus ASCII frame. */
53 | #define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus ASCII frame. */
54 | #define MB_SER_PDU_SIZE_LRC 1 /*!< Size of LRC field in PDU. */
55 | #define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
56 | #define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
57 |
58 | /* ----------------------- Type definitions ---------------------------------*/
59 | typedef enum
60 | {
61 | STATE_RX_IDLE, /*!< Receiver is in idle state. */
62 | STATE_RX_RCV, /*!< Frame is beeing received. */
63 | STATE_RX_WAIT_EOF /*!< Wait for End of Frame. */
64 | } eMBRcvState;
65 |
66 | typedef enum
67 | {
68 | STATE_TX_IDLE, /*!< Transmitter is in idle state. */
69 | STATE_TX_START, /*!< Starting transmission (':' sent). */
70 | STATE_TX_DATA, /*!< Sending of data (Address, Data, LRC). */
71 | STATE_TX_END, /*!< End of transmission. */
72 | STATE_TX_NOTIFY /*!< Notify sender that the frame has been sent. */
73 | } eMBSndState;
74 |
75 | typedef enum
76 | {
77 | BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */
78 | BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */
79 | } eMBBytePos;
80 |
81 | /* ----------------------- Static functions ---------------------------------*/
82 | static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter );
83 |
84 | static UCHAR prvucMBBIN2CHAR( UCHAR ucByte );
85 |
86 | static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen );
87 |
88 | /* ----------------------- Static variables ---------------------------------*/
89 | static volatile eMBSndState eSndState;
90 | static volatile eMBRcvState eRcvState;
91 |
92 | /* We reuse the Modbus RTU buffer because only one buffer is needed and the
93 | * RTU buffer is bigger. */
94 | extern volatile UCHAR ucRTUBuf[];
95 | static volatile UCHAR *ucASCIIBuf = ucRTUBuf;
96 |
97 | static volatile USHORT usRcvBufferPos;
98 | static volatile eMBBytePos eBytePos;
99 |
100 | static volatile UCHAR *pucSndBufferCur;
101 | static volatile USHORT usSndBufferCount;
102 |
103 | static volatile UCHAR ucLRC;
104 | static volatile UCHAR ucMBLFCharacter;
105 |
106 | /* ----------------------- Start implementation -----------------------------*/
107 | eMBErrorCode
108 | eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
109 | {
110 | eMBErrorCode eStatus = MB_ENOERR;
111 | ( void )ucSlaveAddress;
112 |
113 | ENTER_CRITICAL_SECTION( );
114 | ucMBLFCharacter = MB_ASCII_DEFAULT_LF;
115 |
116 | if( xMBPortSerialInit( ucPort, ulBaudRate, 7, eParity ) != TRUE )
117 | {
118 | eStatus = MB_EPORTERR;
119 | }
120 | else if( xMBPortTimersInit( MB_ASCII_TIMEOUT_SEC * 20000UL ) != TRUE )
121 | {
122 | eStatus = MB_EPORTERR;
123 | }
124 |
125 | EXIT_CRITICAL_SECTION( );
126 |
127 | return eStatus;
128 | }
129 |
130 | void
131 | eMBASCIIStart( void )
132 | {
133 | ENTER_CRITICAL_SECTION( );
134 | vMBPortSerialEnable( TRUE, FALSE );
135 | eRcvState = STATE_RX_IDLE;
136 | EXIT_CRITICAL_SECTION( );
137 |
138 | /* No special startup required for ASCII. */
139 | ( void )xMBPortEventPost( EV_READY );
140 | }
141 |
142 | void
143 | eMBASCIIStop( void )
144 | {
145 | ENTER_CRITICAL_SECTION( );
146 | vMBPortSerialEnable( FALSE, FALSE );
147 | vMBPortTimersDisable( );
148 | EXIT_CRITICAL_SECTION( );
149 | }
150 |
151 | eMBErrorCode
152 | eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
153 | {
154 | eMBErrorCode eStatus = MB_ENOERR;
155 |
156 | ENTER_CRITICAL_SECTION( );
157 | assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
158 |
159 | /* Length and CRC check */
160 | if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
161 | && ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
162 | {
163 | /* Save the address field. All frames are passed to the upper layed
164 | * and the decision if a frame is used is done there.
165 | */
166 | *pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
167 |
168 | /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
169 | * size of address field and CRC checksum.
170 | */
171 | *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
172 |
173 | /* Return the start of the Modbus PDU to the caller. */
174 | *pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
175 | }
176 | else
177 | {
178 | eStatus = MB_EIO;
179 | }
180 | EXIT_CRITICAL_SECTION( );
181 | return eStatus;
182 | }
183 |
184 | eMBErrorCode
185 | eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
186 | {
187 | eMBErrorCode eStatus = MB_ENOERR;
188 | UCHAR usLRC;
189 |
190 | ENTER_CRITICAL_SECTION( );
191 | /* Check if the receiver is still in idle state. If not we where too
192 | * slow with processing the received frame and the master sent another
193 | * frame on the network. We have to abort sending the frame.
194 | */
195 | if( eRcvState == STATE_RX_IDLE )
196 | {
197 | /* First byte before the Modbus-PDU is the slave address. */
198 | pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
199 | usSndBufferCount = 1;
200 |
201 | /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
202 | pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
203 | usSndBufferCount += usLength;
204 |
205 | /* Calculate LRC checksum for Modbus-Serial-Line-PDU. */
206 | usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
207 | ucASCIIBuf[usSndBufferCount++] = usLRC;
208 |
209 | /* Activate the transmitter. */
210 | eSndState = STATE_TX_START;
211 | vMBPortSerialEnable( FALSE, TRUE );
212 | }
213 | else
214 | {
215 | eStatus = MB_EIO;
216 | }
217 | EXIT_CRITICAL_SECTION( );
218 | return eStatus;
219 | }
220 |
221 | BOOL
222 | xMBASCIIReceiveFSM( void )
223 | {
224 | BOOL xNeedPoll = FALSE;
225 | UCHAR ucByte;
226 | UCHAR ucResult;
227 |
228 | assert( eSndState == STATE_TX_IDLE );
229 |
230 | ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );
231 | switch ( eRcvState )
232 | {
233 | /* A new character is received. If the character is a ':' the input
234 | * buffer is cleared. A CR-character signals the end of the data
235 | * block. Other characters are part of the data block and their
236 | * ASCII value is converted back to a binary representation.
237 | */
238 | case STATE_RX_RCV:
239 | /* Enable timer for character timeout. */
240 | vMBPortTimersEnable( );
241 | if( ucByte == ':' )
242 | {
243 | /* Empty receive buffer. */
244 | eBytePos = BYTE_HIGH_NIBBLE;
245 | usRcvBufferPos = 0;
246 | }
247 | else if( ucByte == MB_ASCII_DEFAULT_CR )
248 | {
249 | eRcvState = STATE_RX_WAIT_EOF;
250 | }
251 | else
252 | {
253 | ucResult = prvucMBCHAR2BIN( ucByte );
254 | switch ( eBytePos )
255 | {
256 | /* High nibble of the byte comes first. We check for
257 | * a buffer overflow here. */
258 | case BYTE_HIGH_NIBBLE:
259 | if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
260 | {
261 | ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 );
262 | eBytePos = BYTE_LOW_NIBBLE;
263 | break;
264 | }
265 | else
266 | {
267 | /* not handled in Modbus specification but seems
268 | * a resonable implementation. */
269 | eRcvState = STATE_RX_IDLE;
270 | /* Disable previously activated timer because of error state. */
271 | vMBPortTimersDisable( );
272 | }
273 | break;
274 |
275 | case BYTE_LOW_NIBBLE:
276 | ucASCIIBuf[usRcvBufferPos] |= ucResult;
277 | usRcvBufferPos++;
278 | eBytePos = BYTE_HIGH_NIBBLE;
279 | break;
280 | }
281 | }
282 | break;
283 |
284 | case STATE_RX_WAIT_EOF:
285 | if( ucByte == ucMBLFCharacter )
286 | {
287 | /* Disable character timeout timer because all characters are
288 | * received. */
289 | vMBPortTimersDisable( );
290 | /* Receiver is again in idle state. */
291 | eRcvState = STATE_RX_IDLE;
292 |
293 | /* Notify the caller of eMBASCIIReceive that a new frame
294 | * was received. */
295 | xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
296 | }
297 | else if( ucByte == ':' )
298 | {
299 | /* Empty receive buffer and back to receive state. */
300 | eBytePos = BYTE_HIGH_NIBBLE;
301 | usRcvBufferPos = 0;
302 | eRcvState = STATE_RX_RCV;
303 |
304 | /* Enable timer for character timeout. */
305 | vMBPortTimersEnable( );
306 | }
307 | else
308 | {
309 | /* Frame is not okay. Delete entire frame. */
310 | eRcvState = STATE_RX_IDLE;
311 | }
312 | break;
313 |
314 | case STATE_RX_IDLE:
315 | if( ucByte == ':' )
316 | {
317 | /* Enable timer for character timeout. */
318 | vMBPortTimersEnable( );
319 | /* Reset the input buffers to store the frame. */
320 | usRcvBufferPos = 0;;
321 | eBytePos = BYTE_HIGH_NIBBLE;
322 | eRcvState = STATE_RX_RCV;
323 | }
324 | break;
325 | }
326 |
327 | return xNeedPoll;
328 | }
329 |
330 | BOOL
331 | xMBASCIITransmitFSM( void )
332 | {
333 | BOOL xNeedPoll = FALSE;
334 | UCHAR ucByte;
335 |
336 | assert( eRcvState == STATE_RX_IDLE );
337 | switch ( eSndState )
338 | {
339 | /* Start of transmission. The start of a frame is defined by sending
340 | * the character ':'. */
341 | case STATE_TX_START:
342 | ucByte = ':';
343 | xMBPortSerialPutByte( ( CHAR )ucByte );
344 | eSndState = STATE_TX_DATA;
345 | eBytePos = BYTE_HIGH_NIBBLE;
346 | break;
347 |
348 | /* Send the data block. Each data byte is encoded as a character hex
349 | * stream with the high nibble sent first and the low nibble sent
350 | * last. If all data bytes are exhausted we send a '\r' character
351 | * to end the transmission. */
352 | case STATE_TX_DATA:
353 | if( usSndBufferCount > 0 )
354 | {
355 | switch ( eBytePos )
356 | {
357 | case BYTE_HIGH_NIBBLE:
358 | ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) );
359 | xMBPortSerialPutByte( ( CHAR ) ucByte );
360 | eBytePos = BYTE_LOW_NIBBLE;
361 | break;
362 |
363 | case BYTE_LOW_NIBBLE:
364 | ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) );
365 | xMBPortSerialPutByte( ( CHAR )ucByte );
366 | pucSndBufferCur++;
367 | eBytePos = BYTE_HIGH_NIBBLE;
368 | usSndBufferCount--;
369 | break;
370 | }
371 | }
372 | else
373 | {
374 | xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR );
375 | eSndState = STATE_TX_END;
376 | }
377 | break;
378 |
379 | /* Finish the frame by sending a LF character. */
380 | case STATE_TX_END:
381 | xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter );
382 | /* We need another state to make sure that the CR character has
383 | * been sent. */
384 | eSndState = STATE_TX_NOTIFY;
385 | break;
386 |
387 | /* Notify the task which called eMBASCIISend that the frame has
388 | * been sent. */
389 | case STATE_TX_NOTIFY:
390 | eSndState = STATE_TX_IDLE;
391 | xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
392 |
393 | /* Disable transmitter. This prevents another transmit buffer
394 | * empty interrupt. */
395 | vMBPortSerialEnable( TRUE, FALSE );
396 | eSndState = STATE_TX_IDLE;
397 | break;
398 |
399 | /* We should not get a transmitter event if the transmitter is in
400 | * idle state. */
401 | case STATE_TX_IDLE:
402 | /* enable receiver/disable transmitter. */
403 | vMBPortSerialEnable( TRUE, FALSE );
404 | break;
405 | }
406 |
407 | return xNeedPoll;
408 | }
409 |
410 | BOOL
411 | xMBASCIITimerT1SExpired( void )
412 | {
413 | switch ( eRcvState )
414 | {
415 | /* If we have a timeout we go back to the idle state and wait for
416 | * the next frame.
417 | */
418 | case STATE_RX_RCV:
419 | case STATE_RX_WAIT_EOF:
420 | eRcvState = STATE_RX_IDLE;
421 | break;
422 |
423 | default:
424 | assert( ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_WAIT_EOF ) );
425 | break;
426 | }
427 | vMBPortTimersDisable( );
428 |
429 | /* no context switch required. */
430 | return FALSE;
431 | }
432 |
433 |
434 | static UCHAR
435 | prvucMBCHAR2BIN( UCHAR ucCharacter )
436 | {
437 | if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) )
438 | {
439 | return ( UCHAR )( ucCharacter - '0' );
440 | }
441 | else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) )
442 | {
443 | return ( UCHAR )( ucCharacter - 'A' + 0x0A );
444 | }
445 | else
446 | {
447 | return 0xFF;
448 | }
449 | }
450 |
451 | static UCHAR
452 | prvucMBBIN2CHAR( UCHAR ucByte )
453 | {
454 | if( ucByte <= 0x09 )
455 | {
456 | return ( UCHAR )( '0' + ucByte );
457 | }
458 | else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) )
459 | {
460 | return ( UCHAR )( ucByte - 0x0A + 'A' );
461 | }
462 | else
463 | {
464 | /* Programming error. */
465 | assert( 0 );
466 | }
467 | return '0';
468 | }
469 |
470 |
471 | static UCHAR
472 | prvucMBLRC( UCHAR * pucFrame, USHORT usLen )
473 | {
474 | UCHAR ucLRC = 0; /* LRC char initialized */
475 |
476 | while( usLen-- )
477 | {
478 | ucLRC += *pucFrame++; /* Add buffer byte without carry */
479 | }
480 |
481 | /* Return twos complement */
482 | ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) );
483 | return ucLRC;
484 | }
485 |
486 | #endif
487 |
--------------------------------------------------------------------------------
/modbus/ascii/mbascii.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbascii.h,v 1.8 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_ASCII_H
32 | #define _MB_ASCII_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 |
38 | #if MB_ASCII_ENABLED > 0
39 | eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort,
40 | ULONG ulBaudRate, eMBParity eParity );
41 | void eMBASCIIStart( void );
42 | void eMBASCIIStop( void );
43 |
44 | eMBErrorCode eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
45 | USHORT * pusLength );
46 | eMBErrorCode eMBASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame,
47 | USHORT usLength );
48 | BOOL xMBASCIIReceiveFSM( void );
49 | BOOL xMBASCIITransmitFSM( void );
50 | BOOL xMBASCIITimerT1SExpired( void );
51 | #endif
52 |
53 | #ifdef __cplusplus
54 | PR_END_EXTERN_C
55 | #endif
56 | #endif
57 |
--------------------------------------------------------------------------------
/modbus/functions/mbfunccoils.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfunccoils.c,v 1.8 2007/02/18 23:47:16 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbframe.h"
41 | #include "mbproto.h"
42 | #include "mbconfig.h"
43 |
44 | /* ----------------------- Defines ------------------------------------------*/
45 | #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
46 | #define MB_PDU_FUNC_READ_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
47 | #define MB_PDU_FUNC_READ_SIZE ( 4 )
48 | #define MB_PDU_FUNC_READ_COILCNT_MAX ( 0x07D0 )
49 |
50 | #define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF )
51 | #define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
52 | #define MB_PDU_FUNC_WRITE_SIZE ( 4 )
53 |
54 | #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF )
55 | #define MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF ( MB_PDU_DATA_OFF + 2 )
56 | #define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
57 | #define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
58 | #define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 )
59 | #define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ( 0x07B0 )
60 |
61 | /* ----------------------- Static functions ---------------------------------*/
62 | eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
63 |
64 | /* ----------------------- Start implementation -----------------------------*/
65 |
66 | #if MB_FUNC_READ_COILS_ENABLED > 0
67 |
68 | eMBException
69 | eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen )
70 | {
71 | USHORT usRegAddress;
72 | USHORT usCoilCount;
73 | UCHAR ucNBytes;
74 | UCHAR *pucFrameCur;
75 |
76 | eMBException eStatus = MB_EX_NONE;
77 | eMBErrorCode eRegStatus;
78 |
79 | if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
80 | {
81 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
82 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
83 | usRegAddress++;
84 |
85 | usCoilCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8 );
86 | usCoilCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1] );
87 |
88 | /* Check if the number of registers to read is valid. If not
89 | * return Modbus illegal data value exception.
90 | */
91 | if( ( usCoilCount >= 1 ) &&
92 | ( usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX ) )
93 | {
94 | /* Set the current PDU data pointer to the beginning. */
95 | pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
96 | *usLen = MB_PDU_FUNC_OFF;
97 |
98 | /* First byte contains the function code. */
99 | *pucFrameCur++ = MB_FUNC_READ_COILS;
100 | *usLen += 1;
101 |
102 | /* Test if the quantity of coils is a multiple of 8. If not last
103 | * byte is only partially field with unused coils set to zero. */
104 | if( ( usCoilCount & 0x0007 ) != 0 )
105 | {
106 | ucNBytes = ( UCHAR )( usCoilCount / 8 + 1 );
107 | }
108 | else
109 | {
110 | ucNBytes = ( UCHAR )( usCoilCount / 8 );
111 | }
112 | *pucFrameCur++ = ucNBytes;
113 | *usLen += 1;
114 |
115 | eRegStatus =
116 | eMBRegCoilsCB( pucFrameCur, usRegAddress, usCoilCount,
117 | MB_REG_READ );
118 |
119 | /* If an error occured convert it into a Modbus exception. */
120 | if( eRegStatus != MB_ENOERR )
121 | {
122 | eStatus = prveMBError2Exception( eRegStatus );
123 | }
124 | else
125 | {
126 | /* The response contains the function code, the starting address
127 | * and the quantity of registers. We reuse the old values in the
128 | * buffer because they are still valid. */
129 | *usLen += ucNBytes;;
130 | }
131 | }
132 | else
133 | {
134 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
135 | }
136 | }
137 | else
138 | {
139 | /* Can't be a valid read coil register request because the length
140 | * is incorrect. */
141 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
142 | }
143 | return eStatus;
144 | }
145 |
146 | #if MB_FUNC_WRITE_COIL_ENABLED > 0
147 | eMBException
148 | eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen )
149 | {
150 | USHORT usRegAddress;
151 | UCHAR ucBuf[2];
152 |
153 | eMBException eStatus = MB_EX_NONE;
154 | eMBErrorCode eRegStatus;
155 |
156 | if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
157 | {
158 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
159 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
160 | usRegAddress++;
161 |
162 | if( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00 ) &&
163 | ( ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF ) ||
164 | ( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00 ) ) )
165 | {
166 | ucBuf[1] = 0;
167 | if( pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF )
168 | {
169 | ucBuf[0] = 1;
170 | }
171 | else
172 | {
173 | ucBuf[0] = 0;
174 | }
175 | eRegStatus =
176 | eMBRegCoilsCB( &ucBuf[0], usRegAddress, 1, MB_REG_WRITE );
177 |
178 | /* If an error occured convert it into a Modbus exception. */
179 | if( eRegStatus != MB_ENOERR )
180 | {
181 | eStatus = prveMBError2Exception( eRegStatus );
182 | }
183 | }
184 | else
185 | {
186 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
187 | }
188 | }
189 | else
190 | {
191 | /* Can't be a valid write coil register request because the length
192 | * is incorrect. */
193 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
194 | }
195 | return eStatus;
196 | }
197 |
198 | #endif
199 |
200 | #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
201 | eMBException
202 | eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen )
203 | {
204 | USHORT usRegAddress;
205 | USHORT usCoilCnt;
206 | UCHAR ucByteCount;
207 | UCHAR ucByteCountVerify;
208 |
209 | eMBException eStatus = MB_EX_NONE;
210 | eMBErrorCode eRegStatus;
211 |
212 | if( *usLen > ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
213 | {
214 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
215 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
216 | usRegAddress++;
217 |
218 | usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 );
219 | usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] );
220 |
221 | ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
222 |
223 | /* Compute the number of expected bytes in the request. */
224 | if( ( usCoilCnt & 0x0007 ) != 0 )
225 | {
226 | ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 );
227 | }
228 | else
229 | {
230 | ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 );
231 | }
232 |
233 | if( ( usCoilCnt >= 1 ) &&
234 | ( usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX ) &&
235 | ( ucByteCountVerify == ucByteCount ) )
236 | {
237 | eRegStatus =
238 | eMBRegCoilsCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
239 | usRegAddress, usCoilCnt, MB_REG_WRITE );
240 |
241 | /* If an error occured convert it into a Modbus exception. */
242 | if( eRegStatus != MB_ENOERR )
243 | {
244 | eStatus = prveMBError2Exception( eRegStatus );
245 | }
246 | else
247 | {
248 | /* The response contains the function code, the starting address
249 | * and the quantity of registers. We reuse the old values in the
250 | * buffer because they are still valid. */
251 | *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
252 | }
253 | }
254 | else
255 | {
256 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
257 | }
258 | }
259 | else
260 | {
261 | /* Can't be a valid write coil register request because the length
262 | * is incorrect. */
263 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
264 | }
265 | return eStatus;
266 | }
267 |
268 | #endif
269 |
270 | #endif
271 |
--------------------------------------------------------------------------------
/modbus/functions/mbfuncdiag.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfuncdiag.c,v 1.3 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
--------------------------------------------------------------------------------
/modbus/functions/mbfuncdisc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS
3 | * Copyright (C) 2006 Christian Walter
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 2.1 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 | */
19 |
20 |
21 |
22 | /* ----------------------- System includes ----------------------------------*/
23 | #include "stdlib.h"
24 | #include "string.h"
25 |
26 | /* ----------------------- Platform includes --------------------------------*/
27 | #include "port.h"
28 |
29 | /* ----------------------- Modbus includes ----------------------------------*/
30 | #include "mb.h"
31 | #include "mbframe.h"
32 | #include "mbproto.h"
33 | #include "mbconfig.h"
34 |
35 | /* ----------------------- Defines ------------------------------------------*/
36 | #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
37 | #define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 )
38 | #define MB_PDU_FUNC_READ_SIZE ( 4 )
39 | #define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 )
40 |
41 | /* ----------------------- Static functions ---------------------------------*/
42 | eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
43 |
44 | /* ----------------------- Start implementation -----------------------------*/
45 |
46 | #if MB_FUNC_READ_COILS_ENABLED > 0
47 |
48 | eMBException
49 | eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen )
50 | {
51 | USHORT usRegAddress;
52 | USHORT usDiscreteCnt;
53 | UCHAR ucNBytes;
54 | UCHAR *pucFrameCur;
55 |
56 | eMBException eStatus = MB_EX_NONE;
57 | eMBErrorCode eRegStatus;
58 |
59 | if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
60 | {
61 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
62 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
63 | usRegAddress++;
64 |
65 | usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 );
66 | usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] );
67 |
68 | /* Check if the number of registers to read is valid. If not
69 | * return Modbus illegal data value exception.
70 | */
71 | if( ( usDiscreteCnt >= 1 ) &&
72 | ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) )
73 | {
74 | /* Set the current PDU data pointer to the beginning. */
75 | pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
76 | *usLen = MB_PDU_FUNC_OFF;
77 |
78 | /* First byte contains the function code. */
79 | *pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS;
80 | *usLen += 1;
81 |
82 | /* Test if the quantity of coils is a multiple of 8. If not last
83 | * byte is only partially field with unused coils set to zero. */
84 | if( ( usDiscreteCnt & 0x0007 ) != 0 )
85 | {
86 | ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 );
87 | }
88 | else
89 | {
90 | ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 );
91 | }
92 | *pucFrameCur++ = ucNBytes;
93 | *usLen += 1;
94 |
95 | eRegStatus =
96 | eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt );
97 |
98 | /* If an error occured convert it into a Modbus exception. */
99 | if( eRegStatus != MB_ENOERR )
100 | {
101 | eStatus = prveMBError2Exception( eRegStatus );
102 | }
103 | else
104 | {
105 | /* The response contains the function code, the starting address
106 | * and the quantity of registers. We reuse the old values in the
107 | * buffer because they are still valid. */
108 | *usLen += ucNBytes;;
109 | }
110 | }
111 | else
112 | {
113 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
114 | }
115 | }
116 | else
117 | {
118 | /* Can't be a valid read coil register request because the length
119 | * is incorrect. */
120 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
121 | }
122 | return eStatus;
123 | }
124 |
125 | #endif
126 |
--------------------------------------------------------------------------------
/modbus/functions/mbfuncholding.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfuncholding.c,v 1.12 2007/02/18 23:48:22 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbframe.h"
41 | #include "mbproto.h"
42 | #include "mbconfig.h"
43 |
44 | /* ----------------------- Defines ------------------------------------------*/
45 | #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
46 | #define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
47 | #define MB_PDU_FUNC_READ_SIZE ( 4 )
48 | #define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
49 |
50 | #define MB_PDU_FUNC_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 0)
51 | #define MB_PDU_FUNC_WRITE_VALUE_OFF ( MB_PDU_DATA_OFF + 2 )
52 | #define MB_PDU_FUNC_WRITE_SIZE ( 4 )
53 |
54 | #define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
55 | #define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
56 | #define MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF ( MB_PDU_DATA_OFF + 4 )
57 | #define MB_PDU_FUNC_WRITE_MUL_VALUES_OFF ( MB_PDU_DATA_OFF + 5 )
58 | #define MB_PDU_FUNC_WRITE_MUL_SIZE_MIN ( 5 )
59 | #define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ( 0x0078 )
60 |
61 | #define MB_PDU_FUNC_READWRITE_READ_ADDR_OFF ( MB_PDU_DATA_OFF + 0 )
62 | #define MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
63 | #define MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF ( MB_PDU_DATA_OFF + 4 )
64 | #define MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF ( MB_PDU_DATA_OFF + 6 )
65 | #define MB_PDU_FUNC_READWRITE_BYTECNT_OFF ( MB_PDU_DATA_OFF + 8 )
66 | #define MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF ( MB_PDU_DATA_OFF + 9 )
67 | #define MB_PDU_FUNC_READWRITE_SIZE_MIN ( 9 )
68 |
69 | /* ----------------------- Static functions ---------------------------------*/
70 | eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
71 |
72 | /* ----------------------- Start implementation -----------------------------*/
73 |
74 | #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
75 |
76 | eMBException
77 | eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
78 | {
79 | USHORT usRegAddress;
80 | eMBException eStatus = MB_EX_NONE;
81 | eMBErrorCode eRegStatus;
82 |
83 | if( *usLen == ( MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN ) )
84 | {
85 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8 );
86 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1] );
87 | usRegAddress++;
88 |
89 | /* Make callback to update the value. */
90 | eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
91 | usRegAddress, 1, MB_REG_WRITE );
92 |
93 | /* If an error occured convert it into a Modbus exception. */
94 | if( eRegStatus != MB_ENOERR )
95 | {
96 | eStatus = prveMBError2Exception( eRegStatus );
97 | }
98 | }
99 | else
100 | {
101 | /* Can't be a valid request because the length is incorrect. */
102 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
103 | }
104 | return eStatus;
105 | }
106 | #endif
107 |
108 | #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
109 | eMBException
110 | eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
111 | {
112 | USHORT usRegAddress;
113 | USHORT usRegCount;
114 | UCHAR ucRegByteCount;
115 |
116 | eMBException eStatus = MB_EX_NONE;
117 | eMBErrorCode eRegStatus;
118 |
119 | if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) )
120 | {
121 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );
122 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );
123 | usRegAddress++;
124 |
125 | usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 );
126 | usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] );
127 |
128 | ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];
129 |
130 | if( ( usRegCount >= 1 ) &&
131 | ( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) &&
132 | ( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) )
133 | {
134 | /* Make callback to update the register values. */
135 | eRegStatus =
136 | eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF],
137 | usRegAddress, usRegCount, MB_REG_WRITE );
138 |
139 | /* If an error occured convert it into a Modbus exception. */
140 | if( eRegStatus != MB_ENOERR )
141 | {
142 | eStatus = prveMBError2Exception( eRegStatus );
143 | }
144 | else
145 | {
146 | /* The response contains the function code, the starting
147 | * address and the quantity of registers. We reuse the
148 | * old values in the buffer because they are still valid.
149 | */
150 | *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;
151 | }
152 | }
153 | else
154 | {
155 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
156 | }
157 | }
158 | else
159 | {
160 | /* Can't be a valid request because the length is incorrect. */
161 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
162 | }
163 | return eStatus;
164 | }
165 | #endif
166 |
167 | #if MB_FUNC_READ_HOLDING_ENABLED > 0
168 |
169 | eMBException
170 | eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
171 | {
172 | USHORT usRegAddress;
173 | USHORT usRegCount;
174 | UCHAR *pucFrameCur;
175 |
176 | eMBException eStatus = MB_EX_NONE;
177 | eMBErrorCode eRegStatus;
178 |
179 | if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
180 | {
181 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
182 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
183 | usRegAddress++;
184 |
185 | usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
186 | usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
187 |
188 | /* Check if the number of registers to read is valid. If not
189 | * return Modbus illegal data value exception.
190 | */
191 | if( ( usRegCount >= 1 ) && ( usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX ) )
192 | {
193 | /* Set the current PDU data pointer to the beginning. */
194 | pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
195 | *usLen = MB_PDU_FUNC_OFF;
196 |
197 | /* First byte contains the function code. */
198 | *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER;
199 | *usLen += 1;
200 |
201 | /* Second byte in the response contain the number of bytes. */
202 | *pucFrameCur++ = ( UCHAR ) ( usRegCount * 2 );
203 | *usLen += 1;
204 |
205 | /* Make callback to fill the buffer. */
206 | eRegStatus = eMBRegHoldingCB( pucFrameCur, usRegAddress, usRegCount, MB_REG_READ );
207 | /* If an error occured convert it into a Modbus exception. */
208 | if( eRegStatus != MB_ENOERR )
209 | {
210 | eStatus = prveMBError2Exception( eRegStatus );
211 | }
212 | else
213 | {
214 | *usLen += usRegCount * 2;
215 | }
216 | }
217 | else
218 | {
219 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
220 | }
221 | }
222 | else
223 | {
224 | /* Can't be a valid request because the length is incorrect. */
225 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
226 | }
227 | return eStatus;
228 | }
229 |
230 | #endif
231 |
232 | #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
233 |
234 | eMBException
235 | eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
236 | {
237 | USHORT usRegReadAddress;
238 | USHORT usRegReadCount;
239 | USHORT usRegWriteAddress;
240 | USHORT usRegWriteCount;
241 | UCHAR ucRegWriteByteCount;
242 | UCHAR *pucFrameCur;
243 |
244 | eMBException eStatus = MB_EX_NONE;
245 | eMBErrorCode eRegStatus;
246 |
247 | if( *usLen >= ( MB_PDU_FUNC_READWRITE_SIZE_MIN + MB_PDU_SIZE_MIN ) )
248 | {
249 | usRegReadAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF] << 8U );
250 | usRegReadAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_ADDR_OFF + 1] );
251 | usRegReadAddress++;
252 |
253 | usRegReadCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF] << 8U );
254 | usRegReadCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_READ_REGCNT_OFF + 1] );
255 |
256 | usRegWriteAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF] << 8U );
257 | usRegWriteAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_ADDR_OFF + 1] );
258 | usRegWriteAddress++;
259 |
260 | usRegWriteCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF] << 8U );
261 | usRegWriteCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READWRITE_WRITE_REGCNT_OFF + 1] );
262 |
263 | ucRegWriteByteCount = pucFrame[MB_PDU_FUNC_READWRITE_BYTECNT_OFF];
264 |
265 | if( ( usRegReadCount >= 1 ) && ( usRegReadCount <= 0x7D ) &&
266 | ( usRegWriteCount >= 1 ) && ( usRegWriteCount <= 0x79 ) &&
267 | ( ( 2 * usRegWriteCount ) == ucRegWriteByteCount ) )
268 | {
269 | /* Make callback to update the register values. */
270 | eRegStatus = eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_READWRITE_WRITE_VALUES_OFF],
271 | usRegWriteAddress, usRegWriteCount, MB_REG_WRITE );
272 |
273 | if( eRegStatus == MB_ENOERR )
274 | {
275 | /* Set the current PDU data pointer to the beginning. */
276 | pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
277 | *usLen = MB_PDU_FUNC_OFF;
278 |
279 | /* First byte contains the function code. */
280 | *pucFrameCur++ = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
281 | *usLen += 1;
282 |
283 | /* Second byte in the response contain the number of bytes. */
284 | *pucFrameCur++ = ( UCHAR ) ( usRegReadCount * 2 );
285 | *usLen += 1;
286 |
287 | /* Make the read callback. */
288 | eRegStatus =
289 | eMBRegHoldingCB( pucFrameCur, usRegReadAddress, usRegReadCount, MB_REG_READ );
290 | if( eRegStatus == MB_ENOERR )
291 | {
292 | *usLen += 2 * usRegReadCount;
293 | }
294 | }
295 | if( eRegStatus != MB_ENOERR )
296 | {
297 | eStatus = prveMBError2Exception( eRegStatus );
298 | }
299 | }
300 | else
301 | {
302 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
303 | }
304 | }
305 | return eStatus;
306 | }
307 |
308 | #endif
309 |
--------------------------------------------------------------------------------
/modbus/functions/mbfuncinput.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfuncinput.c,v 1.10 2007/09/12 10:15:56 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbframe.h"
41 | #include "mbproto.h"
42 | #include "mbconfig.h"
43 |
44 | /* ----------------------- Defines ------------------------------------------*/
45 | #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF )
46 | #define MB_PDU_FUNC_READ_REGCNT_OFF ( MB_PDU_DATA_OFF + 2 )
47 | #define MB_PDU_FUNC_READ_SIZE ( 4 )
48 | #define MB_PDU_FUNC_READ_REGCNT_MAX ( 0x007D )
49 |
50 | #define MB_PDU_FUNC_READ_RSP_BYTECNT_OFF ( MB_PDU_DATA_OFF )
51 |
52 | /* ----------------------- Static functions ---------------------------------*/
53 | eMBException prveMBError2Exception( eMBErrorCode eErrorCode );
54 |
55 | /* ----------------------- Start implementation -----------------------------*/
56 | #if MB_FUNC_READ_INPUT_ENABLED > 0
57 |
58 | eMBException
59 | eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen )
60 | {
61 | USHORT usRegAddress;
62 | USHORT usRegCount;
63 | UCHAR *pucFrameCur;
64 |
65 | eMBException eStatus = MB_EX_NONE;
66 | eMBErrorCode eRegStatus;
67 |
68 | if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) )
69 | {
70 | usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );
71 | usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );
72 | usRegAddress++;
73 |
74 | usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
75 | usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
76 |
77 | /* Check if the number of registers to read is valid. If not
78 | * return Modbus illegal data value exception.
79 | */
80 | if( ( usRegCount >= 1 )
81 | && ( usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX ) )
82 | {
83 | /* Set the current PDU data pointer to the beginning. */
84 | pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF];
85 | *usLen = MB_PDU_FUNC_OFF;
86 |
87 | /* First byte contains the function code. */
88 | *pucFrameCur++ = MB_FUNC_READ_INPUT_REGISTER;
89 | *usLen += 1;
90 |
91 | /* Second byte in the response contain the number of bytes. */
92 | *pucFrameCur++ = ( UCHAR )( usRegCount * 2 );
93 | *usLen += 1;
94 |
95 | eRegStatus =
96 | eMBRegInputCB( pucFrameCur, usRegAddress, usRegCount );
97 |
98 | /* If an error occured convert it into a Modbus exception. */
99 | if( eRegStatus != MB_ENOERR )
100 | {
101 | eStatus = prveMBError2Exception( eRegStatus );
102 | }
103 | else
104 | {
105 | *usLen += usRegCount * 2;
106 | }
107 | }
108 | else
109 | {
110 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
111 | }
112 | }
113 | else
114 | {
115 | /* Can't be a valid read input register request because the length
116 | * is incorrect. */
117 | eStatus = MB_EX_ILLEGAL_DATA_VALUE;
118 | }
119 | return eStatus;
120 | }
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/modbus/functions/mbfuncother.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfuncother.c,v 1.8 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbframe.h"
41 | #include "mbproto.h"
42 | #include "mbconfig.h"
43 |
44 | #if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
45 |
46 | /* ----------------------- Static variables ---------------------------------*/
47 | static UCHAR ucMBSlaveID[MB_FUNC_OTHER_REP_SLAVEID_BUF];
48 | static USHORT usMBSlaveIDLen;
49 |
50 | /* ----------------------- Start implementation -----------------------------*/
51 |
52 | eMBErrorCode
53 | eMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,
54 | UCHAR const *pucAdditional, USHORT usAdditionalLen )
55 | {
56 | eMBErrorCode eStatus = MB_ENOERR;
57 |
58 | /* the first byte and second byte in the buffer is reserved for
59 | * the parameter ucSlaveID and the running flag. The rest of
60 | * the buffer is available for additional data. */
61 | if( usAdditionalLen + 2 < MB_FUNC_OTHER_REP_SLAVEID_BUF )
62 | {
63 | usMBSlaveIDLen = 0;
64 | ucMBSlaveID[usMBSlaveIDLen++] = ucSlaveID;
65 | ucMBSlaveID[usMBSlaveIDLen++] = ( UCHAR )( xIsRunning ? 0xFF : 0x00 );
66 | if( usAdditionalLen > 0 )
67 | {
68 | memcpy( &ucMBSlaveID[usMBSlaveIDLen], pucAdditional,
69 | ( size_t )usAdditionalLen );
70 | usMBSlaveIDLen += usAdditionalLen;
71 | }
72 | }
73 | else
74 | {
75 | eStatus = MB_ENORES;
76 | }
77 | return eStatus;
78 | }
79 |
80 | eMBException
81 | eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
82 | {
83 | memcpy( &pucFrame[MB_PDU_DATA_OFF], &ucMBSlaveID[0], ( size_t )usMBSlaveIDLen );
84 | *usLen = ( USHORT )( MB_PDU_DATA_OFF + usMBSlaveIDLen );
85 | return MB_EX_NONE;
86 | }
87 |
88 | #endif
89 |
--------------------------------------------------------------------------------
/modbus/functions/mbutils.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbutils.c,v 1.6 2007/02/18 23:49:07 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbproto.h"
41 |
42 | /* ----------------------- Defines ------------------------------------------*/
43 | #define BITS_UCHAR 8U
44 |
45 | /* ----------------------- Start implementation -----------------------------*/
46 | void
47 | xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,
48 | UCHAR ucValue )
49 | {
50 | USHORT usWordBuf;
51 | USHORT usMask;
52 | USHORT usByteOffset;
53 | USHORT usNPreBits;
54 | USHORT usValue = ucValue;
55 |
56 | ////assert( ucNBits <= 8 );
57 | ////assert( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 );
58 |
59 | /* Calculate byte offset for first byte containing the bit values starting
60 | * at usBitOffset. */
61 | usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );
62 |
63 | /* How many bits precede our bits to set. */
64 | usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );
65 |
66 | /* Move bit field into position over bits to set */
67 | usValue <<= usNPreBits;
68 |
69 | /* Prepare a mask for setting the new bits. */
70 | usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
71 | usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;
72 |
73 | /* copy bits into temporary storage. */
74 | usWordBuf = ucByteBuf[usByteOffset];
75 | usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
76 |
77 | /* Zero out bit field bits and then or value bits into them. */
78 | usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue );
79 |
80 | /* move bits back into storage */
81 | ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF );
82 | ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR );
83 | }
84 |
85 | UCHAR
86 | xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits )
87 | {
88 | USHORT usWordBuf;
89 | USHORT usMask;
90 | USHORT usByteOffset;
91 | USHORT usNPreBits;
92 |
93 | /* Calculate byte offset for first byte containing the bit values starting
94 | * at usBitOffset. */
95 | usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );
96 |
97 | /* How many bits precede our bits to set. */
98 | usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );
99 |
100 | /* Prepare a mask for setting the new bits. */
101 | usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
102 |
103 | /* copy bits into temporary storage. */
104 | usWordBuf = ucByteBuf[usByteOffset];
105 | usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;
106 |
107 | /* throw away unneeded bits. */
108 | usWordBuf >>= usNPreBits;
109 |
110 | /* mask away bits above the requested bitfield. */
111 | usWordBuf &= usMask;
112 |
113 | return ( UCHAR ) usWordBuf;
114 | }
115 |
116 | eMBException
117 | prveMBError2Exception( eMBErrorCode eErrorCode )
118 | {
119 | eMBException eStatus;
120 |
121 | switch ( eErrorCode )
122 | {
123 | case MB_ENOERR:
124 | eStatus = MB_EX_NONE;
125 | break;
126 |
127 | case MB_ENOREG:
128 | eStatus = MB_EX_ILLEGAL_DATA_ADDRESS;
129 | break;
130 |
131 | case MB_ETIMEDOUT:
132 | eStatus = MB_EX_SLAVE_BUSY;
133 | break;
134 |
135 | default:
136 | eStatus = MB_EX_SLAVE_DEVICE_FAILURE;
137 | break;
138 | }
139 |
140 | return eStatus;
141 | }
142 |
--------------------------------------------------------------------------------
/modbus/include/mbconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbconfig.h,v 1.15 2010/06/06 13:54:40 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_CONFIG_H
32 | #define _MB_CONFIG_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 | /* ----------------------- Defines ------------------------------------------*/
38 | /*! \defgroup modbus_cfg Modbus Configuration
39 | *
40 | * Most modules in the protocol stack are completly optional and can be
41 | * excluded. This is specially important if target resources are very small
42 | * and program memory space should be saved.
43 | *
44 | * All of these settings are available in the file mbconfig.h
45 | */
46 | /*! \addtogroup modbus_cfg
47 | * @{
48 | */
49 | /*! \brief If Modbus ASCII support is enabled. */
50 | #define MB_ASCII_ENABLED ( 0 )
51 |
52 | /*! \brief If Modbus RTU support is enabled. */
53 | #define MB_RTU_ENABLED ( 1 )
54 |
55 | /*! \brief If Modbus TCP support is enabled. */
56 | #define MB_TCP_ENABLED ( 0 )
57 |
58 | /*! \brief The character timeout value for Modbus ASCII.
59 | *
60 | * The character timeout value is not fixed for Modbus ASCII and is therefore
61 | * a configuration option. It should be set to the maximum expected delay
62 | * time of the network.
63 | */
64 | #define MB_ASCII_TIMEOUT_SEC ( 1 )
65 |
66 | /*! \brief Timeout to wait in ASCII prior to enabling transmitter.
67 | *
68 | * If defined the function calls vMBPortSerialDelay with the argument
69 | * MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS to allow for a delay before
70 | * the serial transmitter is enabled. This is required because some
71 | * targets are so fast that there is no time between receiving and
72 | * transmitting the frame. If the master is to slow with enabling its
73 | * receiver then he will not receive the response correctly.
74 | */
75 | #ifndef MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS
76 | #define MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS ( 0 )
77 | #endif
78 |
79 | /*! \brief Maximum number of Modbus functions codes the protocol stack
80 | * should support.
81 | *
82 | * The maximum number of supported Modbus functions must be greater than
83 | * the sum of all enabled functions in this file and custom function
84 | * handlers. If set to small adding more functions will fail.
85 | */
86 | #define MB_FUNC_HANDLERS_MAX ( 16 )
87 |
88 | /*! \brief Number of bytes which should be allocated for the Report Slave ID
89 | * command.
90 | *
91 | * This number limits the maximum size of the additional segment in the
92 | * report slave id function. See eMBSetSlaveID( ) for more information on
93 | * how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED
94 | * is set to 1
.
95 | */
96 | #define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 )
97 |
98 | /*! \brief If the Report Slave ID function should be enabled. */
99 | #define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( 1 )
100 |
101 | /*! \brief If the Read Input Registers function should be enabled. */
102 | #define MB_FUNC_READ_INPUT_ENABLED ( 1 )
103 |
104 | /*! \brief If the Read Holding Registers function should be enabled. */
105 | #define MB_FUNC_READ_HOLDING_ENABLED ( 1 )
106 |
107 | /*! \brief If the Write Single Register function should be enabled. */
108 | #define MB_FUNC_WRITE_HOLDING_ENABLED ( 1 )
109 |
110 | /*! \brief If the Write Multiple registers function should be enabled. */
111 | #define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 )
112 |
113 | /*! \brief If the Read Coils function should be enabled. */
114 | #define MB_FUNC_READ_COILS_ENABLED ( 1 )
115 |
116 | /*! \brief If the Write Coils function should be enabled. */
117 | #define MB_FUNC_WRITE_COIL_ENABLED ( 1 )
118 |
119 | /*! \brief If the Write Multiple Coils function should be enabled. */
120 | #define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED ( 1 )
121 |
122 | /*! \brief If the Read Discrete Inputs function should be enabled. */
123 | #define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED ( 1 )
124 |
125 | /*! \brief If the Read/Write Multiple Registers function should be enabled. */
126 | #define MB_FUNC_READWRITE_HOLDING_ENABLED ( 1 )
127 |
128 | /*! @} */
129 | #ifdef __cplusplus
130 | PR_END_EXTERN_C
131 | #endif
132 | #endif
133 |
--------------------------------------------------------------------------------
/modbus/include/mbframe.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbframe.h,v 1.9 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_FRAME_H
32 | #define _MB_FRAME_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 |
38 | /*!
39 | * Constants which defines the format of a modbus frame. The example is
40 | * shown for a Modbus RTU/ASCII frame. Note that the Modbus PDU is not
41 | * dependent on the underlying transport.
42 | *
43 | *
44 | * <------------------------ MODBUS SERIAL LINE PDU (1) ------------------->
45 | * <----------- MODBUS PDU (1') ---------------->
46 | * +-----------+---------------+----------------------------+-------------+
47 | * | Address | Function Code | Data | CRC/LRC |
48 | * +-----------+---------------+----------------------------+-------------+
49 | * | | | |
50 | * (2) (3/2') (3') (4)
51 | *
52 | * (1) ... MB_SER_PDU_SIZE_MAX = 256
53 | * (2) ... MB_SER_PDU_ADDR_OFF = 0
54 | * (3) ... MB_SER_PDU_PDU_OFF = 1
55 | * (4) ... MB_SER_PDU_SIZE_CRC = 2
56 | *
57 | * (1') ... MB_PDU_SIZE_MAX = 253
58 | * (2') ... MB_PDU_FUNC_OFF = 0
59 | * (3') ... MB_PDU_DATA_OFF = 1
60 | *
61 | */
62 |
63 | /* ----------------------- Defines ------------------------------------------*/
64 | #define MB_PDU_SIZE_MAX 253 /*!< Maximum size of a PDU. */
65 | #define MB_PDU_SIZE_MIN 1 /*!< Function Code */
66 | #define MB_PDU_FUNC_OFF 0 /*!< Offset of function code in PDU. */
67 | #define MB_PDU_DATA_OFF 1 /*!< Offset for response data in PDU. */
68 |
69 | /* ----------------------- Prototypes 0-------------------------------------*/
70 | typedef void ( *pvMBFrameStart ) ( void );
71 |
72 | typedef void ( *pvMBFrameStop ) ( void );
73 |
74 | typedef eMBErrorCode( *peMBFrameReceive ) ( UCHAR * pucRcvAddress,
75 | UCHAR ** pucFrame,
76 | USHORT * pusLength );
77 |
78 | typedef eMBErrorCode( *peMBFrameSend ) ( UCHAR slaveAddress,
79 | const UCHAR * pucFrame,
80 | USHORT usLength );
81 |
82 | typedef void( *pvMBFrameClose ) ( void );
83 |
84 | #ifdef __cplusplus
85 | PR_END_EXTERN_C
86 | #endif
87 | #endif
88 |
--------------------------------------------------------------------------------
/modbus/include/mbfunc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbfunc.h,v 1.12 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_FUNC_H
32 | #define _MB_FUNC_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 | #if MB_FUNC_OTHER_REP_SLAVEID_BUF > 0
38 | eMBException eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen );
39 | #endif
40 |
41 | #if MB_FUNC_READ_INPUT_ENABLED > 0
42 | eMBException eMBFuncReadInputRegister( UCHAR * pucFrame, USHORT * usLen );
43 | #endif
44 |
45 | #if MB_FUNC_READ_HOLDING_ENABLED > 0
46 | eMBException eMBFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
47 | #endif
48 |
49 | #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
50 | eMBException eMBFuncWriteHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
51 | #endif
52 |
53 | #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
54 | eMBException eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
55 | #endif
56 |
57 | #if MB_FUNC_READ_COILS_ENABLED > 0
58 | eMBException eMBFuncReadCoils( UCHAR * pucFrame, USHORT * usLen );
59 | #endif
60 |
61 | #if MB_FUNC_WRITE_COIL_ENABLED > 0
62 | eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * usLen );
63 | #endif
64 |
65 | #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
66 | eMBException eMBFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen );
67 | #endif
68 |
69 | #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
70 | eMBException eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen );
71 | #endif
72 |
73 | #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
74 | eMBException eMBFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen );
75 | #endif
76 |
77 | #ifdef __cplusplus
78 | PR_END_EXTERN_C
79 | #endif
80 | #endif
81 |
--------------------------------------------------------------------------------
/modbus/include/mbport.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbport.h,v 1.19 2010/06/06 13:54:40 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_PORT_H
32 | #define _MB_PORT_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 |
38 | /* ----------------------- Type definitions ---------------------------------*/
39 |
40 | typedef enum
41 | {
42 | EV_READY, /*!< Startup finished. */
43 | EV_FRAME_RECEIVED, /*!< Frame received. */
44 | EV_EXECUTE, /*!< Execute function. */
45 | EV_FRAME_SENT /*!< Frame sent. */
46 | } eMBEventType;
47 |
48 | /*! \ingroup modbus
49 | * \brief Parity used for characters in serial mode.
50 | *
51 | * The parity which should be applied to the characters sent over the serial
52 | * link. Please note that this values are actually passed to the porting
53 | * layer and therefore not all parity modes might be available.
54 | */
55 | typedef enum
56 | {
57 | MB_PAR_NONE, /*!< No parity. */
58 | MB_PAR_ODD, /*!< Odd parity. */
59 | MB_PAR_EVEN /*!< Even parity. */
60 | } eMBParity;
61 |
62 | /* ----------------------- Supporting functions -----------------------------*/
63 | BOOL xMBPortEventInit( void );
64 |
65 | BOOL xMBPortEventPost( eMBEventType eEvent );
66 |
67 | BOOL xMBPortEventGet( /*@out@ */ eMBEventType * eEvent );
68 |
69 | /* ----------------------- Serial port functions ----------------------------*/
70 |
71 | BOOL xMBPortSerialInit( UCHAR ucPort, ULONG ulBaudRate,
72 | UCHAR ucDataBits, eMBParity eParity );
73 |
74 | void vMBPortClose( void );
75 |
76 | void xMBPortSerialClose( void );
77 |
78 | void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable );
79 |
80 | BOOL xMBPortSerialGetByte( CHAR * pucByte );
81 |
82 | BOOL xMBPortSerialPutByte( CHAR ucByte );
83 |
84 | BOOL xMBPortSerialPutBuff( CHAR * ucBuff, CHAR len);
85 |
86 | /* ----------------------- Timers functions ---------------------------------*/
87 | BOOL xMBPortTimersInit( USHORT usTimeOut50us );
88 |
89 | void xMBPortTimersClose( void );
90 |
91 | void vMBPortTimersEnable( void );
92 |
93 | void vMBPortTimersDisable( void );
94 |
95 | void vMBPortTimersDelay( USHORT usTimeOutMS );
96 |
97 | /* ----------------------- Callback for the protocol stack ------------------*/
98 |
99 | /*!
100 | * \brief Callback function for the porting layer when a new byte is
101 | * available.
102 | *
103 | * Depending upon the mode this callback function is used by the RTU or
104 | * ASCII transmission layers. In any case a call to xMBPortSerialGetByte()
105 | * must immediately return a new character.
106 | *
107 | * \return TRUE
if a event was posted to the queue because
108 | * a new byte was received. The port implementation should wake up the
109 | * tasks which are currently blocked on the eventqueue.
110 | */
111 | extern BOOL( *pxMBFrameCBByteReceived ) ( void );
112 |
113 | extern BOOL( *pxMBFrameCBTransmitterEmpty ) ( void );
114 |
115 | extern BOOL( *pxMBPortCBTimerExpired ) ( void );
116 |
117 | /* ----------------------- TCP port functions -------------------------------*/
118 | BOOL xMBTCPPortInit( USHORT usTCPPort );
119 |
120 | void vMBTCPPortClose( void );
121 |
122 | void vMBTCPPortDisable( void );
123 |
124 | BOOL xMBTCPPortGetRequest( UCHAR **ppucMBTCPFrame, USHORT * usTCPLength );
125 |
126 | BOOL xMBTCPPortSendResponse( const UCHAR *pucMBTCPFrame, USHORT usTCPLength );
127 |
128 | #ifdef __cplusplus
129 | PR_END_EXTERN_C
130 | #endif
131 | #endif
132 |
--------------------------------------------------------------------------------
/modbus/include/mbproto.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbproto.h,v 1.14 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_PROTO_H
32 | #define _MB_PROTO_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 | /* ----------------------- Defines ------------------------------------------*/
38 | #define MB_ADDRESS_BROADCAST ( 0 ) /*! Modbus broadcast address. */
39 | #define MB_ADDRESS_MIN ( 1 ) /*! Smallest possible slave address. */
40 | #define MB_ADDRESS_MAX ( 247 ) /*! Biggest possible slave address. */
41 | #define MB_FUNC_NONE ( 0 )
42 | #define MB_FUNC_READ_COILS ( 1 )
43 | #define MB_FUNC_READ_DISCRETE_INPUTS ( 2 )
44 | #define MB_FUNC_WRITE_SINGLE_COIL ( 5 )
45 | #define MB_FUNC_WRITE_MULTIPLE_COILS ( 15 )
46 | #define MB_FUNC_READ_HOLDING_REGISTER ( 3 )
47 | #define MB_FUNC_READ_INPUT_REGISTER ( 4 )
48 | #define MB_FUNC_WRITE_REGISTER ( 6 )
49 | #define MB_FUNC_WRITE_MULTIPLE_REGISTERS ( 16 )
50 | #define MB_FUNC_READWRITE_MULTIPLE_REGISTERS ( 23 )
51 | #define MB_FUNC_DIAG_READ_EXCEPTION ( 7 )
52 | #define MB_FUNC_DIAG_DIAGNOSTIC ( 8 )
53 | #define MB_FUNC_DIAG_GET_COM_EVENT_CNT ( 11 )
54 | #define MB_FUNC_DIAG_GET_COM_EVENT_LOG ( 12 )
55 | #define MB_FUNC_OTHER_REPORT_SLAVEID ( 17 )
56 | #define MB_FUNC_ERROR ( 128 )
57 | /* ----------------------- Type definitions ---------------------------------*/
58 | typedef enum
59 | {
60 | MB_EX_NONE = 0x00,
61 | MB_EX_ILLEGAL_FUNCTION = 0x01,
62 | MB_EX_ILLEGAL_DATA_ADDRESS = 0x02,
63 | MB_EX_ILLEGAL_DATA_VALUE = 0x03,
64 | MB_EX_SLAVE_DEVICE_FAILURE = 0x04,
65 | MB_EX_ACKNOWLEDGE = 0x05,
66 | MB_EX_SLAVE_BUSY = 0x06,
67 | MB_EX_MEMORY_PARITY_ERROR = 0x08,
68 | MB_EX_GATEWAY_PATH_FAILED = 0x0A,
69 | MB_EX_GATEWAY_TGT_FAILED = 0x0B
70 | } eMBException;
71 |
72 | typedef eMBException( *pxMBFunctionHandler ) ( UCHAR * pucFrame, USHORT * pusLength );
73 |
74 | typedef struct
75 | {
76 | UCHAR ucFunctionCode;
77 | pxMBFunctionHandler pxHandler;
78 | } xMBFunctionHandler;
79 |
80 | #ifdef __cplusplus
81 | PR_END_EXTERN_C
82 | #endif
83 | #endif
84 |
--------------------------------------------------------------------------------
/modbus/include/mbutils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbutils.h,v 1.5 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_UTILS_H
32 | #define _MB_UTILS_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 | /*! \defgroup modbus_utils Utilities
38 | *
39 | * This module contains some utility functions which can be used by
40 | * the application. It includes some special functions for working with
41 | * bitfields backed by a character array buffer.
42 | *
43 | */
44 | /*! \addtogroup modbus_utils
45 | * @{
46 | */
47 | /*! \brief Function to set bits in a byte buffer.
48 | *
49 | * This function allows the efficient use of an array to implement bitfields.
50 | * The array used for storing the bits must always be a multiple of two
51 | * bytes. Up to eight bits can be set or cleared in one operation.
52 | *
53 | * \param ucByteBuf A buffer where the bit values are stored. Must be a
54 | * multiple of 2 bytes. No length checking is performed and if
55 | * usBitOffset / 8 is greater than the size of the buffer memory contents
56 | * is overwritten.
57 | * \param usBitOffset The starting address of the bits to set. The first
58 | * bit has the offset 0.
59 | * \param ucNBits Number of bits to modify. The value must always be smaller
60 | * than 8.
61 | * \param ucValues Thew new values for the bits. The value for the first bit
62 | * starting at usBitOffset
is the LSB of the value
63 | * ucValues
64 | *
65 | * \code
66 | * ucBits[2] = {0, 0};
67 | *
68 | * // Set bit 4 to 1 (read: set 1 bit starting at bit offset 4 to value 1)
69 | * xMBUtilSetBits( ucBits, 4, 1, 1 );
70 | *
71 | * // Set bit 7 to 1 and bit 8 to 0.
72 | * xMBUtilSetBits( ucBits, 7, 2, 0x01 );
73 | *
74 | * // Set bits 8 - 11 to 0x05 and bits 12 - 15 to 0x0A;
75 | * xMBUtilSetBits( ucBits, 8, 8, 0x5A);
76 | * \endcode
77 | */
78 | void xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset,
79 | UCHAR ucNBits, UCHAR ucValues );
80 |
81 | /*! \brief Function to read bits in a byte buffer.
82 | *
83 | * This function is used to extract up bit values from an array. Up to eight
84 | * bit values can be extracted in one step.
85 | *
86 | * \param ucByteBuf A buffer where the bit values are stored.
87 | * \param usBitOffset The starting address of the bits to set. The first
88 | * bit has the offset 0.
89 | * \param ucNBits Number of bits to modify. The value must always be smaller
90 | * than 8.
91 | *
92 | * \code
93 | * UCHAR ucBits[2] = {0, 0};
94 | * UCHAR ucResult;
95 | *
96 | * // Extract the bits 3 - 10.
97 | * ucResult = xMBUtilGetBits( ucBits, 3, 8 );
98 | * \endcode
99 | */
100 | UCHAR xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset,
101 | UCHAR ucNBits );
102 |
103 | /*! @} */
104 |
105 | #ifdef __cplusplus
106 | PR_END_EXTERN_C
107 | #endif
108 | #endif
109 |
--------------------------------------------------------------------------------
/modbus/mb.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mb.c,v 1.28 2010/06/06 13:54:40 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbconfig.h"
41 | #include "mbframe.h"
42 | #include "mbproto.h"
43 | #include "mbfunc.h"
44 |
45 | #include "mbport.h"
46 | //#if MB_RTU_ENABLED == 1
47 | #include "mbrtu.h"
48 |
49 |
50 | #ifndef MB_PORT_HAS_CLOSE
51 | #define MB_PORT_HAS_CLOSE 0
52 | #endif
53 |
54 | /* ----------------------- Static variables ---------------------------------*/
55 |
56 | static UCHAR ucMBAddress;
57 | static eMBMode eMBCurrentMode;
58 |
59 | static enum
60 | {
61 | STATE_ENABLED,
62 | STATE_DISABLED,
63 | STATE_NOT_INITIALIZED
64 | } eMBState = STATE_NOT_INITIALIZED;
65 |
66 | /* Functions pointer which are initialized in eMBInit( ). Depending on the
67 | * mode (RTU or ASCII) the are set to the correct implementations.
68 | */
69 | static peMBFrameSend peMBFrameSendCur;
70 | static pvMBFrameStart pvMBFrameStartCur;
71 | static pvMBFrameStop pvMBFrameStopCur;
72 | static peMBFrameReceive peMBFrameReceiveCur;
73 | static pvMBFrameClose pvMBFrameCloseCur;
74 |
75 | /* Callback functions required by the porting layer. They are called when
76 | * an external event has happend which includes a timeout or the reception
77 | * or transmission of a character.
78 | */
79 | BOOL( *pxMBFrameCBByteReceived ) ( void );
80 | BOOL( *pxMBFrameCBTransmitterEmpty ) ( void );
81 | BOOL( *pxMBPortCBTimerExpired ) ( void );
82 |
83 | BOOL( *pxMBFrameCBReceiveFSMCur ) ( void );
84 | BOOL( *pxMBFrameCBTransmitFSMCur ) ( void );
85 |
86 | /* An array of Modbus functions handlers which associates Modbus function
87 | * codes with implementing functions.
88 | */
89 | static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX] = {
90 | #if MB_FUNC_OTHER_REP_SLAVEID_ENABLED > 0
91 | {MB_FUNC_OTHER_REPORT_SLAVEID, eMBFuncReportSlaveID},
92 | #endif
93 | #if MB_FUNC_READ_INPUT_ENABLED > 0
94 | {MB_FUNC_READ_INPUT_REGISTER, eMBFuncReadInputRegister},
95 | #endif
96 | #if MB_FUNC_READ_HOLDING_ENABLED > 0
97 | {MB_FUNC_READ_HOLDING_REGISTER, eMBFuncReadHoldingRegister},
98 | #endif
99 | #if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
100 | {MB_FUNC_WRITE_MULTIPLE_REGISTERS, eMBFuncWriteMultipleHoldingRegister},
101 | #endif
102 | #if MB_FUNC_WRITE_HOLDING_ENABLED > 0
103 | {MB_FUNC_WRITE_REGISTER, eMBFuncWriteHoldingRegister},
104 | #endif
105 | #if MB_FUNC_READWRITE_HOLDING_ENABLED > 0
106 | {MB_FUNC_READWRITE_MULTIPLE_REGISTERS, eMBFuncReadWriteMultipleHoldingRegister},
107 | #endif
108 | #if MB_FUNC_READ_COILS_ENABLED > 0
109 | {MB_FUNC_READ_COILS, eMBFuncReadCoils},
110 | #endif
111 | #if MB_FUNC_WRITE_COIL_ENABLED > 0
112 | {MB_FUNC_WRITE_SINGLE_COIL, eMBFuncWriteCoil},
113 | #endif
114 | #if MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED > 0
115 | {MB_FUNC_WRITE_MULTIPLE_COILS, eMBFuncWriteMultipleCoils},
116 | #endif
117 | #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
118 | {MB_FUNC_READ_DISCRETE_INPUTS, eMBFuncReadDiscreteInputs},
119 | #endif
120 | };
121 |
122 | /* ----------------------- Start implementation -----------------------------*/
123 | eMBErrorCode
124 | eMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
125 | {
126 | eMBErrorCode eStatus = MB_ENOERR;
127 |
128 | /* check preconditions */
129 | if( ( ucSlaveAddress == MB_ADDRESS_BROADCAST ) ||
130 | ( ucSlaveAddress < MB_ADDRESS_MIN ) || ( ucSlaveAddress > MB_ADDRESS_MAX ) )
131 | {
132 | eStatus = MB_EINVAL;
133 | }
134 | else
135 | {
136 | ucMBAddress = ucSlaveAddress;
137 |
138 | switch ( eMode )
139 | {
140 | #if MB_RTU_ENABLED > 0
141 | case MB_RTU:
142 | pvMBFrameStartCur = eMBRTUStart;
143 | pvMBFrameStopCur = eMBRTUStop;
144 | peMBFrameSendCur = eMBRTUSend;
145 | peMBFrameReceiveCur = eMBRTUReceive;
146 | pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL;
147 | pxMBFrameCBByteReceived = xMBRTUReceiveFSM;
148 | pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM;
149 | pxMBPortCBTimerExpired = xMBRTUTimerT35Expired;
150 |
151 | eStatus = eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity );
152 | break;
153 | #endif
154 | #if MB_ASCII_ENABLED > 0
155 | case MB_ASCII:
156 | pvMBFrameStartCur = eMBASCIIStart;
157 | pvMBFrameStopCur = eMBASCIIStop;
158 | peMBFrameSendCur = eMBASCIISend;
159 | peMBFrameReceiveCur = eMBASCIIReceive;
160 | pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose : NULL;
161 | pxMBFrameCBByteReceived = xMBASCIIReceiveFSM;
162 | pxMBFrameCBTransmitterEmpty = xMBASCIITransmitFSM;
163 | pxMBPortCBTimerExpired = xMBASCIITimerT1SExpired;
164 |
165 | eStatus = eMBASCIIInit( ucMBAddress, ucPort, ulBaudRate, eParity );
166 | break;
167 | #endif
168 | default:
169 | eStatus = MB_EINVAL;
170 | }
171 |
172 | if( eStatus == MB_ENOERR )
173 | {
174 | if( !xMBPortEventInit( ) )
175 | {
176 | /* port dependent event module initalization failed. */
177 | eStatus = MB_EPORTERR;
178 | }
179 | else
180 | {
181 | eMBCurrentMode = eMode;
182 | eMBState = STATE_DISABLED;
183 | }
184 | }
185 | }
186 | return eStatus;
187 | }
188 |
189 | #if MB_TCP_ENABLED > 0
190 | eMBErrorCode
191 | eMBTCPInit( USHORT ucTCPPort )
192 | {
193 | eMBErrorCode eStatus = MB_ENOERR;
194 |
195 | if( ( eStatus = eMBTCPDoInit( ucTCPPort ) ) != MB_ENOERR )
196 | {
197 | eMBState = STATE_DISABLED;
198 | }
199 | else if( !xMBPortEventInit( ) )
200 | {
201 | /* Port dependent event module initalization failed. */
202 | eStatus = MB_EPORTERR;
203 | }
204 | else
205 | {
206 | pvMBFrameStartCur = eMBTCPStart;
207 | pvMBFrameStopCur = eMBTCPStop;
208 | peMBFrameReceiveCur = eMBTCPReceive;
209 | peMBFrameSendCur = eMBTCPSend;
210 | pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBTCPPortClose : NULL;
211 | ucMBAddress = MB_TCP_PSEUDO_ADDRESS;
212 | eMBCurrentMode = MB_TCP;
213 | eMBState = STATE_DISABLED;
214 | }
215 | return eStatus;
216 | }
217 | #endif
218 |
219 | eMBErrorCode
220 | eMBRegisterCB( UCHAR ucFunctionCode, pxMBFunctionHandler pxHandler )
221 | {
222 | int i;
223 | eMBErrorCode eStatus;
224 |
225 | if( ( 0 < ucFunctionCode ) && ( ucFunctionCode <= 127 ) )
226 | {
227 | ENTER_CRITICAL_SECTION( );
228 | if( pxHandler != NULL )
229 | {
230 | for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
231 | {
232 | if( ( xFuncHandlers[i].pxHandler == NULL ) ||
233 | ( xFuncHandlers[i].pxHandler == pxHandler ) )
234 | {
235 | xFuncHandlers[i].ucFunctionCode = ucFunctionCode;
236 | xFuncHandlers[i].pxHandler = pxHandler;
237 | break;
238 | }
239 | }
240 | eStatus = ( i != MB_FUNC_HANDLERS_MAX ) ? MB_ENOERR : MB_ENORES;
241 | }
242 | else
243 | {
244 | for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
245 | {
246 | if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
247 | {
248 | xFuncHandlers[i].ucFunctionCode = 0;
249 | xFuncHandlers[i].pxHandler = NULL;
250 | break;
251 | }
252 | }
253 | /* Remove can't fail. */
254 | eStatus = MB_ENOERR;
255 | }
256 | EXIT_CRITICAL_SECTION( );
257 | }
258 | else
259 | {
260 | eStatus = MB_EINVAL;
261 | }
262 | return eStatus;
263 | }
264 |
265 |
266 | eMBErrorCode
267 | eMBClose( void )
268 | {
269 | eMBErrorCode eStatus = MB_ENOERR;
270 |
271 | if( eMBState == STATE_DISABLED )
272 | {
273 | if( pvMBFrameCloseCur != NULL )
274 | {
275 | pvMBFrameCloseCur( );
276 | }
277 | }
278 | else
279 | {
280 | eStatus = MB_EILLSTATE;
281 | }
282 | return eStatus;
283 | }
284 |
285 | eMBErrorCode
286 | eMBEnable( void )
287 | {
288 | eMBErrorCode eStatus = MB_ENOERR;
289 |
290 | if( eMBState == STATE_DISABLED )
291 | {
292 | /* Activate the protocol stack. */
293 | pvMBFrameStartCur( );
294 | eMBState = STATE_ENABLED;
295 | }
296 | else
297 | {
298 | eStatus = MB_EILLSTATE;
299 | }
300 | return eStatus;
301 | }
302 |
303 | eMBErrorCode
304 | eMBDisable( void )
305 | {
306 | eMBErrorCode eStatus;
307 |
308 | if( eMBState == STATE_ENABLED )
309 | {
310 | pvMBFrameStopCur( );
311 | eMBState = STATE_DISABLED;
312 | eStatus = MB_ENOERR;
313 | }
314 | else if( eMBState == STATE_DISABLED )
315 | {
316 | eStatus = MB_ENOERR;
317 | }
318 | else
319 | {
320 | eStatus = MB_EILLSTATE;
321 | }
322 | return eStatus;
323 | }
324 |
325 | eMBErrorCode
326 | eMBPoll( void )
327 | {
328 | static UCHAR *ucMBFrame;
329 | static UCHAR ucRcvAddress;
330 | static UCHAR ucFunctionCode;
331 | static USHORT usLength;
332 | static eMBException eException;
333 |
334 | int i;
335 | eMBErrorCode eStatus = MB_ENOERR;
336 | eMBEventType eEvent;
337 |
338 | /* Check if the protocol stack is ready. */
339 | if( eMBState != STATE_ENABLED )
340 | {
341 | return MB_EILLSTATE;
342 | }
343 |
344 | /* Check if there is a event available. If not return control to caller.
345 | * Otherwise we will handle the event. */
346 | if( xMBPortEventGet( &eEvent ) == TRUE )
347 | {
348 | switch ( eEvent )
349 | {
350 | case EV_READY:
351 | break;
352 |
353 | case EV_FRAME_RECEIVED:
354 | eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
355 | if( eStatus == MB_ENOERR )
356 | {
357 | /* Check if the frame is for us. If not ignore the frame. */
358 | if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
359 | {
360 | ( void )xMBPortEventPost( EV_EXECUTE );
361 | }
362 | }
363 | break;
364 |
365 | case EV_EXECUTE:
366 | ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
367 | eException = MB_EX_ILLEGAL_FUNCTION;
368 | for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
369 | {
370 | /* No more function handlers registered. Abort. */
371 | if( xFuncHandlers[i].ucFunctionCode == 0 )
372 | {
373 | break;
374 | }
375 | else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
376 | {
377 | eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
378 | break;
379 | }
380 | }
381 |
382 | /* If the request was not sent to the broadcast address we
383 | * return a reply. */
384 | if( ucRcvAddress != MB_ADDRESS_BROADCAST )
385 | {
386 | if( eException != MB_EX_NONE )
387 | {
388 | /* An exception occured. Build an error frame. */
389 | usLength = 0;
390 | ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
391 | ucMBFrame[usLength++] = eException;
392 | }
393 | if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS )
394 | {
395 | vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS );
396 | }
397 | eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
398 | }
399 | break;
400 |
401 | case EV_FRAME_SENT:
402 | break;
403 | }
404 | }
405 | return MB_ENOERR;
406 | }
407 |
--------------------------------------------------------------------------------
/modbus/port/assert.h:
--------------------------------------------------------------------------------
1 | /* assert.h: ANSI 'C' (X3J11 Oct 88) library header section 4.2 */
2 | /* Copyright (C) Codemist Ltd., 1988-1993 */
3 | /* Copyright 1991-1993 ARM Limited. All rights reserved. */
4 | /* version 0.04 */
5 |
6 | /*
7 | * RCS $Revision: 137287 $
8 | * Checkin $Date: 2008-08-27 13:36:52 +0100 (Wed, 27 Aug 2008) $
9 | * Revising $Author: drodgman $
10 | */
11 |
12 | /*
13 | * The assert macro puts diagnostics into programs. When it is executed,
14 | * if its argument expression is false, it writes information about the
15 | * call that failed (including the text of the argument, the name of the
16 | * source file, and the source line number - the latter are respectively
17 | * the values of the preprocessing macros __FILE__ and __LINE__) on the
18 | * standard error stream. It then calls the abort function.
19 | * If its argument expression is true, the assert macro returns no value.
20 | */
21 |
22 | /*
23 | * Note that may be included more that once in a program with
24 | * different setting of NDEBUG. Hence the slightly unusual first-time
25 | * only flag.
26 | */
27 |
28 | #ifndef __assert_h
29 | # define __assert_h
30 | #define _ARMABI_NORETURN __declspec(__nothrow) __declspec(__noreturn)
31 | # undef __CLIBNS
32 | # ifdef __cplusplus
33 | namespace std {
34 | # define __CLIBNS ::std::
35 | extern "C" {
36 | # else
37 | # define __CLIBNS
38 | # endif /* __cplusplus */
39 | // extern _ARMABI_NORETURN void abort(void);
40 | // extern _ARMABI_NORETURN void __aeabi_assert(const char *, const char *, int) __attribute__((__nonnull__(1,2)));
41 | # ifdef __cplusplus
42 | } /* extern "C" */
43 | } /* namespace std */
44 | # endif
45 | #else
46 | # undef assert
47 | # undef __promise
48 | #endif
49 |
50 | #ifdef NDEBUG
51 | # define assert(ignore) ((void)0)
52 | # define __promise(e) ((__promise)((e)?1:0))
53 | #else
54 | # if defined __DO_NOT_LINK_PROMISE_WITH_ASSERT
55 | # if defined __OPT_SMALL_ASSERT && !defined __ASSERT_MSG && !defined __STRICT_ANSI__ && !(_AEABI_PORTABILITY_LEVEL != 0 || (!defined _AEABI_PORTABILITY_LEVEL && __DEFAULT_AEABI_PORTABILITY_LEVEL != 0))
56 | # define assert(e) ((e) ? (void)0 : __CLIBNS abort())
57 | # elif defined __STDC__
58 | # define assert(e) ((e) ? (void)0 : __CLIBNS __aeabi_assert(#e, __FILE__, __LINE__))
59 | # else
60 | # define assert(e) ((e) ? (void)0 : __CLIBNS __aeabi_assert("e", __FILE__, __LINE__))
61 | # endif
62 | # define __promise(e) ((__promise)((e)?1:0))
63 | # else
64 | # if defined __OPT_SMALL_ASSERT && !defined __ASSERT_MSG && !defined __STRICT_ANSI__ && !(_AEABI_PORTABILITY_LEVEL != 0 || (!defined _AEABI_PORTABILITY_LEVEL && __DEFAULT_AEABI_PORTABILITY_LEVEL != 0))
65 | # define assert(e)(void)0 // ((e) ? (void)0 : __CLIBNS abort(), (__promise)((e)?1:0))
66 | # else
67 | # define assert(e) (void)0// ((e) ? (void)0 : __CLIBNS __aeabi_assert(#e, __FILE__, __LINE__), (__promise)((e)?1:0))
68 | # endif
69 | # define __promise(e) assert(e)
70 | # endif
71 | #endif
72 |
73 | #if _AEABI_PORTABILITY_LEVEL != 0 && !defined _AEABI_PORTABLE
74 | #define _AEABI_PORTABLE
75 | #endif
76 |
77 | /* end of assert.h */
78 |
--------------------------------------------------------------------------------
/modbus/port/port.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MahdiKarimian/STM32-Modbus-SerialDMA/621d17b3a045999197b3382ceca5f814c3788f4c/modbus/port/port.c
--------------------------------------------------------------------------------
/modbus/port/port.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MahdiKarimian/STM32-Modbus-SerialDMA/621d17b3a045999197b3382ceca5f814c3788f4c/modbus/port/port.h
--------------------------------------------------------------------------------
/modbus/port/portevent.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: BARE Port
3 | * Copyright (C) 2006 Christian Walter
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 2.1 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 | *
19 | * File: $Id: portevent.c,v 1.1 2006/08/22 21:35:13 wolti Exp $
20 | */
21 |
22 | /* ----------------------- Modbus includes ----------------------------------*/
23 | #include "mb.h"
24 | #include "mbport.h"
25 |
26 | /* ----------------------- Variables ----------------------------------------*/
27 | static eMBEventType eQueuedEvent;
28 | static BOOL xEventInQueue;
29 |
30 | /* ----------------------- Start implementation -----------------------------*/
31 | BOOL
32 | xMBPortEventInit( void )
33 | {
34 | xEventInQueue = FALSE;
35 | return TRUE;
36 | }
37 |
38 | BOOL
39 | xMBPortEventPost( eMBEventType eEvent )
40 | {
41 | xEventInQueue = TRUE;
42 | eQueuedEvent = eEvent;
43 | return TRUE;
44 | }
45 |
46 | BOOL
47 | xMBPortEventGet( eMBEventType * eEvent )
48 | {
49 | BOOL xEventHappened = FALSE;
50 |
51 | if( xEventInQueue )
52 | {
53 | *eEvent = eQueuedEvent;
54 | xEventInQueue = FALSE;
55 | xEventHappened = TRUE;
56 | }
57 | return xEventHappened;
58 | }
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/modbus/port/portserial.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MahdiKarimian/STM32-Modbus-SerialDMA/621d17b3a045999197b3382ceca5f814c3788f4c/modbus/port/portserial.c
--------------------------------------------------------------------------------
/modbus/port/porttimer.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MahdiKarimian/STM32-Modbus-SerialDMA/621d17b3a045999197b3382ceca5f814c3788f4c/modbus/port/porttimer.c
--------------------------------------------------------------------------------
/modbus/rtu/mbcrc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbcrc.c,v 1.7 2007/02/18 23:50:27 wolti Exp $
29 | */
30 |
31 | /* ----------------------- Platform includes --------------------------------*/
32 | #include "port.h"
33 |
34 | static const UCHAR aucCRCHi[] = {
35 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
36 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
37 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
38 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
39 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
40 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
41 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
42 | 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
43 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
44 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
45 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
46 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
47 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
48 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
49 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
50 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
51 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
52 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
53 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
54 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
55 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
56 | 0x00, 0xC1, 0x81, 0x40
57 | };
58 |
59 | static const UCHAR aucCRCLo[] = {
60 | 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
61 | 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
62 | 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
63 | 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
64 | 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
65 | 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
66 | 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
67 | 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
68 | 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
69 | 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
70 | 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
71 | 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
72 | 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
73 | 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
74 | 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
75 | 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
76 | 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
77 | 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
78 | 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
79 | 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
80 | 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
81 | 0x41, 0x81, 0x80, 0x40
82 | };
83 |
84 | USHORT
85 | usMBCRC16( UCHAR * pucFrame, USHORT usLen )
86 | {
87 | UCHAR ucCRCHi = 0xFF;
88 | UCHAR ucCRCLo = 0xFF;
89 | int iIndex;
90 |
91 | while( usLen-- )
92 | {
93 | iIndex = ucCRCLo ^ *( pucFrame++ );
94 | //ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] );
95 | //ucCRCHi = aucCRCLo[iIndex];
96 | ucCRCLo = ( UCHAR )( ucCRCHi ^ (UCHAR)aucCRCHi[iIndex] );
97 | ucCRCHi = (UCHAR)aucCRCLo[iIndex];
98 | }
99 | return ( USHORT )( ucCRCHi << 8 | ucCRCLo );
100 | }
101 |
--------------------------------------------------------------------------------
/modbus/rtu/mbcrc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbcrc.h,v 1.5 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_CRC_H
32 | #define _MB_CRC_H
33 |
34 | USHORT usMBCRC16( UCHAR * pucFrame, USHORT usLen );
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/modbus/rtu/mbrtu.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbrtu.c,v 1.18 2007/09/12 10:15:56 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbrtu.h"
41 | #include "mbframe.h"
42 |
43 | #include "mbcrc.h"
44 | #include "mbport.h"
45 | #include
46 |
47 | /* ----------------------- Defines ------------------------------------------*/
48 | #define MB_SER_PDU_SIZE_MIN 4 /*!< Minimum size of a Modbus RTU frame. */
49 | #define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus RTU frame. */
50 | #define MB_SER_PDU_SIZE_CRC 2 /*!< Size of CRC field in PDU. */
51 | #define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
52 | #define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
53 |
54 | /* ----------------------- Type definitions ---------------------------------*/
55 | typedef enum
56 | {
57 | STATE_RX_INIT, /*!< Receiver is in initial state. */
58 | STATE_RX_IDLE, /*!< Receiver is in idle state. */
59 | STATE_RX_RCV, /*!< Frame is beeing received. */
60 | STATE_RX_ERROR /*!< If the frame is invalid. */
61 | } eMBRcvState;
62 |
63 | typedef enum
64 | {
65 | STATE_TX_IDLE, /*!< Transmitter is in idle state. */
66 | STATE_TX_XMIT /*!< Transmitter is in transfer state. */
67 | } eMBSndState;
68 |
69 | /* ----------------------- Static variables ---------------------------------*/
70 | static volatile eMBSndState eSndState;
71 | static volatile eMBRcvState eRcvState;
72 |
73 | volatile UCHAR ucRTUBuf[MB_SER_PDU_SIZE_MAX];
74 |
75 | static volatile UCHAR *pucSndBufferCur;
76 | static volatile USHORT usSndBufferCount;
77 |
78 | static volatile USHORT usRcvBufferPos;
79 |
80 | /* ----------------------- Start implementation -----------------------------*/
81 | eMBErrorCode
82 | eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
83 | {
84 | eMBErrorCode eStatus = MB_ENOERR;
85 | ULONG usTimerT35_50us;
86 |
87 | ( void )ucSlaveAddress;
88 | ENTER_CRITICAL_SECTION( );
89 |
90 | /* Modbus RTU uses 8 Databits. */
91 | if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE )
92 | {
93 | eStatus = MB_EPORTERR;
94 | }
95 | else
96 | {
97 | /* If baudrate > 19200 then we should use the fixed timer values
98 | * t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
99 | */
100 | if( ulBaudRate > 19200 )
101 | {
102 | usTimerT35_50us = 35; /* 1800us. */
103 | }
104 | else
105 | {
106 | /* The timer reload value for a character is given by:
107 | *
108 | * ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
109 | * = 11 * Ticks_per_1s / Baudrate
110 | * = 220000 / Baudrate
111 | * The reload for t3.5 is 1.5 times this value and similary
112 | * for t3.5.
113 | */
114 | usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );
115 | }
116 | if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
117 | {
118 | eStatus = MB_EPORTERR;
119 | }
120 | }
121 | EXIT_CRITICAL_SECTION( );
122 |
123 | return eStatus;
124 | }
125 |
126 | void
127 | eMBRTUStart( void )
128 | {
129 | ENTER_CRITICAL_SECTION( );
130 | /* Initially the receiver is in the state STATE_RX_INIT. we start
131 | * the timer and if no character is received within t3.5 we change
132 | * to STATE_RX_IDLE. This makes sure that we delay startup of the
133 | * modbus protocol stack until the bus is free.
134 | */
135 | eRcvState = STATE_RX_INIT;
136 | vMBPortSerialEnable( TRUE, FALSE );
137 | vMBPortTimersEnable( );
138 |
139 | EXIT_CRITICAL_SECTION( );
140 | }
141 |
142 | void
143 | eMBRTUStop( void )
144 | {
145 | ENTER_CRITICAL_SECTION( );
146 | vMBPortSerialEnable( FALSE, FALSE );
147 | vMBPortTimersDisable( );
148 | EXIT_CRITICAL_SECTION( );
149 | }
150 |
151 | eMBErrorCode
152 | eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
153 | {
154 | BOOL xFrameReceived = FALSE;
155 | eMBErrorCode eStatus = MB_ENOERR;
156 |
157 | ENTER_CRITICAL_SECTION( );
158 | ////assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
159 |
160 | /* Length and CRC check */
161 | if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
162 | && ( usMBCRC16( ( UCHAR * ) ucRTUBuf, usRcvBufferPos ) == 0 ) )
163 | {
164 | /* Save the address field. All frames are passed to the upper layed
165 | * and the decision if a frame is used is done there.
166 | */
167 | *pucRcvAddress = ucRTUBuf[MB_SER_PDU_ADDR_OFF];
168 |
169 | /* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
170 | * size of address field and CRC checksum.
171 | */
172 | *pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC );
173 |
174 | /* Return the start of the Modbus PDU to the caller. */
175 | *pucFrame = ( UCHAR * ) & ucRTUBuf[MB_SER_PDU_PDU_OFF];
176 | xFrameReceived = TRUE;
177 | }
178 | else
179 | {
180 | eStatus = MB_EIO;
181 | }
182 |
183 | EXIT_CRITICAL_SECTION( );
184 | return eStatus;
185 | }
186 |
187 | eMBErrorCode
188 | eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
189 | {
190 | eMBErrorCode eStatus = MB_ENOERR;
191 | USHORT usCRC16;
192 |
193 | ENTER_CRITICAL_SECTION( );
194 |
195 | /* Check if the receiver is still in idle state. If not we where to
196 | * slow with processing the received frame and the master sent another
197 | * frame on the network. We have to abort sending the frame.
198 | */
199 | if( eRcvState == STATE_RX_IDLE )
200 | {
201 | /* First byte before the Modbus-PDU is the slave address. */
202 | pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
203 | usSndBufferCount = 1;
204 |
205 | /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
206 | pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
207 | usSndBufferCount += usLength;
208 |
209 | /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
210 | usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
211 | pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
212 | pucSndBufferCur[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
213 |
214 | //ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
215 | //ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
216 |
217 | /* Activate the transmitter. */
218 | eSndState = STATE_TX_XMIT;
219 |
220 | vMBPortSerialEnable( FALSE, TRUE );
221 |
222 | xMBRTUTransmitFSM();
223 | }
224 | else
225 | {
226 | eStatus = MB_EIO;
227 | }
228 | EXIT_CRITICAL_SECTION( );
229 | return eStatus;
230 | }
231 |
232 | BOOL
233 | xMBRTUReceiveFSM( void )
234 | {
235 | BOOL xTaskNeedSwitch = FALSE;
236 | UCHAR ucByte;
237 |
238 | ////assert( eSndState == STATE_TX_IDLE );
239 |
240 | /* Always read the character. */
241 | ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );
242 |
243 | switch ( eRcvState )
244 | {
245 | /* If we have received a character in the init state we have to
246 | * wait until the frame is finished.
247 | */
248 | case STATE_RX_INIT:
249 | vMBPortTimersEnable( );
250 | break;
251 |
252 | /* In the error state we wait until all characters in the
253 | * damaged frame are transmitted.
254 | */
255 | case STATE_RX_ERROR:
256 | vMBPortTimersEnable( );
257 | break;
258 |
259 | /* In the idle state we wait for a new character. If a character
260 | * is received the t1.5 and t3.5 timers are started and the
261 | * receiver is in the state STATE_RX_RECEIVCE.
262 | */
263 | case STATE_RX_IDLE:
264 | usRcvBufferPos = 0;
265 | ucRTUBuf[usRcvBufferPos++] = ucByte;
266 | eRcvState = STATE_RX_RCV;
267 |
268 | /* Enable t3.5 timers. */
269 | vMBPortTimersEnable( );
270 | break;
271 |
272 | /* We are currently receiving a frame. Reset the timer after
273 | * every character received. If more than the maximum possible
274 | * number of bytes in a modbus frame is received the frame is
275 | * ignored.
276 | */
277 | case STATE_RX_RCV:
278 | if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
279 | {
280 | ucRTUBuf[usRcvBufferPos++] = ucByte;
281 | }
282 | else
283 | {
284 | eRcvState = STATE_RX_ERROR;
285 | }
286 | vMBPortTimersEnable( );
287 | break;
288 | }
289 | return xTaskNeedSwitch;
290 | }
291 |
292 | BOOL
293 | xMBRTUTransmitFSM( void )
294 | {
295 | BOOL xNeedPoll = FALSE;
296 |
297 | ////assert( eRcvState == STATE_RX_IDLE );
298 |
299 | switch ( eSndState )
300 | {
301 | /* We should not get a transmitter event if the transmitter is in
302 | * idle state. */
303 | case STATE_TX_IDLE:
304 | /* enable receiver/disable transmitter. */
305 | vMBPortSerialEnable( TRUE, FALSE );
306 | break;
307 |
308 | case STATE_TX_XMIT:
309 | /* check if we are finished. */
310 | if( usSndBufferCount != 0 )
311 | {
312 | // xMBPortSerialPutByte( ( CHAR )*pucSndBufferCur );
313 | // pucSndBufferCur++; /* next byte in sendbuffer. */
314 | // usSndBufferCount--;
315 | xMBPortSerialPutBuff( pucSndBufferCur, usSndBufferCount);
316 | pucSndBufferCur+=usSndBufferCount; /* next byte in sendbuffer. */
317 | usSndBufferCount = 0;
318 | }
319 | else
320 | {
321 | xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
322 | /* Disable transmitter. This prevents another transmit buffer
323 | * empty interrupt. */
324 | vMBPortSerialEnable( TRUE, FALSE );
325 | eSndState = STATE_TX_IDLE;
326 | }
327 | break;
328 | }
329 |
330 | return xNeedPoll;
331 | }
332 |
333 | BOOL
334 | xMBRTUTimerT35Expired( void )
335 | {
336 | BOOL xNeedPoll = FALSE;
337 |
338 | switch ( eRcvState )
339 | {
340 | /* Timer t35 expired. Startup phase is finished. */
341 | case STATE_RX_INIT:
342 | xNeedPoll = xMBPortEventPost( EV_READY );
343 | break;
344 |
345 | /* A frame was received and t35 expired. Notify the listener that
346 | * a new frame was received. */
347 | case STATE_RX_RCV:
348 | xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
349 | break;
350 |
351 | /* An error occured while receiving the frame. */
352 | case STATE_RX_ERROR:
353 | break;
354 |
355 | /* Function called in an illegal state. */
356 | default:
357 | {}
358 | // assert( ( eRcvState == STATE_RX_INIT ) ||
359 | // ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_ERROR ) );
360 | }
361 |
362 | vMBPortTimersDisable( );
363 | eRcvState = STATE_RX_IDLE;
364 |
365 | return xNeedPoll;
366 | }
367 |
--------------------------------------------------------------------------------
/modbus/rtu/mbrtu.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbrtu.h,v 1.9 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_RTU_H
32 | #define _MB_RTU_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 | eMBErrorCode eMBRTUInit( UCHAR slaveAddress, UCHAR ucPort, ULONG ulBaudRate,
38 | eMBParity eParity );
39 | void eMBRTUStart( void );
40 | void eMBRTUStop( void );
41 | eMBErrorCode eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength );
42 | eMBErrorCode eMBRTUSend( UCHAR slaveAddress, const UCHAR * pucFrame, USHORT usLength );
43 | BOOL xMBRTUReceiveFSM( void );
44 | BOOL xMBRTUTransmitFSM( void );
45 | BOOL xMBRTUTimerT15Expired( void );
46 | BOOL xMBRTUTimerT35Expired( void );
47 |
48 | #ifdef __cplusplus
49 | PR_END_EXTERN_C
50 | #endif
51 | #endif
52 |
--------------------------------------------------------------------------------
/modbus/tcp/mbtcp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | /* ----------------------- System includes ----------------------------------*/
32 | #include "stdlib.h"
33 | #include "string.h"
34 |
35 | /* ----------------------- Platform includes --------------------------------*/
36 | #include "port.h"
37 |
38 | /* ----------------------- Modbus includes ----------------------------------*/
39 | #include "mb.h"
40 | #include "mbconfig.h"
41 | #include "mbtcp.h"
42 | #include "mbframe.h"
43 | #include "mbport.h"
44 |
45 | #if MB_TCP_ENABLED > 0
46 |
47 | /* ----------------------- Defines ------------------------------------------*/
48 |
49 | /* ----------------------- MBAP Header --------------------------------------*/
50 | /*
51 | *
52 | * <------------------------ MODBUS TCP/IP ADU(1) ------------------------->
53 | * <----------- MODBUS PDU (1') ---------------->
54 | * +-----------+---------------+------------------------------------------+
55 | * | TID | PID | Length | UID |Code | Data |
56 | * +-----------+---------------+------------------------------------------+
57 | * | | | | |
58 | * (2) (3) (4) (5) (6)
59 | *
60 | * (2) ... MB_TCP_TID = 0 (Transaction Identifier - 2 Byte)
61 | * (3) ... MB_TCP_PID = 2 (Protocol Identifier - 2 Byte)
62 | * (4) ... MB_TCP_LEN = 4 (Number of bytes - 2 Byte)
63 | * (5) ... MB_TCP_UID = 6 (Unit Identifier - 1 Byte)
64 | * (6) ... MB_TCP_FUNC = 7 (Modbus Function Code)
65 | *
66 | * (1) ... Modbus TCP/IP Application Data Unit
67 | * (1') ... Modbus Protocol Data Unit
68 | */
69 |
70 | #define MB_TCP_TID 0
71 | #define MB_TCP_PID 2
72 | #define MB_TCP_LEN 4
73 | #define MB_TCP_UID 6
74 | #define MB_TCP_FUNC 7
75 |
76 | #define MB_TCP_PROTOCOL_ID 0 /* 0 = Modbus Protocol */
77 |
78 |
79 | /* ----------------------- Start implementation -----------------------------*/
80 | eMBErrorCode
81 | eMBTCPDoInit( USHORT ucTCPPort )
82 | {
83 | eMBErrorCode eStatus = MB_ENOERR;
84 |
85 | if( xMBTCPPortInit( ucTCPPort ) == FALSE )
86 | {
87 | eStatus = MB_EPORTERR;
88 | }
89 | return eStatus;
90 | }
91 |
92 | void
93 | eMBTCPStart( void )
94 | {
95 | }
96 |
97 | void
98 | eMBTCPStop( void )
99 | {
100 | /* Make sure that no more clients are connected. */
101 | vMBTCPPortDisable( );
102 | }
103 |
104 | eMBErrorCode
105 | eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength )
106 | {
107 | eMBErrorCode eStatus = MB_EIO;
108 | UCHAR *pucMBTCPFrame;
109 | USHORT usLength;
110 | USHORT usPID;
111 |
112 | if( xMBTCPPortGetRequest( &pucMBTCPFrame, &usLength ) != FALSE )
113 | {
114 | usPID = pucMBTCPFrame[MB_TCP_PID] << 8U;
115 | usPID |= pucMBTCPFrame[MB_TCP_PID + 1];
116 |
117 | if( usPID == MB_TCP_PROTOCOL_ID )
118 | {
119 | *ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC];
120 | *pusLength = usLength - MB_TCP_FUNC;
121 | eStatus = MB_ENOERR;
122 |
123 | /* Modbus TCP does not use any addresses. Fake the source address such
124 | * that the processing part deals with this frame.
125 | */
126 | *pucRcvAddress = MB_TCP_PSEUDO_ADDRESS;
127 | }
128 | }
129 | else
130 | {
131 | eStatus = MB_EIO;
132 | }
133 | return eStatus;
134 | }
135 |
136 | eMBErrorCode
137 | eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength )
138 | {
139 | eMBErrorCode eStatus = MB_ENOERR;
140 | UCHAR *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC;
141 | USHORT usTCPLength = usLength + MB_TCP_FUNC;
142 |
143 | /* The MBAP header is already initialized because the caller calls this
144 | * function with the buffer returned by the previous call. Therefore we
145 | * only have to update the length in the header. Note that the length
146 | * header includes the size of the Modbus PDU and the UID Byte. Therefore
147 | * the length is usLength plus one.
148 | */
149 | pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U;
150 | pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF;
151 | if( xMBTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE )
152 | {
153 | eStatus = MB_EIO;
154 | }
155 | return eStatus;
156 | }
157 |
158 | #endif
159 |
--------------------------------------------------------------------------------
/modbus/tcp/mbtcp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
3 | * Copyright (c) 2006 Christian Walter
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | * 3. The name of the author may not be used to endorse or promote products
15 | * derived from this software without specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | *
28 | * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $
29 | */
30 |
31 | #ifndef _MB_TCP_H
32 | #define _MB_TCP_H
33 |
34 | #ifdef __cplusplus
35 | PR_BEGIN_EXTERN_C
36 | #endif
37 |
38 | /* ----------------------- Defines ------------------------------------------*/
39 | #define MB_TCP_PSEUDO_ADDRESS 255
40 |
41 | /* ----------------------- Function prototypes ------------------------------*/
42 | eMBErrorCode eMBTCPDoInit( USHORT ucTCPPort );
43 | void eMBTCPStart( void );
44 | void eMBTCPStop( void );
45 | eMBErrorCode eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
46 | USHORT * pusLength );
47 | eMBErrorCode eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame,
48 | USHORT usLength );
49 |
50 | #ifdef __cplusplus
51 | PR_END_EXTERN_C
52 | #endif
53 | #endif
54 |
--------------------------------------------------------------------------------