├── 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 | --------------------------------------------------------------------------------