├── .gitignore
├── Core
├── Inc
│ ├── ModbusRTU_Master.h
│ ├── main.h
│ ├── stm32f4xx_hal_conf.h
│ └── stm32f4xx_it.h
└── Src
│ ├── ModbusRTU_Master.c
│ ├── main.c
│ ├── stm32f4xx_hal_msp.c
│ ├── stm32f4xx_it.c
│ ├── syscalls.c
│ ├── sysmem.c
│ └── system_stm32f4xx.c
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | STM32F407VGTX_RAM.ld
2 | STM32F407VGTX_FLASH.ld
3 | Modbus_Master.ioc
4 | Modbus_Master Debug.launch
5 | Drivers/
6 | Debug/
7 | .cproject
8 | .project
9 | .settings/
10 | .mxproject
11 | Core/Startup
--------------------------------------------------------------------------------
/Core/Inc/ModbusRTU_Master.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ModbusRTU_Master.h
3 | *
4 | * Created on: Feb 17, 2022
5 | * Author: Ümit Can Güveren
6 | */
7 |
8 | #ifndef INC_MODBUSRTU_MASTER_H_
9 | #define INC_MODBUSRTU_MASTER_H_
10 |
11 | #include "stdbool.h"
12 | #include "stdio.h"
13 | #include "stdint.h"
14 | #include "string.h"
15 | #include "stdbool.h"
16 |
17 | #define SLAVEID 1
18 | #define NUMBER_OF_REGISTER 10
19 | #define NUMBER_OF_COIL 16
20 | #define BUFFERSIZE (NUMBER_OF_REGISTER * 2 + 5)
21 |
22 | uint16_t ModbusRegister[NUMBER_OF_REGISTER];
23 | bool ModbusCoil[NUMBER_OF_COIL];
24 |
25 | enum
26 | {
27 | ReadCoil = 0x01,
28 | ReadHoldingRegister = 0x03,
29 | WriteSingleCoil = 0x05,
30 | WriteSingleRegister = 0x06,
31 | WriteMultipleCoils = 0x0F,
32 | WriteMultipleRegisters = 0x10,
33 | };
34 |
35 | typedef enum
36 | {
37 | uartOkState,
38 | uartErrState,
39 | }uartState_t;
40 |
41 | typedef enum
42 | {
43 | crcOk,
44 | crcErr,
45 | }crcState_t;
46 |
47 | typedef enum
48 | {
49 | funcOk,
50 | funcErr,
51 | }funcState_t;
52 |
53 | typedef enum
54 | {
55 | coilOff = 0x00,
56 | coilOn = 0xFF,
57 | }coilState_t;
58 |
59 | /*Data transmit and receive func*/
60 | funcState_t sendMessage(char *msg, uint16_t len);
61 | funcState_t takeMessage(char *msg, uint16_t len, uint8_t SlaveID);
62 |
63 | /****************************************** MODBUS Command Function ******************************************************/
64 | funcState_t Modbus_ReadHoldingRegister(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg);
65 | funcState_t Modbus_WriteSingleRegister(uint8_t SlaveID, uint16_t RegAddress, uint16_t RegValue);
66 |
67 | funcState_t Modbus_ReadCoil(uint8_t SlaveID, uint16_t StartAddress, int16_t NumberOfCoil);
68 | funcState_t Modbus_WriteSingleCoil(uint8_t SlaveID, uint16_t RegAddress, coilState_t CoilState);
69 |
70 | funcState_t Modbus_WriteMultipleCoils(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfCoils, char *coilValue);
71 | funcState_t Modbus_WriteMultipleRegisters(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg, uint16_t *regValue);
72 | /**************************************************************************************************************************/
73 | uint8_t findByte(int16_t NumberOfCoil);
74 | uint16_t MODBUS_CRC16(char *buf, uint8_t len );
75 |
76 | #endif /* INC_MODBUSRTU_MASTER_H_ */
77 |
--------------------------------------------------------------------------------
/Core/Inc/main.h:
--------------------------------------------------------------------------------
1 | /* USER CODE BEGIN Header */
2 | /**
3 | ******************************************************************************
4 | * @file : main.h
5 | * @brief : Header for main.c file.
6 | * This file contains the common defines of the application.
7 | ******************************************************************************
8 | * @attention
9 | *
10 | *
© Copyright (c) 2022 STMicroelectronics.
11 | * All rights reserved.
12 | *
13 | * This software component is licensed by ST under BSD 3-Clause license,
14 | * the "License"; You may not use this file except in compliance with the
15 | * License. You may obtain a copy of the License at:
16 | * opensource.org/licenses/BSD-3-Clause
17 | *
18 | ******************************************************************************
19 | */
20 | /* USER CODE END Header */
21 |
22 | /* Define to prevent recursive inclusion -------------------------------------*/
23 | #ifndef __MAIN_H
24 | #define __MAIN_H
25 |
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif
29 |
30 | /* Includes ------------------------------------------------------------------*/
31 | #include "stm32f4xx_hal.h"
32 |
33 | /* Private includes ----------------------------------------------------------*/
34 | /* USER CODE BEGIN Includes */
35 |
36 | /* USER CODE END Includes */
37 |
38 | /* Exported types ------------------------------------------------------------*/
39 | /* USER CODE BEGIN ET */
40 |
41 | /* USER CODE END ET */
42 |
43 | /* Exported constants --------------------------------------------------------*/
44 | /* USER CODE BEGIN EC */
45 |
46 | /* USER CODE END EC */
47 |
48 | /* Exported macro ------------------------------------------------------------*/
49 | /* USER CODE BEGIN EM */
50 |
51 | /* USER CODE END EM */
52 |
53 | /* Exported functions prototypes ---------------------------------------------*/
54 | void Error_Handler(void);
55 |
56 | /* USER CODE BEGIN EFP */
57 |
58 | /* USER CODE END EFP */
59 |
60 | /* Private defines -----------------------------------------------------------*/
61 | /* USER CODE BEGIN Private defines */
62 |
63 | /* USER CODE END Private defines */
64 |
65 | #ifdef __cplusplus
66 | }
67 | #endif
68 |
69 | #endif /* __MAIN_H */
70 |
71 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
72 |
--------------------------------------------------------------------------------
/Core/Inc/stm32f4xx_hal_conf.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file stm32f4xx_hal_conf_template.h
4 | * @author MCD Application Team
5 | * @brief HAL configuration template file.
6 | * This file should be copied to the application folder and renamed
7 | * to stm32f4xx_hal_conf.h.
8 | ******************************************************************************
9 | * @attention
10 | *
11 | * © Copyright (c) 2017 STMicroelectronics.
12 | * All rights reserved.
13 | *
14 | * This software component is licensed by ST under BSD 3-Clause license,
15 | * the "License"; You may not use this file except in compliance with the
16 | * License. You may obtain a copy of the License at:
17 | * opensource.org/licenses/BSD-3-Clause
18 | *
19 | ******************************************************************************
20 | */
21 |
22 | /* Define to prevent recursive inclusion -------------------------------------*/
23 | #ifndef __STM32F4xx_HAL_CONF_H
24 | #define __STM32F4xx_HAL_CONF_H
25 |
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif
29 |
30 | /* Exported types ------------------------------------------------------------*/
31 | /* Exported constants --------------------------------------------------------*/
32 |
33 | /* ########################## Module Selection ############################## */
34 | /**
35 | * @brief This is the list of modules to be used in the HAL driver
36 | */
37 | #define HAL_MODULE_ENABLED
38 |
39 | /* #define HAL_ADC_MODULE_ENABLED */
40 | /* #define HAL_CRYP_MODULE_ENABLED */
41 | /* #define HAL_CAN_MODULE_ENABLED */
42 | /* #define HAL_CRC_MODULE_ENABLED */
43 | /* #define HAL_CAN_LEGACY_MODULE_ENABLED */
44 | /* #define HAL_CRYP_MODULE_ENABLED */
45 | /* #define HAL_DAC_MODULE_ENABLED */
46 | /* #define HAL_DCMI_MODULE_ENABLED */
47 | /* #define HAL_DMA2D_MODULE_ENABLED */
48 | /* #define HAL_ETH_MODULE_ENABLED */
49 | /* #define HAL_NAND_MODULE_ENABLED */
50 | /* #define HAL_NOR_MODULE_ENABLED */
51 | /* #define HAL_PCCARD_MODULE_ENABLED */
52 | /* #define HAL_SRAM_MODULE_ENABLED */
53 | /* #define HAL_SDRAM_MODULE_ENABLED */
54 | /* #define HAL_HASH_MODULE_ENABLED */
55 | /* #define HAL_I2C_MODULE_ENABLED */
56 | /* #define HAL_I2S_MODULE_ENABLED */
57 | /* #define HAL_IWDG_MODULE_ENABLED */
58 | /* #define HAL_LTDC_MODULE_ENABLED */
59 | /* #define HAL_RNG_MODULE_ENABLED */
60 | /* #define HAL_RTC_MODULE_ENABLED */
61 | /* #define HAL_SAI_MODULE_ENABLED */
62 | /* #define HAL_SD_MODULE_ENABLED */
63 | /* #define HAL_MMC_MODULE_ENABLED */
64 | /* #define HAL_SPI_MODULE_ENABLED */
65 | /* #define HAL_TIM_MODULE_ENABLED */
66 | #define HAL_UART_MODULE_ENABLED
67 | /* #define HAL_USART_MODULE_ENABLED */
68 | /* #define HAL_IRDA_MODULE_ENABLED */
69 | /* #define HAL_SMARTCARD_MODULE_ENABLED */
70 | /* #define HAL_SMBUS_MODULE_ENABLED */
71 | /* #define HAL_WWDG_MODULE_ENABLED */
72 | /* #define HAL_PCD_MODULE_ENABLED */
73 | /* #define HAL_HCD_MODULE_ENABLED */
74 | /* #define HAL_DSI_MODULE_ENABLED */
75 | /* #define HAL_QSPI_MODULE_ENABLED */
76 | /* #define HAL_QSPI_MODULE_ENABLED */
77 | /* #define HAL_CEC_MODULE_ENABLED */
78 | /* #define HAL_FMPI2C_MODULE_ENABLED */
79 | /* #define HAL_FMPSMBUS_MODULE_ENABLED */
80 | /* #define HAL_SPDIFRX_MODULE_ENABLED */
81 | /* #define HAL_DFSDM_MODULE_ENABLED */
82 | /* #define HAL_LPTIM_MODULE_ENABLED */
83 | #define HAL_GPIO_MODULE_ENABLED
84 | #define HAL_EXTI_MODULE_ENABLED
85 | #define HAL_DMA_MODULE_ENABLED
86 | #define HAL_RCC_MODULE_ENABLED
87 | #define HAL_FLASH_MODULE_ENABLED
88 | #define HAL_PWR_MODULE_ENABLED
89 | #define HAL_CORTEX_MODULE_ENABLED
90 |
91 | /* ########################## HSE/HSI Values adaptation ##################### */
92 | /**
93 | * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
94 | * This value is used by the RCC HAL module to compute the system frequency
95 | * (when HSE is used as system clock source, directly or through the PLL).
96 | */
97 | #if !defined (HSE_VALUE)
98 | #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
99 | #endif /* HSE_VALUE */
100 |
101 | #if !defined (HSE_STARTUP_TIMEOUT)
102 | #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */
103 | #endif /* HSE_STARTUP_TIMEOUT */
104 |
105 | /**
106 | * @brief Internal High Speed oscillator (HSI) value.
107 | * This value is used by the RCC HAL module to compute the system frequency
108 | * (when HSI is used as system clock source, directly or through the PLL).
109 | */
110 | #if !defined (HSI_VALUE)
111 | #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
112 | #endif /* HSI_VALUE */
113 |
114 | /**
115 | * @brief Internal Low Speed oscillator (LSI) value.
116 | */
117 | #if !defined (LSI_VALUE)
118 | #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/
119 | #endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
120 | The real value may vary depending on the variations
121 | in voltage and temperature.*/
122 | /**
123 | * @brief External Low Speed oscillator (LSE) value.
124 | */
125 | #if !defined (LSE_VALUE)
126 | #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */
127 | #endif /* LSE_VALUE */
128 |
129 | #if !defined (LSE_STARTUP_TIMEOUT)
130 | #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
131 | #endif /* LSE_STARTUP_TIMEOUT */
132 |
133 | /**
134 | * @brief External clock source for I2S peripheral
135 | * This value is used by the I2S HAL module to compute the I2S clock source
136 | * frequency, this source is inserted directly through I2S_CKIN pad.
137 | */
138 | #if !defined (EXTERNAL_CLOCK_VALUE)
139 | #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External audio frequency in Hz*/
140 | #endif /* EXTERNAL_CLOCK_VALUE */
141 |
142 | /* Tip: To avoid modifying this file each time you need to use different HSE,
143 | === you can define the HSE value in your toolchain compiler preprocessor. */
144 |
145 | /* ########################### System Configuration ######################### */
146 | /**
147 | * @brief This is the HAL system configuration section
148 | */
149 | #define VDD_VALUE 3300U /*!< Value of VDD in mv */
150 | #define TICK_INT_PRIORITY 15U /*!< tick interrupt priority */
151 | #define USE_RTOS 0U
152 | #define PREFETCH_ENABLE 1U
153 | #define INSTRUCTION_CACHE_ENABLE 1U
154 | #define DATA_CACHE_ENABLE 1U
155 |
156 | #define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
157 | #define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
158 | #define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
159 | #define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */
160 | #define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
161 | #define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */
162 | #define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */
163 | #define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
164 | #define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */
165 | #define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
166 | #define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */
167 | #define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */
168 | #define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
169 | #define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */
170 | #define USE_HAL_FMPSMBUS_REGISTER_CALLBACKS 0U /* FMPSMBUS register callback disabled */
171 | #define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
172 | #define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
173 | #define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */
174 | #define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */
175 | #define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */
176 | #define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
177 | #define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
178 | #define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */
179 | #define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
180 | #define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
181 | #define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */
182 | #define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
183 | #define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */
184 | #define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */
185 | #define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
186 | #define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */
187 | #define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
188 | #define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */
189 | #define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
190 | #define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
191 | #define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
192 | #define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
193 | #define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
194 | #define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
195 |
196 | /* ########################## Assert Selection ############################## */
197 | /**
198 | * @brief Uncomment the line below to expanse the "assert_param" macro in the
199 | * HAL drivers code
200 | */
201 | /* #define USE_FULL_ASSERT 1U */
202 |
203 | /* ################## Ethernet peripheral configuration ##################### */
204 |
205 | /* Section 1 : Ethernet peripheral configuration */
206 |
207 | /* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
208 | #define MAC_ADDR0 2U
209 | #define MAC_ADDR1 0U
210 | #define MAC_ADDR2 0U
211 | #define MAC_ADDR3 0U
212 | #define MAC_ADDR4 0U
213 | #define MAC_ADDR5 0U
214 |
215 | /* Definition of the Ethernet driver buffers size and count */
216 | #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
217 | #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
218 | #define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
219 | #define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
220 |
221 | /* Section 2: PHY configuration section */
222 |
223 | /* DP83848_PHY_ADDRESS Address*/
224 | #define DP83848_PHY_ADDRESS 0x01U
225 | /* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
226 | #define PHY_RESET_DELAY 0x000000FFU
227 | /* PHY Configuration delay */
228 | #define PHY_CONFIG_DELAY 0x00000FFFU
229 |
230 | #define PHY_READ_TO 0x0000FFFFU
231 | #define PHY_WRITE_TO 0x0000FFFFU
232 |
233 | /* Section 3: Common PHY Registers */
234 |
235 | #define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
236 | #define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
237 |
238 | #define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
239 | #define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
240 | #define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
241 | #define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
242 | #define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
243 | #define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
244 | #define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
245 | #define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
246 | #define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
247 | #define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
248 |
249 | #define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
250 | #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
251 | #define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
252 |
253 | /* Section 4: Extended PHY Registers */
254 | #define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
255 |
256 | #define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
257 | #define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
258 |
259 | /* ################## SPI peripheral configuration ########################## */
260 |
261 | /* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
262 | * Activated: CRC code is present inside driver
263 | * Deactivated: CRC code cleaned from driver
264 | */
265 |
266 | #define USE_SPI_CRC 0U
267 |
268 | /* Includes ------------------------------------------------------------------*/
269 | /**
270 | * @brief Include module's header file
271 | */
272 |
273 | #ifdef HAL_RCC_MODULE_ENABLED
274 | #include "stm32f4xx_hal_rcc.h"
275 | #endif /* HAL_RCC_MODULE_ENABLED */
276 |
277 | #ifdef HAL_GPIO_MODULE_ENABLED
278 | #include "stm32f4xx_hal_gpio.h"
279 | #endif /* HAL_GPIO_MODULE_ENABLED */
280 |
281 | #ifdef HAL_EXTI_MODULE_ENABLED
282 | #include "stm32f4xx_hal_exti.h"
283 | #endif /* HAL_EXTI_MODULE_ENABLED */
284 |
285 | #ifdef HAL_DMA_MODULE_ENABLED
286 | #include "stm32f4xx_hal_dma.h"
287 | #endif /* HAL_DMA_MODULE_ENABLED */
288 |
289 | #ifdef HAL_CORTEX_MODULE_ENABLED
290 | #include "stm32f4xx_hal_cortex.h"
291 | #endif /* HAL_CORTEX_MODULE_ENABLED */
292 |
293 | #ifdef HAL_ADC_MODULE_ENABLED
294 | #include "stm32f4xx_hal_adc.h"
295 | #endif /* HAL_ADC_MODULE_ENABLED */
296 |
297 | #ifdef HAL_CAN_MODULE_ENABLED
298 | #include "stm32f4xx_hal_can.h"
299 | #endif /* HAL_CAN_MODULE_ENABLED */
300 |
301 | #ifdef HAL_CAN_LEGACY_MODULE_ENABLED
302 | #include "stm32f4xx_hal_can_legacy.h"
303 | #endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
304 |
305 | #ifdef HAL_CRC_MODULE_ENABLED
306 | #include "stm32f4xx_hal_crc.h"
307 | #endif /* HAL_CRC_MODULE_ENABLED */
308 |
309 | #ifdef HAL_CRYP_MODULE_ENABLED
310 | #include "stm32f4xx_hal_cryp.h"
311 | #endif /* HAL_CRYP_MODULE_ENABLED */
312 |
313 | #ifdef HAL_DMA2D_MODULE_ENABLED
314 | #include "stm32f4xx_hal_dma2d.h"
315 | #endif /* HAL_DMA2D_MODULE_ENABLED */
316 |
317 | #ifdef HAL_DAC_MODULE_ENABLED
318 | #include "stm32f4xx_hal_dac.h"
319 | #endif /* HAL_DAC_MODULE_ENABLED */
320 |
321 | #ifdef HAL_DCMI_MODULE_ENABLED
322 | #include "stm32f4xx_hal_dcmi.h"
323 | #endif /* HAL_DCMI_MODULE_ENABLED */
324 |
325 | #ifdef HAL_ETH_MODULE_ENABLED
326 | #include "stm32f4xx_hal_eth.h"
327 | #endif /* HAL_ETH_MODULE_ENABLED */
328 |
329 | #ifdef HAL_FLASH_MODULE_ENABLED
330 | #include "stm32f4xx_hal_flash.h"
331 | #endif /* HAL_FLASH_MODULE_ENABLED */
332 |
333 | #ifdef HAL_SRAM_MODULE_ENABLED
334 | #include "stm32f4xx_hal_sram.h"
335 | #endif /* HAL_SRAM_MODULE_ENABLED */
336 |
337 | #ifdef HAL_NOR_MODULE_ENABLED
338 | #include "stm32f4xx_hal_nor.h"
339 | #endif /* HAL_NOR_MODULE_ENABLED */
340 |
341 | #ifdef HAL_NAND_MODULE_ENABLED
342 | #include "stm32f4xx_hal_nand.h"
343 | #endif /* HAL_NAND_MODULE_ENABLED */
344 |
345 | #ifdef HAL_PCCARD_MODULE_ENABLED
346 | #include "stm32f4xx_hal_pccard.h"
347 | #endif /* HAL_PCCARD_MODULE_ENABLED */
348 |
349 | #ifdef HAL_SDRAM_MODULE_ENABLED
350 | #include "stm32f4xx_hal_sdram.h"
351 | #endif /* HAL_SDRAM_MODULE_ENABLED */
352 |
353 | #ifdef HAL_HASH_MODULE_ENABLED
354 | #include "stm32f4xx_hal_hash.h"
355 | #endif /* HAL_HASH_MODULE_ENABLED */
356 |
357 | #ifdef HAL_I2C_MODULE_ENABLED
358 | #include "stm32f4xx_hal_i2c.h"
359 | #endif /* HAL_I2C_MODULE_ENABLED */
360 |
361 | #ifdef HAL_SMBUS_MODULE_ENABLED
362 | #include "stm32f4xx_hal_smbus.h"
363 | #endif /* HAL_SMBUS_MODULE_ENABLED */
364 |
365 | #ifdef HAL_I2S_MODULE_ENABLED
366 | #include "stm32f4xx_hal_i2s.h"
367 | #endif /* HAL_I2S_MODULE_ENABLED */
368 |
369 | #ifdef HAL_IWDG_MODULE_ENABLED
370 | #include "stm32f4xx_hal_iwdg.h"
371 | #endif /* HAL_IWDG_MODULE_ENABLED */
372 |
373 | #ifdef HAL_LTDC_MODULE_ENABLED
374 | #include "stm32f4xx_hal_ltdc.h"
375 | #endif /* HAL_LTDC_MODULE_ENABLED */
376 |
377 | #ifdef HAL_PWR_MODULE_ENABLED
378 | #include "stm32f4xx_hal_pwr.h"
379 | #endif /* HAL_PWR_MODULE_ENABLED */
380 |
381 | #ifdef HAL_RNG_MODULE_ENABLED
382 | #include "stm32f4xx_hal_rng.h"
383 | #endif /* HAL_RNG_MODULE_ENABLED */
384 |
385 | #ifdef HAL_RTC_MODULE_ENABLED
386 | #include "stm32f4xx_hal_rtc.h"
387 | #endif /* HAL_RTC_MODULE_ENABLED */
388 |
389 | #ifdef HAL_SAI_MODULE_ENABLED
390 | #include "stm32f4xx_hal_sai.h"
391 | #endif /* HAL_SAI_MODULE_ENABLED */
392 |
393 | #ifdef HAL_SD_MODULE_ENABLED
394 | #include "stm32f4xx_hal_sd.h"
395 | #endif /* HAL_SD_MODULE_ENABLED */
396 |
397 | #ifdef HAL_SPI_MODULE_ENABLED
398 | #include "stm32f4xx_hal_spi.h"
399 | #endif /* HAL_SPI_MODULE_ENABLED */
400 |
401 | #ifdef HAL_TIM_MODULE_ENABLED
402 | #include "stm32f4xx_hal_tim.h"
403 | #endif /* HAL_TIM_MODULE_ENABLED */
404 |
405 | #ifdef HAL_UART_MODULE_ENABLED
406 | #include "stm32f4xx_hal_uart.h"
407 | #endif /* HAL_UART_MODULE_ENABLED */
408 |
409 | #ifdef HAL_USART_MODULE_ENABLED
410 | #include "stm32f4xx_hal_usart.h"
411 | #endif /* HAL_USART_MODULE_ENABLED */
412 |
413 | #ifdef HAL_IRDA_MODULE_ENABLED
414 | #include "stm32f4xx_hal_irda.h"
415 | #endif /* HAL_IRDA_MODULE_ENABLED */
416 |
417 | #ifdef HAL_SMARTCARD_MODULE_ENABLED
418 | #include "stm32f4xx_hal_smartcard.h"
419 | #endif /* HAL_SMARTCARD_MODULE_ENABLED */
420 |
421 | #ifdef HAL_WWDG_MODULE_ENABLED
422 | #include "stm32f4xx_hal_wwdg.h"
423 | #endif /* HAL_WWDG_MODULE_ENABLED */
424 |
425 | #ifdef HAL_PCD_MODULE_ENABLED
426 | #include "stm32f4xx_hal_pcd.h"
427 | #endif /* HAL_PCD_MODULE_ENABLED */
428 |
429 | #ifdef HAL_HCD_MODULE_ENABLED
430 | #include "stm32f4xx_hal_hcd.h"
431 | #endif /* HAL_HCD_MODULE_ENABLED */
432 |
433 | #ifdef HAL_DSI_MODULE_ENABLED
434 | #include "stm32f4xx_hal_dsi.h"
435 | #endif /* HAL_DSI_MODULE_ENABLED */
436 |
437 | #ifdef HAL_QSPI_MODULE_ENABLED
438 | #include "stm32f4xx_hal_qspi.h"
439 | #endif /* HAL_QSPI_MODULE_ENABLED */
440 |
441 | #ifdef HAL_CEC_MODULE_ENABLED
442 | #include "stm32f4xx_hal_cec.h"
443 | #endif /* HAL_CEC_MODULE_ENABLED */
444 |
445 | #ifdef HAL_FMPI2C_MODULE_ENABLED
446 | #include "stm32f4xx_hal_fmpi2c.h"
447 | #endif /* HAL_FMPI2C_MODULE_ENABLED */
448 |
449 | #ifdef HAL_FMPSMBUS_MODULE_ENABLED
450 | #include "stm32f4xx_hal_fmpsmbus.h"
451 | #endif /* HAL_FMPSMBUS_MODULE_ENABLED */
452 |
453 | #ifdef HAL_SPDIFRX_MODULE_ENABLED
454 | #include "stm32f4xx_hal_spdifrx.h"
455 | #endif /* HAL_SPDIFRX_MODULE_ENABLED */
456 |
457 | #ifdef HAL_DFSDM_MODULE_ENABLED
458 | #include "stm32f4xx_hal_dfsdm.h"
459 | #endif /* HAL_DFSDM_MODULE_ENABLED */
460 |
461 | #ifdef HAL_LPTIM_MODULE_ENABLED
462 | #include "stm32f4xx_hal_lptim.h"
463 | #endif /* HAL_LPTIM_MODULE_ENABLED */
464 |
465 | #ifdef HAL_MMC_MODULE_ENABLED
466 | #include "stm32f4xx_hal_mmc.h"
467 | #endif /* HAL_MMC_MODULE_ENABLED */
468 |
469 | /* Exported macro ------------------------------------------------------------*/
470 | #ifdef USE_FULL_ASSERT
471 | /**
472 | * @brief The assert_param macro is used for function's parameters check.
473 | * @param expr If expr is false, it calls assert_failed function
474 | * which reports the name of the source file and the source
475 | * line number of the call that failed.
476 | * If expr is true, it returns no value.
477 | * @retval None
478 | */
479 | #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
480 | /* Exported functions ------------------------------------------------------- */
481 | void assert_failed(uint8_t* file, uint32_t line);
482 | #else
483 | #define assert_param(expr) ((void)0U)
484 | #endif /* USE_FULL_ASSERT */
485 |
486 | #ifdef __cplusplus
487 | }
488 | #endif
489 |
490 | #endif /* __STM32F4xx_HAL_CONF_H */
491 |
492 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
493 |
--------------------------------------------------------------------------------
/Core/Inc/stm32f4xx_it.h:
--------------------------------------------------------------------------------
1 | /* USER CODE BEGIN Header */
2 | /**
3 | ******************************************************************************
4 | * @file stm32f4xx_it.h
5 | * @brief This file contains the headers of the interrupt handlers.
6 | ******************************************************************************
7 | * @attention
8 | *
9 | * © Copyright (c) 2022 STMicroelectronics.
10 | * All rights reserved.
11 | *
12 | * This software component is licensed by ST under BSD 3-Clause license,
13 | * the "License"; You may not use this file except in compliance with the
14 | * License. You may obtain a copy of the License at:
15 | * opensource.org/licenses/BSD-3-Clause
16 | *
17 | ******************************************************************************
18 | */
19 | /* USER CODE END Header */
20 |
21 | /* Define to prevent recursive inclusion -------------------------------------*/
22 | #ifndef __STM32F4xx_IT_H
23 | #define __STM32F4xx_IT_H
24 |
25 | #ifdef __cplusplus
26 | extern "C" {
27 | #endif
28 |
29 | /* Private includes ----------------------------------------------------------*/
30 | /* USER CODE BEGIN Includes */
31 |
32 | /* USER CODE END Includes */
33 |
34 | /* Exported types ------------------------------------------------------------*/
35 | /* USER CODE BEGIN ET */
36 |
37 | /* USER CODE END ET */
38 |
39 | /* Exported constants --------------------------------------------------------*/
40 | /* USER CODE BEGIN EC */
41 |
42 | /* USER CODE END EC */
43 |
44 | /* Exported macro ------------------------------------------------------------*/
45 | /* USER CODE BEGIN EM */
46 |
47 | /* USER CODE END EM */
48 |
49 | /* Exported functions prototypes ---------------------------------------------*/
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 USART2_IRQHandler(void);
60 | /* USER CODE BEGIN EFP */
61 |
62 | /* USER CODE END EFP */
63 |
64 | #ifdef __cplusplus
65 | }
66 | #endif
67 |
68 | #endif /* __STM32F4xx_IT_H */
69 |
70 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
71 |
--------------------------------------------------------------------------------
/Core/Src/ModbusRTU_Master.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ModbusRTU_Master.c
3 | *
4 | * Created on: Feb 17, 2022
5 | * Author: Ümit Can Güveren
6 | */
7 |
8 | #include
9 | #include "main.h"
10 |
11 |
12 | extern UART_HandleTypeDef huart2;
13 | uint8_t BytetoBit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
14 |
15 |
16 | funcState_t sendMessage(char *msg, uint16_t len)
17 | {
18 | uartState_t stateTx;
19 |
20 | stateTx = HAL_UART_Transmit_IT(&huart2, (uint8_t *)msg, len);
21 |
22 | if(stateTx == uartOkState)
23 | {
24 | return funcOk;
25 | }
26 | else
27 | {
28 | return funcErr;
29 | }
30 | }
31 |
32 | funcState_t takeMessage(char *msg, uint16_t len, uint8_t SlaveID)
33 | {
34 | uartState_t stateRx;
35 | crcState_t crcCheck;
36 | uint16_t CRCVal, rxCRC;
37 |
38 | stateRx = HAL_UART_Receive(&huart2, (uint8_t *)msg, len, 100);
39 |
40 |
41 | rxCRC = (msg[len -1] << 8) | (msg[len - 2]);
42 | CRCVal = MODBUS_CRC16(msg, len - 2);
43 |
44 | if(CRCVal == rxCRC)
45 | {
46 | crcCheck = crcOk;
47 | }
48 | else
49 | {
50 | crcCheck = crcErr;
51 | }
52 |
53 | if(stateRx == uartOkState && crcCheck == crcOk && msg[0] == SLAVEID)
54 | {
55 | return funcOk;
56 | }
57 | else
58 | {
59 | return funcErr;
60 | }
61 |
62 | }
63 |
64 |
65 | /*
66 | * @brief Modbus_ReadHoldingRegister, Reads Holding Register #0x03
67 | *
68 | * @param SlaveID = Slave address to be read
69 | *
70 | * @param StartAddress = First address of the register to be read
71 | *
72 | * @param NumberOfReg = Number of register to be read
73 | *
74 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
75 | */
76 | funcState_t Modbus_ReadHoldingRegister(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg)
77 | {
78 | uint16_t CRCVal = 0;
79 | funcState_t funcTxState, funcRxState;
80 | uint8_t i, m = 0;
81 |
82 | char ModbusRx[BUFFERSIZE];
83 | char ModbusTx[8];
84 |
85 | memset(ModbusTx, 0, 8);
86 |
87 | ModbusTx[0] = SlaveID;
88 | ModbusTx[1] = ReadHoldingRegister;
89 | ModbusTx[2] = StartAddress >> 8;
90 | ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
91 | ModbusTx[4] = NumberOfReg >> 8;
92 | ModbusTx[5] = (uint8_t)(NumberOfReg & 0x00FF);
93 |
94 | CRCVal = MODBUS_CRC16(ModbusTx, 6);
95 |
96 | ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
97 | ModbusTx[7] = CRCVal >> 8;
98 |
99 | funcTxState = sendMessage(&ModbusTx[0], 8);
100 |
101 | if(funcTxState == funcOk)
102 | {
103 | funcRxState = takeMessage(ModbusRx, 5 + (NumberOfReg * 2), SlaveID);
104 | }
105 | if(funcRxState == funcOk)
106 | {
107 | for(i = 0; i < NumberOfReg; i++)
108 | {
109 | ModbusRegister[StartAddress + i] = (uint16_t)((ModbusRx[3 + m] << 8) | (ModbusRx[4 + m]));
110 | m += 2;
111 | }
112 | }
113 |
114 | return funcRxState;
115 | }
116 |
117 | /*
118 | * @brief Modbus_ReadHoldingRegister, Reads Holding Register #0x03
119 | *
120 | * @param SlaveID = Slave address to be read
121 | *
122 | * @param RegAddress = Address of the register to be write
123 | *
124 | * @param RegValue = Value to be write to register
125 | *
126 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
127 | */
128 | funcState_t Modbus_WriteSingleRegister(uint8_t SlaveID, uint16_t RegAddress, uint16_t RegValue)
129 | {
130 | uint16_t CRCVal = 0;
131 | funcState_t funcTxState, funcRxState;
132 |
133 | char ModbusRx[BUFFERSIZE];
134 | char ModbusTx[8];
135 |
136 | memset(ModbusTx, 0, 8);
137 |
138 | ModbusTx[0] = SlaveID;
139 | ModbusTx[1] = WriteSingleRegister;
140 | ModbusTx[2] = (uint8_t)(RegAddress >> 8);
141 | ModbusTx[3] = (uint8_t)(RegAddress & 0x00FF);
142 | ModbusTx[4] = (uint8_t)(RegValue >> 8);
143 | ModbusTx[5] = (uint8_t)(RegValue & 0x00FF);
144 |
145 | CRCVal = MODBUS_CRC16(ModbusTx, 6);
146 |
147 | ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
148 | ModbusTx[7] = CRCVal >> 8;
149 |
150 | funcTxState = sendMessage(&ModbusTx[0], 8);
151 |
152 | if(funcTxState == funcOk)
153 | {
154 | funcRxState = takeMessage(ModbusRx, 8, SlaveID);
155 | }
156 |
157 | return funcRxState; //CRC and ID is true.
158 | }
159 |
160 |
161 | /*
162 | * @brief Modbus_ReadCoil, Reads Coils #0x01
163 | *
164 | * @param SlaveID = Slave address to be read
165 | *
166 | * @param StartAddress = First address of the coil to be read
167 | *
168 | * @param NumberOfCoil = Number of coils to be read
169 | *
170 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
171 | */
172 | funcState_t Modbus_ReadCoil(uint8_t SlaveID, uint16_t StartAddress, int16_t NumberOfCoil)
173 | {
174 | uint16_t CRCVal = 0, Modbus_i, ByteCounter = 0, BitCounter = 0;
175 |
176 | funcState_t funcTxState, funcRxState;
177 | char ModbusRx[BUFFERSIZE];
178 | char ModbusTx[8];
179 |
180 | uint8_t NumberOfByte;
181 |
182 | NumberOfByte = findByte(NumberOfCoil);
183 |
184 | ModbusTx[0] = SlaveID;
185 | ModbusTx[1] = ReadCoil;
186 | ModbusTx[2] = (uint8_t)(StartAddress >> 8);
187 | ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
188 | ModbusTx[4] = (uint8_t)(NumberOfCoil >> 8);
189 | ModbusTx[5] = (uint8_t)(NumberOfCoil & 0x00FF);
190 |
191 | CRCVal = MODBUS_CRC16(ModbusTx, 6);
192 |
193 | ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
194 | ModbusTx[7] = CRCVal >> 8;
195 |
196 | funcTxState = sendMessage(&ModbusTx[0], 8);
197 |
198 | if(funcTxState == funcOk)
199 | {
200 | funcRxState = takeMessage(ModbusRx, 5 + NumberOfByte, SlaveID);
201 | }
202 |
203 | if(funcRxState == funcOk)
204 | {
205 | for(Modbus_i = 0; Modbus_i < NumberOfCoil; Modbus_i++)
206 | {
207 | ModbusCoil[StartAddress + Modbus_i] = (bool)(ModbusRx[3 + ByteCounter] & BytetoBit[BitCounter]);
208 |
209 | BitCounter++;
210 |
211 | if(Modbus_i % 8 == 7)
212 | {
213 | ByteCounter++;
214 | BitCounter = 0;
215 | }
216 | }
217 | }
218 | return funcRxState;
219 | }
220 |
221 | /*
222 | * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x05
223 | *
224 | * @param SlaveID = Slave address to be read
225 | *
226 | * @param RegAddress = First address of the coil to be write
227 | *
228 | * @param CoilState = coilOn or coilOff @def group coilState_t
229 | *
230 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
231 | */
232 | funcState_t Modbus_WriteSingleCoil(uint8_t SlaveID, uint16_t RegAddress, coilState_t CoilState)
233 | {
234 | uint16_t CRCVal = 0;
235 |
236 | funcState_t funcTxState, funcRxState;
237 | char ModbusRx[BUFFERSIZE];
238 | char ModbusTx[8];
239 |
240 | ModbusTx[0] = SlaveID;
241 | ModbusTx[1] = WriteSingleCoil;
242 | ModbusTx[2] = (uint8_t)(RegAddress >> 8);
243 | ModbusTx[3] = (uint8_t)(RegAddress & 0x00FF);
244 | ModbusTx[4] = CoilState;
245 | ModbusTx[5] = 0x00;
246 |
247 | CRCVal = MODBUS_CRC16(ModbusTx, 6);
248 |
249 | ModbusTx[6] = (uint8_t)(CRCVal & 0x00FF);
250 | ModbusTx[7] = CRCVal >> 8;
251 |
252 | funcTxState = sendMessage(&ModbusTx[0], 8);
253 |
254 | if(funcTxState == funcOk)
255 | {
256 | funcRxState = takeMessage(ModbusRx, 8, SlaveID);
257 | }
258 |
259 | return funcRxState; //CRC and ID is true.
260 | }
261 |
262 | /*
263 | * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x15
264 | *
265 | * @param SlaveID = Slave address to be read
266 | *
267 | * @param StartAddress = First address of the coil to be read
268 | *
269 | * @param NumberOfCoils = Number of coils to be write
270 | *
271 | * @param coilValue = Array of values to write to coils
272 | *
273 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
274 | */
275 | funcState_t Modbus_WriteMultipleCoils(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfCoils, char *coilValue)
276 | {
277 | uint16_t CRCVal = 0;
278 | uint8_t i, NumberOfByte;
279 | funcState_t funcTxState, funcRxState;
280 | char ModbusRx[BUFFERSIZE];
281 | char ModbusTx[8];
282 |
283 | ModbusTx[0] = SlaveID;
284 | ModbusTx[1] = WriteMultipleCoils;
285 | ModbusTx[2] = (uint8_t)(StartAddress >> 8);
286 | ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
287 | ModbusTx[4] = (uint8_t)(NumberOfCoils >> 8);
288 | ModbusTx[5] = (uint8_t)(NumberOfCoils & 0x00FF);
289 |
290 | NumberOfByte = findByte(NumberOfCoils - 1);
291 |
292 | ModbusTx[6] = NumberOfByte;
293 |
294 | for(i = 0; i < NumberOfByte ; i++)
295 | {
296 | ModbusTx[7 + i] = coilValue[i];
297 | }
298 |
299 | CRCVal = MODBUS_CRC16(ModbusTx, 8 + i);
300 |
301 | ModbusTx[8 + i] = (uint8_t)(CRCVal & 0x00FF);
302 | ModbusTx[9 + i] = CRCVal >> 8;
303 |
304 | funcTxState = sendMessage(&ModbusTx[0], 10 + i);
305 |
306 | if(funcTxState == funcOk)
307 | {
308 | funcRxState = takeMessage(ModbusRx, 8, SlaveID);
309 | }
310 |
311 | return funcRxState; //CRC and ID is true.
312 | }
313 |
314 | /*
315 | * @brief Modbus_WriteSingleCoil, Writes Holding Register #0x16
316 | *
317 | * @param SlaveID = Slave address to be read
318 | *
319 | * @param StartAddress = First address of the coil to be read
320 | *
321 | * @param NumberOfReg = Number of registers to be write
322 | *
323 | * @param regValue = Array of values to write to registers
324 | *
325 | * @funcState_t returns funcOk if the received data CRC and SlaveID is true after the sent data
326 | */
327 | funcState_t Modbus_WriteMultipleRegisters(uint8_t SlaveID, uint16_t StartAddress, uint16_t NumberOfReg, uint16_t *regValue)
328 | {
329 | uint16_t CRCVal = 0;
330 | uint8_t i, m = 0;
331 | funcState_t funcTxState, funcRxState;
332 | char ModbusRx[BUFFERSIZE];
333 | char ModbusTx[8];
334 |
335 | ModbusTx[0] = SlaveID;
336 | ModbusTx[1] = WriteMultipleRegisters;
337 | ModbusTx[2] = (uint8_t)(StartAddress >> 8);
338 | ModbusTx[3] = (uint8_t)(StartAddress & 0x00FF);
339 | ModbusTx[4] = (uint8_t)(NumberOfReg >> 8);
340 | ModbusTx[5] = (uint8_t)(NumberOfReg & 0x00FF);
341 | ModbusTx[6] = NumberOfReg * 2;
342 |
343 | for(i = 0; i < NumberOfReg * 2 ; i += 2)
344 | {
345 | ModbusTx[7 + i] = (uint8_t)(regValue[m] >> 8);
346 | ModbusTx[8 + i] = (uint8_t)(regValue[m] & 0x00FF);
347 | m++;
348 | }
349 |
350 | CRCVal = MODBUS_CRC16(ModbusTx, 8 + i);
351 |
352 | ModbusTx[8 + i] = (uint8_t)(CRCVal & 0x00FF);
353 | ModbusTx[9 + i] = CRCVal >> 8;
354 |
355 | funcTxState = sendMessage(&ModbusTx[0], 10 + i);
356 |
357 | if(funcTxState == funcOk)
358 | {
359 | funcRxState = takeMessage(ModbusRx, 8, SlaveID);
360 | }
361 |
362 | return funcRxState; //CRC and ID is true.
363 | }
364 |
365 |
366 | uint8_t findByte(int16_t NumberOfCoil)
367 | {
368 | volatile uint8_t NumberOfByte = 0;
369 |
370 | while(NumberOfCoil >= 0)
371 | {
372 | NumberOfCoil -= 8;
373 |
374 | NumberOfByte++;
375 | if(NumberOfCoil < 0)
376 | {
377 | break;
378 | }
379 | }
380 | return NumberOfByte;
381 | }
382 |
383 | uint16_t MODBUS_CRC16(char *buf, uint8_t len )
384 | {
385 | static const uint16_t table[2] = { 0x0000, 0xA001 };
386 | uint16_t crc = 0xFFFF;
387 | unsigned int i = 0;
388 | char bit = 0;
389 | unsigned int xor = 0;
390 |
391 | for( i = 0; i < len; i++ )
392 | {
393 | crc ^= buf[i];
394 |
395 | for( bit = 0; bit < 8; bit++ )
396 | {
397 | xor = crc & 0x01;
398 | crc >>= 1;
399 | crc ^= table[xor];
400 | }
401 | }
402 |
403 | return crc;
404 | }
405 |
--------------------------------------------------------------------------------
/Core/Src/main.c:
--------------------------------------------------------------------------------
1 | /* USER CODE BEGIN Header */
2 | /**
3 | ******************************************************************************
4 | * @file : main.c
5 | * @brief : Main program body
6 | ******************************************************************************
7 | * @attention
8 | *
9 | * © Copyright (c) 2022 STMicroelectronics.
10 | * All rights reserved.
11 | *
12 | * This software component is licensed by ST under BSD 3-Clause license,
13 | * the "License"; You may not use this file except in compliance with the
14 | * License. You may obtain a copy of the License at:
15 | * opensource.org/licenses/BSD-3-Clause
16 | *
17 | ******************************************************************************
18 | */
19 | /* USER CODE END Header */
20 | /* Includes ------------------------------------------------------------------*/
21 | #include "main.h"
22 |
23 | /* Private includes ----------------------------------------------------------*/
24 | /* USER CODE BEGIN Includes */
25 | #include "ModbusRTU_Master.h"
26 | /* USER CODE END Includes */
27 |
28 | /* Private typedef -----------------------------------------------------------*/
29 | /* USER CODE BEGIN PTD */
30 |
31 | /* USER CODE END PTD */
32 |
33 | /* Private define ------------------------------------------------------------*/
34 | /* USER CODE BEGIN PD */
35 | /* USER CODE END PD */
36 |
37 | /* Private macro -------------------------------------------------------------*/
38 | /* USER CODE BEGIN PM */
39 |
40 | /* USER CODE END PM */
41 |
42 | /* Private variables ---------------------------------------------------------*/
43 | UART_HandleTypeDef huart2;
44 |
45 | /* USER CODE BEGIN PV */
46 |
47 | /* USER CODE END PV */
48 |
49 | /* Private function prototypes -----------------------------------------------*/
50 | void SystemClock_Config(void);
51 | static void MX_GPIO_Init(void);
52 | static void MX_USART2_UART_Init(void);
53 | /* USER CODE BEGIN PFP */
54 |
55 | /* USER CODE END PFP */
56 |
57 | /* Private user code ---------------------------------------------------------*/
58 | /* USER CODE BEGIN 0 */
59 | uint8_t count;
60 | char coilValue[1] = {0x0F};
61 | uint16_t regValue[2] = {5, 10};
62 | /* USER CODE END 0 */
63 |
64 | /**
65 | * @brief The application entry point.
66 | * @retval int
67 | */
68 | int main(void)
69 | {
70 | /* USER CODE BEGIN 1 */
71 |
72 | /* USER CODE END 1 */
73 |
74 | /* MCU Configuration--------------------------------------------------------*/
75 |
76 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
77 | HAL_Init();
78 |
79 | /* USER CODE BEGIN Init */
80 |
81 | /* USER CODE END Init */
82 |
83 | /* Configure the system clock */
84 | SystemClock_Config();
85 |
86 | /* USER CODE BEGIN SysInit */
87 |
88 | /* USER CODE END SysInit */
89 |
90 | /* Initialize all configured peripherals */
91 | MX_GPIO_Init();
92 | MX_USART2_UART_Init();
93 | /* USER CODE BEGIN 2 */
94 |
95 | /* USER CODE END 2 */
96 |
97 | /* Infinite loop */
98 | /* USER CODE BEGIN WHILE */
99 | while (1)
100 | {
101 | /* USER CODE END WHILE */
102 |
103 | /* USER CODE BEGIN 3 */
104 | HAL_Delay(1000);
105 | Modbus_WriteMultipleRegisters(1, 0, 2, ®Value[0]);
106 | //Modbus_WriteMultipleCoils(1, 0, 8, &coilValue[0]);
107 | //Modbus_ReadCoil(1, 0, 10);
108 | //HAL_Delay(1000);
109 | //Modbus_WriteSingleCoil(1, 5, coilOn);
110 | //Modbus_ReadHoldingRegister(1, 0, 5);
111 | //HAL_Delay(1000);
112 | //Modbus_WriteSingleRegister(1, 3, count++);
113 | }
114 | /* USER CODE END 3 */
115 | }
116 |
117 | /**
118 | * @brief System Clock Configuration
119 | * @retval None
120 | */
121 | void SystemClock_Config(void)
122 | {
123 | RCC_OscInitTypeDef RCC_OscInitStruct = {0};
124 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
125 |
126 | /** Configure the main internal regulator output voltage
127 | */
128 | __HAL_RCC_PWR_CLK_ENABLE();
129 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
130 | /** Initializes the RCC Oscillators according to the specified parameters
131 | * in the RCC_OscInitTypeDef structure.
132 | */
133 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
134 | RCC_OscInitStruct.HSIState = RCC_HSI_ON;
135 | RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
136 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
137 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
138 | {
139 | Error_Handler();
140 | }
141 | /** Initializes the CPU, AHB and APB buses clocks
142 | */
143 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
144 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
145 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
146 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
147 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
148 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
149 |
150 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
151 | {
152 | Error_Handler();
153 | }
154 | }
155 |
156 | /**
157 | * @brief USART2 Initialization Function
158 | * @param None
159 | * @retval None
160 | */
161 | static void MX_USART2_UART_Init(void)
162 | {
163 |
164 | /* USER CODE BEGIN USART2_Init 0 */
165 |
166 | /* USER CODE END USART2_Init 0 */
167 |
168 | /* USER CODE BEGIN USART2_Init 1 */
169 |
170 | /* USER CODE END USART2_Init 1 */
171 | huart2.Instance = USART2;
172 | huart2.Init.BaudRate = 115200;
173 | huart2.Init.WordLength = UART_WORDLENGTH_8B;
174 | huart2.Init.StopBits = UART_STOPBITS_1;
175 | huart2.Init.Parity = UART_PARITY_NONE;
176 | huart2.Init.Mode = UART_MODE_TX_RX;
177 | huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
178 | huart2.Init.OverSampling = UART_OVERSAMPLING_16;
179 | if (HAL_UART_Init(&huart2) != HAL_OK)
180 | {
181 | Error_Handler();
182 | }
183 | /* USER CODE BEGIN USART2_Init 2 */
184 |
185 | /* USER CODE END USART2_Init 2 */
186 |
187 | }
188 |
189 | /**
190 | * @brief GPIO Initialization Function
191 | * @param None
192 | * @retval None
193 | */
194 | static void MX_GPIO_Init(void)
195 | {
196 | GPIO_InitTypeDef GPIO_InitStruct = {0};
197 |
198 | /* GPIO Ports Clock Enable */
199 | __HAL_RCC_GPIOA_CLK_ENABLE();
200 | __HAL_RCC_GPIOD_CLK_ENABLE();
201 |
202 | /*Configure GPIO pin Output Level */
203 | HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
204 |
205 | /*Configure GPIO pins : PD12 PD13 PD14 PD15 */
206 | GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
207 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
208 | GPIO_InitStruct.Pull = GPIO_NOPULL;
209 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
210 | HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
211 |
212 | }
213 |
214 | /* USER CODE BEGIN 4 */
215 |
216 | /* USER CODE END 4 */
217 |
218 | /**
219 | * @brief This function is executed in case of error occurrence.
220 | * @retval None
221 | */
222 | void Error_Handler(void)
223 | {
224 | /* USER CODE BEGIN Error_Handler_Debug */
225 | /* User can add his own implementation to report the HAL error return state */
226 | __disable_irq();
227 | while (1)
228 | {
229 | }
230 | /* USER CODE END Error_Handler_Debug */
231 | }
232 |
233 | #ifdef USE_FULL_ASSERT
234 | /**
235 | * @brief Reports the name of the source file and the source line number
236 | * where the assert_param error has occurred.
237 | * @param file: pointer to the source file name
238 | * @param line: assert_param error line source number
239 | * @retval None
240 | */
241 | void assert_failed(uint8_t *file, uint32_t line)
242 | {
243 | /* USER CODE BEGIN 6 */
244 | /* User can add his own implementation to report the file name and line number,
245 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
246 | /* USER CODE END 6 */
247 | }
248 | #endif /* USE_FULL_ASSERT */
249 |
250 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
251 |
--------------------------------------------------------------------------------
/Core/Src/stm32f4xx_hal_msp.c:
--------------------------------------------------------------------------------
1 | /* USER CODE BEGIN Header */
2 | /**
3 | ******************************************************************************
4 | * @file stm32f4xx_hal_msp.c
5 | * @brief This file provides code for the MSP Initialization
6 | * and de-Initialization codes.
7 | ******************************************************************************
8 | * @attention
9 | *
10 | * © Copyright (c) 2022 STMicroelectronics.
11 | * All rights reserved.
12 | *
13 | * This software component is licensed by ST under BSD 3-Clause license,
14 | * the "License"; You may not use this file except in compliance with the
15 | * License. You may obtain a copy of the License at:
16 | * opensource.org/licenses/BSD-3-Clause
17 | *
18 | ******************************************************************************
19 | */
20 | /* USER CODE END Header */
21 |
22 | /* Includes ------------------------------------------------------------------*/
23 | #include "main.h"
24 | /* USER CODE BEGIN Includes */
25 |
26 | /* USER CODE END Includes */
27 |
28 | /* Private typedef -----------------------------------------------------------*/
29 | /* USER CODE BEGIN TD */
30 |
31 | /* USER CODE END TD */
32 |
33 | /* Private define ------------------------------------------------------------*/
34 | /* USER CODE BEGIN Define */
35 |
36 | /* USER CODE END Define */
37 |
38 | /* Private macro -------------------------------------------------------------*/
39 | /* USER CODE BEGIN Macro */
40 |
41 | /* USER CODE END Macro */
42 |
43 | /* Private variables ---------------------------------------------------------*/
44 | /* USER CODE BEGIN PV */
45 |
46 | /* USER CODE END PV */
47 |
48 | /* Private function prototypes -----------------------------------------------*/
49 | /* USER CODE BEGIN PFP */
50 |
51 | /* USER CODE END PFP */
52 |
53 | /* External functions --------------------------------------------------------*/
54 | /* USER CODE BEGIN ExternalFunctions */
55 |
56 | /* USER CODE END ExternalFunctions */
57 |
58 | /* USER CODE BEGIN 0 */
59 |
60 | /* USER CODE END 0 */
61 | /**
62 | * Initializes the Global MSP.
63 | */
64 | void HAL_MspInit(void)
65 | {
66 | /* USER CODE BEGIN MspInit 0 */
67 |
68 | /* USER CODE END MspInit 0 */
69 |
70 | __HAL_RCC_SYSCFG_CLK_ENABLE();
71 | __HAL_RCC_PWR_CLK_ENABLE();
72 |
73 | /* System interrupt init*/
74 |
75 | /* USER CODE BEGIN MspInit 1 */
76 |
77 | /* USER CODE END MspInit 1 */
78 | }
79 |
80 | /**
81 | * @brief UART MSP Initialization
82 | * This function configures the hardware resources used in this example
83 | * @param huart: UART handle pointer
84 | * @retval None
85 | */
86 | void HAL_UART_MspInit(UART_HandleTypeDef* huart)
87 | {
88 | GPIO_InitTypeDef GPIO_InitStruct = {0};
89 | if(huart->Instance==USART2)
90 | {
91 | /* USER CODE BEGIN USART2_MspInit 0 */
92 |
93 | /* USER CODE END USART2_MspInit 0 */
94 | /* Peripheral clock enable */
95 | __HAL_RCC_USART2_CLK_ENABLE();
96 |
97 | __HAL_RCC_GPIOA_CLK_ENABLE();
98 | /**USART2 GPIO Configuration
99 | PA2 ------> USART2_TX
100 | PA3 ------> USART2_RX
101 | */
102 | GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
103 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
104 | GPIO_InitStruct.Pull = GPIO_NOPULL;
105 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
106 | GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
107 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
108 |
109 | /* USART2 interrupt Init */
110 | HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
111 | HAL_NVIC_EnableIRQ(USART2_IRQn);
112 | /* USER CODE BEGIN USART2_MspInit 1 */
113 |
114 | /* USER CODE END USART2_MspInit 1 */
115 | }
116 |
117 | }
118 |
119 | /**
120 | * @brief UART MSP De-Initialization
121 | * This function freeze the hardware resources used in this example
122 | * @param huart: UART handle pointer
123 | * @retval None
124 | */
125 | void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
126 | {
127 | if(huart->Instance==USART2)
128 | {
129 | /* USER CODE BEGIN USART2_MspDeInit 0 */
130 |
131 | /* USER CODE END USART2_MspDeInit 0 */
132 | /* Peripheral clock disable */
133 | __HAL_RCC_USART2_CLK_DISABLE();
134 |
135 | /**USART2 GPIO Configuration
136 | PA2 ------> USART2_TX
137 | PA3 ------> USART2_RX
138 | */
139 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
140 |
141 | /* USART2 interrupt DeInit */
142 | HAL_NVIC_DisableIRQ(USART2_IRQn);
143 | /* USER CODE BEGIN USART2_MspDeInit 1 */
144 |
145 | /* USER CODE END USART2_MspDeInit 1 */
146 | }
147 |
148 | }
149 |
150 | /* USER CODE BEGIN 1 */
151 |
152 | /* USER CODE END 1 */
153 |
154 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
155 |
--------------------------------------------------------------------------------
/Core/Src/stm32f4xx_it.c:
--------------------------------------------------------------------------------
1 | /* USER CODE BEGIN Header */
2 | /**
3 | ******************************************************************************
4 | * @file stm32f4xx_it.c
5 | * @brief Interrupt Service Routines.
6 | ******************************************************************************
7 | * @attention
8 | *
9 | * © Copyright (c) 2022 STMicroelectronics.
10 | * All rights reserved.
11 | *
12 | * This software component is licensed by ST under BSD 3-Clause license,
13 | * the "License"; You may not use this file except in compliance with the
14 | * License. You may obtain a copy of the License at:
15 | * opensource.org/licenses/BSD-3-Clause
16 | *
17 | ******************************************************************************
18 | */
19 | /* USER CODE END Header */
20 |
21 | /* Includes ------------------------------------------------------------------*/
22 | #include "main.h"
23 | #include "stm32f4xx_it.h"
24 | /* Private includes ----------------------------------------------------------*/
25 | /* USER CODE BEGIN Includes */
26 | /* USER CODE END Includes */
27 |
28 | /* Private typedef -----------------------------------------------------------*/
29 | /* USER CODE BEGIN TD */
30 |
31 | /* USER CODE END TD */
32 |
33 | /* Private define ------------------------------------------------------------*/
34 | /* USER CODE BEGIN PD */
35 |
36 | /* USER CODE END PD */
37 |
38 | /* Private macro -------------------------------------------------------------*/
39 | /* USER CODE BEGIN PM */
40 |
41 | /* USER CODE END PM */
42 |
43 | /* Private variables ---------------------------------------------------------*/
44 | /* USER CODE BEGIN PV */
45 |
46 | /* USER CODE END PV */
47 |
48 | /* Private function prototypes -----------------------------------------------*/
49 | /* USER CODE BEGIN PFP */
50 |
51 | /* USER CODE END PFP */
52 |
53 | /* Private user code ---------------------------------------------------------*/
54 | /* USER CODE BEGIN 0 */
55 |
56 | /* USER CODE END 0 */
57 |
58 | /* External variables --------------------------------------------------------*/
59 | extern UART_HandleTypeDef huart2;
60 | /* USER CODE BEGIN EV */
61 |
62 | /* USER CODE END EV */
63 |
64 | /******************************************************************************/
65 | /* Cortex-M4 Processor Interruption and Exception Handlers */
66 | /******************************************************************************/
67 | /**
68 | * @brief This function handles Non maskable interrupt.
69 | */
70 | void NMI_Handler(void)
71 | {
72 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
73 |
74 | /* USER CODE END NonMaskableInt_IRQn 0 */
75 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
76 | while (1)
77 | {
78 | }
79 | /* USER CODE END NonMaskableInt_IRQn 1 */
80 | }
81 |
82 | /**
83 | * @brief This function handles Hard fault interrupt.
84 | */
85 | void HardFault_Handler(void)
86 | {
87 | /* USER CODE BEGIN HardFault_IRQn 0 */
88 |
89 | /* USER CODE END HardFault_IRQn 0 */
90 | while (1)
91 | {
92 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */
93 | /* USER CODE END W1_HardFault_IRQn 0 */
94 | }
95 | }
96 |
97 | /**
98 | * @brief This function handles Memory management fault.
99 | */
100 | void MemManage_Handler(void)
101 | {
102 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */
103 |
104 | /* USER CODE END MemoryManagement_IRQn 0 */
105 | while (1)
106 | {
107 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
108 | /* USER CODE END W1_MemoryManagement_IRQn 0 */
109 | }
110 | }
111 |
112 | /**
113 | * @brief This function handles Pre-fetch fault, memory access fault.
114 | */
115 | void BusFault_Handler(void)
116 | {
117 | /* USER CODE BEGIN BusFault_IRQn 0 */
118 |
119 | /* USER CODE END BusFault_IRQn 0 */
120 | while (1)
121 | {
122 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */
123 | /* USER CODE END W1_BusFault_IRQn 0 */
124 | }
125 | }
126 |
127 | /**
128 | * @brief This function handles Undefined instruction or illegal state.
129 | */
130 | void UsageFault_Handler(void)
131 | {
132 | /* USER CODE BEGIN UsageFault_IRQn 0 */
133 |
134 | /* USER CODE END UsageFault_IRQn 0 */
135 | while (1)
136 | {
137 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
138 | /* USER CODE END W1_UsageFault_IRQn 0 */
139 | }
140 | }
141 |
142 | /**
143 | * @brief This function handles System service call via SWI instruction.
144 | */
145 | void SVC_Handler(void)
146 | {
147 | /* USER CODE BEGIN SVCall_IRQn 0 */
148 |
149 | /* USER CODE END SVCall_IRQn 0 */
150 | /* USER CODE BEGIN SVCall_IRQn 1 */
151 |
152 | /* USER CODE END SVCall_IRQn 1 */
153 | }
154 |
155 | /**
156 | * @brief This function handles Debug monitor.
157 | */
158 | void DebugMon_Handler(void)
159 | {
160 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */
161 |
162 | /* USER CODE END DebugMonitor_IRQn 0 */
163 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */
164 |
165 | /* USER CODE END DebugMonitor_IRQn 1 */
166 | }
167 |
168 | /**
169 | * @brief This function handles Pendable request for system service.
170 | */
171 | void PendSV_Handler(void)
172 | {
173 | /* USER CODE BEGIN PendSV_IRQn 0 */
174 |
175 | /* USER CODE END PendSV_IRQn 0 */
176 | /* USER CODE BEGIN PendSV_IRQn 1 */
177 |
178 | /* USER CODE END PendSV_IRQn 1 */
179 | }
180 |
181 | /**
182 | * @brief This function handles System tick timer.
183 | */
184 | void SysTick_Handler(void)
185 | {
186 | /* USER CODE BEGIN SysTick_IRQn 0 */
187 |
188 | /* USER CODE END SysTick_IRQn 0 */
189 | HAL_IncTick();
190 | /* USER CODE BEGIN SysTick_IRQn 1 */
191 |
192 | /* USER CODE END SysTick_IRQn 1 */
193 | }
194 |
195 | /******************************************************************************/
196 | /* STM32F4xx Peripheral Interrupt Handlers */
197 | /* Add here the Interrupt Handlers for the used peripherals. */
198 | /* For the available peripheral interrupt handler names, */
199 | /* please refer to the startup file (startup_stm32f4xx.s). */
200 | /******************************************************************************/
201 |
202 | /**
203 | * @brief This function handles USART2 global interrupt.
204 | */
205 | void USART2_IRQHandler(void)
206 | {
207 | /* USER CODE BEGIN USART2_IRQn 0 */
208 |
209 | /* USER CODE END USART2_IRQn 0 */
210 | HAL_UART_IRQHandler(&huart2);
211 | /* USER CODE BEGIN USART2_IRQn 1 */
212 |
213 | /* USER CODE END USART2_IRQn 1 */
214 | }
215 |
216 | /* USER CODE BEGIN 1 */
217 |
218 | /* USER CODE END 1 */
219 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
220 |
--------------------------------------------------------------------------------
/Core/Src/syscalls.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file syscalls.c
4 | * @author Auto-generated by STM32CubeIDE
5 | * @brief STM32CubeIDE Minimal System calls file
6 | *
7 | * For more information about which c-functions
8 | * need which of these lowlevel functions
9 | * please consult the Newlib libc-manual
10 | ******************************************************************************
11 | * @attention
12 | *
13 | * © Copyright (c) 2020 STMicroelectronics.
14 | * All rights reserved.
15 | *
16 | * This software component is licensed by ST under BSD 3-Clause license,
17 | * the "License"; You may not use this file except in compliance with the
18 | * License. You may obtain a copy of the License at:
19 | * opensource.org/licenses/BSD-3-Clause
20 | *
21 | ******************************************************************************
22 | */
23 |
24 | /* Includes */
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 |
35 | /* Variables */
36 | extern int __io_putchar(int ch) __attribute__((weak));
37 | extern int __io_getchar(void) __attribute__((weak));
38 |
39 |
40 | char *__env[1] = { 0 };
41 | char **environ = __env;
42 |
43 |
44 | /* Functions */
45 | void initialise_monitor_handles()
46 | {
47 | }
48 |
49 | int _getpid(void)
50 | {
51 | return 1;
52 | }
53 |
54 | int _kill(int pid, int sig)
55 | {
56 | errno = EINVAL;
57 | return -1;
58 | }
59 |
60 | void _exit (int status)
61 | {
62 | _kill(status, -1);
63 | while (1) {} /* Make sure we hang here */
64 | }
65 |
66 | __attribute__((weak)) int _read(int file, char *ptr, int len)
67 | {
68 | int DataIdx;
69 |
70 | for (DataIdx = 0; DataIdx < len; DataIdx++)
71 | {
72 | *ptr++ = __io_getchar();
73 | }
74 |
75 | return len;
76 | }
77 |
78 | __attribute__((weak)) int _write(int file, char *ptr, int len)
79 | {
80 | int DataIdx;
81 |
82 | for (DataIdx = 0; DataIdx < len; DataIdx++)
83 | {
84 | __io_putchar(*ptr++);
85 | }
86 | return len;
87 | }
88 |
89 | int _close(int file)
90 | {
91 | return -1;
92 | }
93 |
94 |
95 | int _fstat(int file, struct stat *st)
96 | {
97 | st->st_mode = S_IFCHR;
98 | return 0;
99 | }
100 |
101 | int _isatty(int file)
102 | {
103 | return 1;
104 | }
105 |
106 | int _lseek(int file, int ptr, int dir)
107 | {
108 | return 0;
109 | }
110 |
111 | int _open(char *path, int flags, ...)
112 | {
113 | /* Pretend like we always fail */
114 | return -1;
115 | }
116 |
117 | int _wait(int *status)
118 | {
119 | errno = ECHILD;
120 | return -1;
121 | }
122 |
123 | int _unlink(char *name)
124 | {
125 | errno = ENOENT;
126 | return -1;
127 | }
128 |
129 | int _times(struct tms *buf)
130 | {
131 | return -1;
132 | }
133 |
134 | int _stat(char *file, struct stat *st)
135 | {
136 | st->st_mode = S_IFCHR;
137 | return 0;
138 | }
139 |
140 | int _link(char *old, char *new)
141 | {
142 | errno = EMLINK;
143 | return -1;
144 | }
145 |
146 | int _fork(void)
147 | {
148 | errno = EAGAIN;
149 | return -1;
150 | }
151 |
152 | int _execve(char *name, char **argv, char **env)
153 | {
154 | errno = ENOMEM;
155 | return -1;
156 | }
157 |
--------------------------------------------------------------------------------
/Core/Src/sysmem.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file sysmem.c
4 | * @author Generated by STM32CubeIDE
5 | * @brief STM32CubeIDE System Memory calls file
6 | *
7 | * For more information about which C functions
8 | * need which of these lowlevel functions
9 | * please consult the newlib libc manual
10 | ******************************************************************************
11 | * @attention
12 | *
13 | * © Copyright (c) 2020 STMicroelectronics.
14 | * All rights reserved.
15 | *
16 | * This software component is licensed by ST under BSD 3-Clause license,
17 | * the "License"; You may not use this file except in compliance with the
18 | * License. You may obtain a copy of the License at:
19 | * opensource.org/licenses/BSD-3-Clause
20 | *
21 | ******************************************************************************
22 | */
23 |
24 | /* Includes */
25 | #include
26 | #include
27 |
28 | /**
29 | * Pointer to the current high watermark of the heap usage
30 | */
31 | static uint8_t *__sbrk_heap_end = NULL;
32 |
33 | /**
34 | * @brief _sbrk() allocates memory to the newlib heap and is used by malloc
35 | * and others from the C library
36 | *
37 | * @verbatim
38 | * ############################################################################
39 | * # .data # .bss # newlib heap # MSP stack #
40 | * # # # # Reserved by _Min_Stack_Size #
41 | * ############################################################################
42 | * ^-- RAM start ^-- _end _estack, RAM end --^
43 | * @endverbatim
44 | *
45 | * This implementation starts allocating at the '_end' linker symbol
46 | * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
47 | * The implementation considers '_estack' linker symbol to be RAM end
48 | * NOTE: If the MSP stack, at any point during execution, grows larger than the
49 | * reserved size, please increase the '_Min_Stack_Size'.
50 | *
51 | * @param incr Memory size
52 | * @return Pointer to allocated memory
53 | */
54 | void *_sbrk(ptrdiff_t incr)
55 | {
56 | extern uint8_t _end; /* Symbol defined in the linker script */
57 | extern uint8_t _estack; /* Symbol defined in the linker script */
58 | extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
59 | const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
60 | const uint8_t *max_heap = (uint8_t *)stack_limit;
61 | uint8_t *prev_heap_end;
62 |
63 | /* Initialize heap end at first call */
64 | if (NULL == __sbrk_heap_end)
65 | {
66 | __sbrk_heap_end = &_end;
67 | }
68 |
69 | /* Protect heap from growing into the reserved MSP stack */
70 | if (__sbrk_heap_end + incr > max_heap)
71 | {
72 | errno = ENOMEM;
73 | return (void *)-1;
74 | }
75 |
76 | prev_heap_end = __sbrk_heap_end;
77 | __sbrk_heap_end += incr;
78 |
79 | return (void *)prev_heap_end;
80 | }
81 |
--------------------------------------------------------------------------------
/Core/Src/system_stm32f4xx.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file system_stm32f4xx.c
4 | * @author MCD Application Team
5 | * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
6 | *
7 | * This file provides two functions and one global variable to be called from
8 | * user application:
9 | * - SystemInit(): This function is called at startup just after reset and
10 | * before branch to main program. This call is made inside
11 | * the "startup_stm32f4xx.s" file.
12 | *
13 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
14 | * by the user application to setup the SysTick
15 | * timer or configure other parameters.
16 | *
17 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
18 | * be called whenever the core clock is changed
19 | * during program execution.
20 | *
21 | *
22 | ******************************************************************************
23 | * @attention
24 | *
25 | * © Copyright (c) 2017 STMicroelectronics.
26 | * All rights reserved.
27 | *
28 | * This software component is licensed by ST under BSD 3-Clause license,
29 | * the "License"; You may not use this file except in compliance with the
30 | * License. You may obtain a copy of the License at:
31 | * opensource.org/licenses/BSD-3-Clause
32 | *
33 | ******************************************************************************
34 | */
35 |
36 | /** @addtogroup CMSIS
37 | * @{
38 | */
39 |
40 | /** @addtogroup stm32f4xx_system
41 | * @{
42 | */
43 |
44 | /** @addtogroup STM32F4xx_System_Private_Includes
45 | * @{
46 | */
47 |
48 |
49 | #include "stm32f4xx.h"
50 |
51 | #if !defined (HSE_VALUE)
52 | #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
53 | #endif /* HSE_VALUE */
54 |
55 | #if !defined (HSI_VALUE)
56 | #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
57 | #endif /* HSI_VALUE */
58 |
59 | /**
60 | * @}
61 | */
62 |
63 | /** @addtogroup STM32F4xx_System_Private_TypesDefinitions
64 | * @{
65 | */
66 |
67 | /**
68 | * @}
69 | */
70 |
71 | /** @addtogroup STM32F4xx_System_Private_Defines
72 | * @{
73 | */
74 |
75 | /************************* Miscellaneous Configuration ************************/
76 | /*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
77 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
78 | || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
79 | || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
80 | /* #define DATA_IN_ExtSRAM */
81 | #endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
82 | STM32F412Zx || STM32F412Vx */
83 |
84 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
85 | || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
86 | /* #define DATA_IN_ExtSDRAM */
87 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
88 | STM32F479xx */
89 |
90 | /* Note: Following vector table addresses must be defined in line with linker
91 | configuration. */
92 | /*!< Uncomment the following line if you need to relocate the vector table
93 | anywhere in Flash or Sram, else the vector table is kept at the automatic
94 | remap of boot address selected */
95 | /* #define USER_VECT_TAB_ADDRESS */
96 |
97 | #if defined(USER_VECT_TAB_ADDRESS)
98 | /*!< Uncomment the following line if you need to relocate your vector Table
99 | in Sram else user remap will be done in Flash. */
100 | /* #define VECT_TAB_SRAM */
101 | #if defined(VECT_TAB_SRAM)
102 | #define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field.
103 | This value must be a multiple of 0x200. */
104 | #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
105 | This value must be a multiple of 0x200. */
106 | #else
107 | #define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
108 | This value must be a multiple of 0x200. */
109 | #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
110 | This value must be a multiple of 0x200. */
111 | #endif /* VECT_TAB_SRAM */
112 | #endif /* USER_VECT_TAB_ADDRESS */
113 | /******************************************************************************/
114 |
115 | /**
116 | * @}
117 | */
118 |
119 | /** @addtogroup STM32F4xx_System_Private_Macros
120 | * @{
121 | */
122 |
123 | /**
124 | * @}
125 | */
126 |
127 | /** @addtogroup STM32F4xx_System_Private_Variables
128 | * @{
129 | */
130 | /* This variable is updated in three ways:
131 | 1) by calling CMSIS function SystemCoreClockUpdate()
132 | 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
133 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
134 | Note: If you use this function to configure the system clock; then there
135 | is no need to call the 2 first functions listed above, since SystemCoreClock
136 | variable is updated automatically.
137 | */
138 | uint32_t SystemCoreClock = 16000000;
139 | const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
140 | const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
141 | /**
142 | * @}
143 | */
144 |
145 | /** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
146 | * @{
147 | */
148 |
149 | #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
150 | static void SystemInit_ExtMemCtl(void);
151 | #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
152 |
153 | /**
154 | * @}
155 | */
156 |
157 | /** @addtogroup STM32F4xx_System_Private_Functions
158 | * @{
159 | */
160 |
161 | /**
162 | * @brief Setup the microcontroller system
163 | * Initialize the FPU setting, vector table location and External memory
164 | * configuration.
165 | * @param None
166 | * @retval None
167 | */
168 | void SystemInit(void)
169 | {
170 | /* FPU settings ------------------------------------------------------------*/
171 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
172 | SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
173 | #endif
174 |
175 | #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
176 | SystemInit_ExtMemCtl();
177 | #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
178 |
179 | /* Configure the Vector Table location -------------------------------------*/
180 | #if defined(USER_VECT_TAB_ADDRESS)
181 | SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
182 | #endif /* USER_VECT_TAB_ADDRESS */
183 | }
184 |
185 | /**
186 | * @brief Update SystemCoreClock variable according to Clock Register Values.
187 | * The SystemCoreClock variable contains the core clock (HCLK), it can
188 | * be used by the user application to setup the SysTick timer or configure
189 | * other parameters.
190 | *
191 | * @note Each time the core clock (HCLK) changes, this function must be called
192 | * to update SystemCoreClock variable value. Otherwise, any configuration
193 | * based on this variable will be incorrect.
194 | *
195 | * @note - The system frequency computed by this function is not the real
196 | * frequency in the chip. It is calculated based on the predefined
197 | * constant and the selected clock source:
198 | *
199 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
200 | *
201 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
202 | *
203 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
204 | * or HSI_VALUE(*) multiplied/divided by the PLL factors.
205 | *
206 | * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
207 | * 16 MHz) but the real value may vary depending on the variations
208 | * in voltage and temperature.
209 | *
210 | * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
211 | * depends on the application requirements), user has to ensure that HSE_VALUE
212 | * is same as the real frequency of the crystal used. Otherwise, this function
213 | * may have wrong result.
214 | *
215 | * - The result of this function could be not correct when using fractional
216 | * value for HSE crystal.
217 | *
218 | * @param None
219 | * @retval None
220 | */
221 | void SystemCoreClockUpdate(void)
222 | {
223 | uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
224 |
225 | /* Get SYSCLK source -------------------------------------------------------*/
226 | tmp = RCC->CFGR & RCC_CFGR_SWS;
227 |
228 | switch (tmp)
229 | {
230 | case 0x00: /* HSI used as system clock source */
231 | SystemCoreClock = HSI_VALUE;
232 | break;
233 | case 0x04: /* HSE used as system clock source */
234 | SystemCoreClock = HSE_VALUE;
235 | break;
236 | case 0x08: /* PLL used as system clock source */
237 |
238 | /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
239 | SYSCLK = PLL_VCO / PLL_P
240 | */
241 | pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
242 | pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
243 |
244 | if (pllsource != 0)
245 | {
246 | /* HSE used as PLL clock source */
247 | pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
248 | }
249 | else
250 | {
251 | /* HSI used as PLL clock source */
252 | pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
253 | }
254 |
255 | pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
256 | SystemCoreClock = pllvco/pllp;
257 | break;
258 | default:
259 | SystemCoreClock = HSI_VALUE;
260 | break;
261 | }
262 | /* Compute HCLK frequency --------------------------------------------------*/
263 | /* Get HCLK prescaler */
264 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
265 | /* HCLK frequency */
266 | SystemCoreClock >>= tmp;
267 | }
268 |
269 | #if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
270 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
271 | || defined(STM32F469xx) || defined(STM32F479xx)
272 | /**
273 | * @brief Setup the external memory controller.
274 | * Called in startup_stm32f4xx.s before jump to main.
275 | * This function configures the external memories (SRAM/SDRAM)
276 | * This SRAM/SDRAM will be used as program data memory (including heap and stack).
277 | * @param None
278 | * @retval None
279 | */
280 | void SystemInit_ExtMemCtl(void)
281 | {
282 | __IO uint32_t tmp = 0x00;
283 |
284 | register uint32_t tmpreg = 0, timeout = 0xFFFF;
285 | register __IO uint32_t index;
286 |
287 | /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
288 | RCC->AHB1ENR |= 0x000001F8;
289 |
290 | /* Delay after an RCC peripheral clock enabling */
291 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
292 |
293 | /* Connect PDx pins to FMC Alternate function */
294 | GPIOD->AFR[0] = 0x00CCC0CC;
295 | GPIOD->AFR[1] = 0xCCCCCCCC;
296 | /* Configure PDx pins in Alternate function mode */
297 | GPIOD->MODER = 0xAAAA0A8A;
298 | /* Configure PDx pins speed to 100 MHz */
299 | GPIOD->OSPEEDR = 0xFFFF0FCF;
300 | /* Configure PDx pins Output type to push-pull */
301 | GPIOD->OTYPER = 0x00000000;
302 | /* No pull-up, pull-down for PDx pins */
303 | GPIOD->PUPDR = 0x00000000;
304 |
305 | /* Connect PEx pins to FMC Alternate function */
306 | GPIOE->AFR[0] = 0xC00CC0CC;
307 | GPIOE->AFR[1] = 0xCCCCCCCC;
308 | /* Configure PEx pins in Alternate function mode */
309 | GPIOE->MODER = 0xAAAA828A;
310 | /* Configure PEx pins speed to 100 MHz */
311 | GPIOE->OSPEEDR = 0xFFFFC3CF;
312 | /* Configure PEx pins Output type to push-pull */
313 | GPIOE->OTYPER = 0x00000000;
314 | /* No pull-up, pull-down for PEx pins */
315 | GPIOE->PUPDR = 0x00000000;
316 |
317 | /* Connect PFx pins to FMC Alternate function */
318 | GPIOF->AFR[0] = 0xCCCCCCCC;
319 | GPIOF->AFR[1] = 0xCCCCCCCC;
320 | /* Configure PFx pins in Alternate function mode */
321 | GPIOF->MODER = 0xAA800AAA;
322 | /* Configure PFx pins speed to 50 MHz */
323 | GPIOF->OSPEEDR = 0xAA800AAA;
324 | /* Configure PFx pins Output type to push-pull */
325 | GPIOF->OTYPER = 0x00000000;
326 | /* No pull-up, pull-down for PFx pins */
327 | GPIOF->PUPDR = 0x00000000;
328 |
329 | /* Connect PGx pins to FMC Alternate function */
330 | GPIOG->AFR[0] = 0xCCCCCCCC;
331 | GPIOG->AFR[1] = 0xCCCCCCCC;
332 | /* Configure PGx pins in Alternate function mode */
333 | GPIOG->MODER = 0xAAAAAAAA;
334 | /* Configure PGx pins speed to 50 MHz */
335 | GPIOG->OSPEEDR = 0xAAAAAAAA;
336 | /* Configure PGx pins Output type to push-pull */
337 | GPIOG->OTYPER = 0x00000000;
338 | /* No pull-up, pull-down for PGx pins */
339 | GPIOG->PUPDR = 0x00000000;
340 |
341 | /* Connect PHx pins to FMC Alternate function */
342 | GPIOH->AFR[0] = 0x00C0CC00;
343 | GPIOH->AFR[1] = 0xCCCCCCCC;
344 | /* Configure PHx pins in Alternate function mode */
345 | GPIOH->MODER = 0xAAAA08A0;
346 | /* Configure PHx pins speed to 50 MHz */
347 | GPIOH->OSPEEDR = 0xAAAA08A0;
348 | /* Configure PHx pins Output type to push-pull */
349 | GPIOH->OTYPER = 0x00000000;
350 | /* No pull-up, pull-down for PHx pins */
351 | GPIOH->PUPDR = 0x00000000;
352 |
353 | /* Connect PIx pins to FMC Alternate function */
354 | GPIOI->AFR[0] = 0xCCCCCCCC;
355 | GPIOI->AFR[1] = 0x00000CC0;
356 | /* Configure PIx pins in Alternate function mode */
357 | GPIOI->MODER = 0x0028AAAA;
358 | /* Configure PIx pins speed to 50 MHz */
359 | GPIOI->OSPEEDR = 0x0028AAAA;
360 | /* Configure PIx pins Output type to push-pull */
361 | GPIOI->OTYPER = 0x00000000;
362 | /* No pull-up, pull-down for PIx pins */
363 | GPIOI->PUPDR = 0x00000000;
364 |
365 | /*-- FMC Configuration -------------------------------------------------------*/
366 | /* Enable the FMC interface clock */
367 | RCC->AHB3ENR |= 0x00000001;
368 | /* Delay after an RCC peripheral clock enabling */
369 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
370 |
371 | FMC_Bank5_6->SDCR[0] = 0x000019E4;
372 | FMC_Bank5_6->SDTR[0] = 0x01115351;
373 |
374 | /* SDRAM initialization sequence */
375 | /* Clock enable command */
376 | FMC_Bank5_6->SDCMR = 0x00000011;
377 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
378 | while((tmpreg != 0) && (timeout-- > 0))
379 | {
380 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
381 | }
382 |
383 | /* Delay */
384 | for (index = 0; index<1000; index++);
385 |
386 | /* PALL command */
387 | FMC_Bank5_6->SDCMR = 0x00000012;
388 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
389 | timeout = 0xFFFF;
390 | while((tmpreg != 0) && (timeout-- > 0))
391 | {
392 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
393 | }
394 |
395 | /* Auto refresh command */
396 | FMC_Bank5_6->SDCMR = 0x00000073;
397 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
398 | timeout = 0xFFFF;
399 | while((tmpreg != 0) && (timeout-- > 0))
400 | {
401 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
402 | }
403 |
404 | /* MRD register program */
405 | FMC_Bank5_6->SDCMR = 0x00046014;
406 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
407 | timeout = 0xFFFF;
408 | while((tmpreg != 0) && (timeout-- > 0))
409 | {
410 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
411 | }
412 |
413 | /* Set refresh count */
414 | tmpreg = FMC_Bank5_6->SDRTR;
415 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
416 |
417 | /* Disable write protection */
418 | tmpreg = FMC_Bank5_6->SDCR[0];
419 | FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
420 |
421 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
422 | /* Configure and enable Bank1_SRAM2 */
423 | FMC_Bank1->BTCR[2] = 0x00001011;
424 | FMC_Bank1->BTCR[3] = 0x00000201;
425 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
426 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
427 | #if defined(STM32F469xx) || defined(STM32F479xx)
428 | /* Configure and enable Bank1_SRAM2 */
429 | FMC_Bank1->BTCR[2] = 0x00001091;
430 | FMC_Bank1->BTCR[3] = 0x00110212;
431 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
432 | #endif /* STM32F469xx || STM32F479xx */
433 |
434 | (void)(tmp);
435 | }
436 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
437 | #elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
438 | /**
439 | * @brief Setup the external memory controller.
440 | * Called in startup_stm32f4xx.s before jump to main.
441 | * This function configures the external memories (SRAM/SDRAM)
442 | * This SRAM/SDRAM will be used as program data memory (including heap and stack).
443 | * @param None
444 | * @retval None
445 | */
446 | void SystemInit_ExtMemCtl(void)
447 | {
448 | __IO uint32_t tmp = 0x00;
449 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
450 | || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
451 | #if defined (DATA_IN_ExtSDRAM)
452 | register uint32_t tmpreg = 0, timeout = 0xFFFF;
453 | register __IO uint32_t index;
454 |
455 | #if defined(STM32F446xx)
456 | /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
457 | clock */
458 | RCC->AHB1ENR |= 0x0000007D;
459 | #else
460 | /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
461 | clock */
462 | RCC->AHB1ENR |= 0x000001F8;
463 | #endif /* STM32F446xx */
464 | /* Delay after an RCC peripheral clock enabling */
465 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
466 |
467 | #if defined(STM32F446xx)
468 | /* Connect PAx pins to FMC Alternate function */
469 | GPIOA->AFR[0] |= 0xC0000000;
470 | GPIOA->AFR[1] |= 0x00000000;
471 | /* Configure PDx pins in Alternate function mode */
472 | GPIOA->MODER |= 0x00008000;
473 | /* Configure PDx pins speed to 50 MHz */
474 | GPIOA->OSPEEDR |= 0x00008000;
475 | /* Configure PDx pins Output type to push-pull */
476 | GPIOA->OTYPER |= 0x00000000;
477 | /* No pull-up, pull-down for PDx pins */
478 | GPIOA->PUPDR |= 0x00000000;
479 |
480 | /* Connect PCx pins to FMC Alternate function */
481 | GPIOC->AFR[0] |= 0x00CC0000;
482 | GPIOC->AFR[1] |= 0x00000000;
483 | /* Configure PDx pins in Alternate function mode */
484 | GPIOC->MODER |= 0x00000A00;
485 | /* Configure PDx pins speed to 50 MHz */
486 | GPIOC->OSPEEDR |= 0x00000A00;
487 | /* Configure PDx pins Output type to push-pull */
488 | GPIOC->OTYPER |= 0x00000000;
489 | /* No pull-up, pull-down for PDx pins */
490 | GPIOC->PUPDR |= 0x00000000;
491 | #endif /* STM32F446xx */
492 |
493 | /* Connect PDx pins to FMC Alternate function */
494 | GPIOD->AFR[0] = 0x000000CC;
495 | GPIOD->AFR[1] = 0xCC000CCC;
496 | /* Configure PDx pins in Alternate function mode */
497 | GPIOD->MODER = 0xA02A000A;
498 | /* Configure PDx pins speed to 50 MHz */
499 | GPIOD->OSPEEDR = 0xA02A000A;
500 | /* Configure PDx pins Output type to push-pull */
501 | GPIOD->OTYPER = 0x00000000;
502 | /* No pull-up, pull-down for PDx pins */
503 | GPIOD->PUPDR = 0x00000000;
504 |
505 | /* Connect PEx pins to FMC Alternate function */
506 | GPIOE->AFR[0] = 0xC00000CC;
507 | GPIOE->AFR[1] = 0xCCCCCCCC;
508 | /* Configure PEx pins in Alternate function mode */
509 | GPIOE->MODER = 0xAAAA800A;
510 | /* Configure PEx pins speed to 50 MHz */
511 | GPIOE->OSPEEDR = 0xAAAA800A;
512 | /* Configure PEx pins Output type to push-pull */
513 | GPIOE->OTYPER = 0x00000000;
514 | /* No pull-up, pull-down for PEx pins */
515 | GPIOE->PUPDR = 0x00000000;
516 |
517 | /* Connect PFx pins to FMC Alternate function */
518 | GPIOF->AFR[0] = 0xCCCCCCCC;
519 | GPIOF->AFR[1] = 0xCCCCCCCC;
520 | /* Configure PFx pins in Alternate function mode */
521 | GPIOF->MODER = 0xAA800AAA;
522 | /* Configure PFx pins speed to 50 MHz */
523 | GPIOF->OSPEEDR = 0xAA800AAA;
524 | /* Configure PFx pins Output type to push-pull */
525 | GPIOF->OTYPER = 0x00000000;
526 | /* No pull-up, pull-down for PFx pins */
527 | GPIOF->PUPDR = 0x00000000;
528 |
529 | /* Connect PGx pins to FMC Alternate function */
530 | GPIOG->AFR[0] = 0xCCCCCCCC;
531 | GPIOG->AFR[1] = 0xCCCCCCCC;
532 | /* Configure PGx pins in Alternate function mode */
533 | GPIOG->MODER = 0xAAAAAAAA;
534 | /* Configure PGx pins speed to 50 MHz */
535 | GPIOG->OSPEEDR = 0xAAAAAAAA;
536 | /* Configure PGx pins Output type to push-pull */
537 | GPIOG->OTYPER = 0x00000000;
538 | /* No pull-up, pull-down for PGx pins */
539 | GPIOG->PUPDR = 0x00000000;
540 |
541 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
542 | || defined(STM32F469xx) || defined(STM32F479xx)
543 | /* Connect PHx pins to FMC Alternate function */
544 | GPIOH->AFR[0] = 0x00C0CC00;
545 | GPIOH->AFR[1] = 0xCCCCCCCC;
546 | /* Configure PHx pins in Alternate function mode */
547 | GPIOH->MODER = 0xAAAA08A0;
548 | /* Configure PHx pins speed to 50 MHz */
549 | GPIOH->OSPEEDR = 0xAAAA08A0;
550 | /* Configure PHx pins Output type to push-pull */
551 | GPIOH->OTYPER = 0x00000000;
552 | /* No pull-up, pull-down for PHx pins */
553 | GPIOH->PUPDR = 0x00000000;
554 |
555 | /* Connect PIx pins to FMC Alternate function */
556 | GPIOI->AFR[0] = 0xCCCCCCCC;
557 | GPIOI->AFR[1] = 0x00000CC0;
558 | /* Configure PIx pins in Alternate function mode */
559 | GPIOI->MODER = 0x0028AAAA;
560 | /* Configure PIx pins speed to 50 MHz */
561 | GPIOI->OSPEEDR = 0x0028AAAA;
562 | /* Configure PIx pins Output type to push-pull */
563 | GPIOI->OTYPER = 0x00000000;
564 | /* No pull-up, pull-down for PIx pins */
565 | GPIOI->PUPDR = 0x00000000;
566 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
567 |
568 | /*-- FMC Configuration -------------------------------------------------------*/
569 | /* Enable the FMC interface clock */
570 | RCC->AHB3ENR |= 0x00000001;
571 | /* Delay after an RCC peripheral clock enabling */
572 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
573 |
574 | /* Configure and enable SDRAM bank1 */
575 | #if defined(STM32F446xx)
576 | FMC_Bank5_6->SDCR[0] = 0x00001954;
577 | #else
578 | FMC_Bank5_6->SDCR[0] = 0x000019E4;
579 | #endif /* STM32F446xx */
580 | FMC_Bank5_6->SDTR[0] = 0x01115351;
581 |
582 | /* SDRAM initialization sequence */
583 | /* Clock enable command */
584 | FMC_Bank5_6->SDCMR = 0x00000011;
585 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
586 | while((tmpreg != 0) && (timeout-- > 0))
587 | {
588 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
589 | }
590 |
591 | /* Delay */
592 | for (index = 0; index<1000; index++);
593 |
594 | /* PALL command */
595 | FMC_Bank5_6->SDCMR = 0x00000012;
596 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
597 | timeout = 0xFFFF;
598 | while((tmpreg != 0) && (timeout-- > 0))
599 | {
600 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
601 | }
602 |
603 | /* Auto refresh command */
604 | #if defined(STM32F446xx)
605 | FMC_Bank5_6->SDCMR = 0x000000F3;
606 | #else
607 | FMC_Bank5_6->SDCMR = 0x00000073;
608 | #endif /* STM32F446xx */
609 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
610 | timeout = 0xFFFF;
611 | while((tmpreg != 0) && (timeout-- > 0))
612 | {
613 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
614 | }
615 |
616 | /* MRD register program */
617 | #if defined(STM32F446xx)
618 | FMC_Bank5_6->SDCMR = 0x00044014;
619 | #else
620 | FMC_Bank5_6->SDCMR = 0x00046014;
621 | #endif /* STM32F446xx */
622 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
623 | timeout = 0xFFFF;
624 | while((tmpreg != 0) && (timeout-- > 0))
625 | {
626 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
627 | }
628 |
629 | /* Set refresh count */
630 | tmpreg = FMC_Bank5_6->SDRTR;
631 | #if defined(STM32F446xx)
632 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
633 | #else
634 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
635 | #endif /* STM32F446xx */
636 |
637 | /* Disable write protection */
638 | tmpreg = FMC_Bank5_6->SDCR[0];
639 | FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
640 | #endif /* DATA_IN_ExtSDRAM */
641 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
642 |
643 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
644 | || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
645 | || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
646 |
647 | #if defined(DATA_IN_ExtSRAM)
648 | /*-- GPIOs Configuration -----------------------------------------------------*/
649 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
650 | RCC->AHB1ENR |= 0x00000078;
651 | /* Delay after an RCC peripheral clock enabling */
652 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
653 |
654 | /* Connect PDx pins to FMC Alternate function */
655 | GPIOD->AFR[0] = 0x00CCC0CC;
656 | GPIOD->AFR[1] = 0xCCCCCCCC;
657 | /* Configure PDx pins in Alternate function mode */
658 | GPIOD->MODER = 0xAAAA0A8A;
659 | /* Configure PDx pins speed to 100 MHz */
660 | GPIOD->OSPEEDR = 0xFFFF0FCF;
661 | /* Configure PDx pins Output type to push-pull */
662 | GPIOD->OTYPER = 0x00000000;
663 | /* No pull-up, pull-down for PDx pins */
664 | GPIOD->PUPDR = 0x00000000;
665 |
666 | /* Connect PEx pins to FMC Alternate function */
667 | GPIOE->AFR[0] = 0xC00CC0CC;
668 | GPIOE->AFR[1] = 0xCCCCCCCC;
669 | /* Configure PEx pins in Alternate function mode */
670 | GPIOE->MODER = 0xAAAA828A;
671 | /* Configure PEx pins speed to 100 MHz */
672 | GPIOE->OSPEEDR = 0xFFFFC3CF;
673 | /* Configure PEx pins Output type to push-pull */
674 | GPIOE->OTYPER = 0x00000000;
675 | /* No pull-up, pull-down for PEx pins */
676 | GPIOE->PUPDR = 0x00000000;
677 |
678 | /* Connect PFx pins to FMC Alternate function */
679 | GPIOF->AFR[0] = 0x00CCCCCC;
680 | GPIOF->AFR[1] = 0xCCCC0000;
681 | /* Configure PFx pins in Alternate function mode */
682 | GPIOF->MODER = 0xAA000AAA;
683 | /* Configure PFx pins speed to 100 MHz */
684 | GPIOF->OSPEEDR = 0xFF000FFF;
685 | /* Configure PFx pins Output type to push-pull */
686 | GPIOF->OTYPER = 0x00000000;
687 | /* No pull-up, pull-down for PFx pins */
688 | GPIOF->PUPDR = 0x00000000;
689 |
690 | /* Connect PGx pins to FMC Alternate function */
691 | GPIOG->AFR[0] = 0x00CCCCCC;
692 | GPIOG->AFR[1] = 0x000000C0;
693 | /* Configure PGx pins in Alternate function mode */
694 | GPIOG->MODER = 0x00085AAA;
695 | /* Configure PGx pins speed to 100 MHz */
696 | GPIOG->OSPEEDR = 0x000CAFFF;
697 | /* Configure PGx pins Output type to push-pull */
698 | GPIOG->OTYPER = 0x00000000;
699 | /* No pull-up, pull-down for PGx pins */
700 | GPIOG->PUPDR = 0x00000000;
701 |
702 | /*-- FMC/FSMC Configuration --------------------------------------------------*/
703 | /* Enable the FMC/FSMC interface clock */
704 | RCC->AHB3ENR |= 0x00000001;
705 |
706 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
707 | /* Delay after an RCC peripheral clock enabling */
708 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
709 | /* Configure and enable Bank1_SRAM2 */
710 | FMC_Bank1->BTCR[2] = 0x00001011;
711 | FMC_Bank1->BTCR[3] = 0x00000201;
712 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
713 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
714 | #if defined(STM32F469xx) || defined(STM32F479xx)
715 | /* Delay after an RCC peripheral clock enabling */
716 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
717 | /* Configure and enable Bank1_SRAM2 */
718 | FMC_Bank1->BTCR[2] = 0x00001091;
719 | FMC_Bank1->BTCR[3] = 0x00110212;
720 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
721 | #endif /* STM32F469xx || STM32F479xx */
722 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
723 | || defined(STM32F412Zx) || defined(STM32F412Vx)
724 | /* Delay after an RCC peripheral clock enabling */
725 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
726 | /* Configure and enable Bank1_SRAM2 */
727 | FSMC_Bank1->BTCR[2] = 0x00001011;
728 | FSMC_Bank1->BTCR[3] = 0x00000201;
729 | FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
730 | #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
731 |
732 | #endif /* DATA_IN_ExtSRAM */
733 | #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
734 | STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
735 | (void)(tmp);
736 | }
737 | #endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
738 | /**
739 | * @}
740 | */
741 |
742 | /**
743 | * @}
744 | */
745 |
746 | /**
747 | * @}
748 | */
749 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
750 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Can Guveren
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # How to Use This Library
2 |
3 | This library supports 1,3,5,6,15,16 functions of modbus.
4 |
5 | **1.** Download file and include the source file in Core/Src/ModbusRTU_Master.c and Core/Inc/ModbusRTU_Master.h header file in your project.
6 |
7 | **2.** Set UART peripheral settings in your project.
8 |
9 | :exclamation: Attention. This project uses USART2 peripheral. If you want to different UART peripheral then you should change the value of UART_HandleTypeDef in the ModbusRTU_Master.c source file.
10 |
11 | 
12 |
13 |
14 |
15 | **3.** Set number of register, number of coil and slave id in the slave device.
16 |
17 | 
18 |
19 |
20 | **4.** You can use the library after making all the above settings. You can see the value of slave device register in the Modbus_Register[] array and you can see the value of slave device coil in the Modbus_Coil[] array. This arrays is in the ModbusRTU_Master.c source file.
21 |
22 | 
23 |
24 | ## Running the Library
25 |
26 | - You can use **Modbus Slave** program to test the library. You can download the **[Modbus Slave](https://www.modbustools.com/download.html)** program from here.
27 | - Open the Modbus Slave program and connect to your device (Connection/Connect)
28 | - :exclamation:Pay attention to your serial settings. The serial settings of the modbus slave program and the settings of the uart peripheral must be the same.
29 |
30 | 
31 |
32 | - After that, you should set slave definition. (Setup/Slave Definition)
33 |
34 | - After this step you can use library functions.
35 |
36 | You can find the **MODBUS CRC** function used in this project [here](https://github.com/LacobusVentura/MODBUS-CRC16).
37 |
38 | Modbus Slave Library [here](https://github.com/CanGuveren/STM32-ModbusRTU-Slave).
39 |
--------------------------------------------------------------------------------