source: trunk/fw_g473rct/SES/src/modbus.c@ 20

Last change on this file since 20 was 20, checked in by f.jahn, 4 months ago

adc dma funktioniert und modbus funktioniert

File size: 31.6 KB
Line 
1/*
2 * modbus.c
3 *
4 * Created: 03.09.2012 08:39:20
5 * Author: Falko
6 */
7
8
9
10#if MODBUS_SUPPORT == TRUE
11
12 #include "modbus.h"
13 //#include "stm32g4xx_hal.h"
14 #include "main.h"
15 //#include "stm32g0xx_hal_tim.h"
16 //#include "stm32_hal_legacy.h"
17 #include <stdio.h>
18 // ---------------------------------------------------------
19 // -------------------- MODUL DEFINES ----------------------
20 // ---------------------------------------------------------
21
22
23
24
25 #define MODBUS_BROADCAST_ADDRESS 0x00
26 #define FC_READ_COILS 0x01
27 #define FC_READ_HOLDING_REGISTERS 0x03
28 #define FC_WRITE_SINGLE_REGISTER 0x06
29 #define FC_WRITE_MULTIPLE_REGISTER 0x10
30
31 /* Protocol exceptions */
32 #define ILLEGAL_FUNCTION 0x01
33 #define ILLEGAL_DATA_ADDRESS 0x02
34 #define ILLEGAL_DATA_VALUE 0x03
35 #define SLAVE_DEVICE_FAILURE 0x04
36 #define SERVER_FAILURE 0x04
37 #define ACKNOWLEDGE 0x05
38 #define SLAVE_DEVICE_BUSY 0x06
39 #define SERVER_BUSY 0x06
40 #define NEGATIVE_ACKNOWLEDGE 0x07
41 #define MEMORY_PARITY_ERROR 0x08
42 #define GATEWAY_PROBLEM_PATH 0x0A
43 #define GATEWAY_PROBLEM_TARGET 0x0B
44
45 /* Local Error codes */
46 #define INVALID_CRC -1
47
48 // Position der Daten im Rx String
49 #define OFFSET_SLAVE_ADRESS 0x00
50 #define OFFSET_FUNCTION_CODE 0x01
51 #define OFFSET_START_ADRESS_HI 0x02
52 #define OFFSET_START_ADRESS_LO 0x03
53 #define OFFSET_NO_OF_REGISTERS_HI 0x04
54 #define OFFSET_NO_OF_REGISTERS_LO 0x05
55
56 #define MIN_NUMBER_OF_REGISTERS_FC3 0x01
57 #define MAX_NUMBER_OF_REGISTERS_FC3 0x7D
58 #define MIN_NUMBER_OF_REGISTERS_FC16 0x01
59 #define MAX_NUMBER_OF_REGISTERS_FC16 0x7B
60
61 #ifdef DEBUG
62 #define RESPONSE_TIMEOUT 300 // * 1ms
63 #else
64 #define RESPONSE_TIMEOUT 1000 // * 1ms
65 #endif
66
67 #define FAST_BAUDRATE_INTERFRAME_DELAY_us (1750UL)
68 // --- Externe Variablen --------------------------------------------
69 extern modbus_t modbusData;
70 extern sys_data_t sys_data;
71
72
73 // --- Private Funktions Prototypen --------------------------------------------
74
75 void mbUartInit (modbus_t * mb_data,UART_HandleTypeDef * usart, uint32_t baudrate, uint32_t parityMode, uint32_t stopBits , uint32_t nrOfBitsPerChar);
76 uint16_t mbCrc16 (uint8_t *buf, uint32_t len);
77 void mbSend (modbus_t * mb_data );
78 uint32_t mbSlaveReadHoldingRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID);
79 uint32_t mbSlaveWriteMultipleRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID);
80 uint32_t mbSlaveWriteSingleRegister (uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID);
81 uint32_t mbSlaveResponseException (uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position) ;
82static HAL_StatusTypeDef RS485_ModbusEx_Init (UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime, uint32_t charReceiveTimeout);
83static void UART_TxISR_8BIT (UART_HandleTypeDef *huart);
84
85 // --- GEMEINSAME MODBUS FUNKTIONEN --------------------------------------------
86 // Diese Funktionen werden sowohl von Modbus Master als auch Modbus Slave verwendet
87
88 /*
89 *
90 * @brief Diese Funktion Initialisert die Modbus Datenstrukturen und die Hardware
91 *
92 * Das Modbus Modul bentigt einen UART und einen Timer pro Modbus Anschluss
93 * Die Funktion erfordert eine vorhandene Callback funktion namens HAL_UART_MspInit
94 * In dieser muss:
95 * - Der UART CLK eingeschaltet werden
96 * - Die Pins initialisert werden (Alternate Port Funktion)
97 * - Der NVIC Interrupt eingeschaltet werden
98 * @param mb_data : Datenstruktur zur Aufnahme aller Daten
99 * @param baudrate : Bautrate
100 * @param parityMode : Parity, mglich ist UART_PARITY_ODD, UART_PARITY_EVEN, UART_PARITY_NONE. Default ist lt. Modbus Standart EVEN
101 * @param usart : Timer Modul, z.B. USART1
102 * @retval None
103 */
104 void mbInit(modbus_t* mb_data, uint32_t baudrate, uint32_t parityMode, uint16_t stopBits, UART_HandleTypeDef* usart)
105 {
106 uint32_t numberOfBitsPerChar;
107 //uint32_t stopBits;
108
109 if (stopBits < 1U || stopBits > 2U) stopBits = 1U;
110
111 // Berechne Stop Bits
112 /*if ((parityMode== MODBUS_UART_PARITY_EVEN) || (parityMode == MODBUS_UART_PARITY_ODD))
113 {
114 stopBits = 1;
115 }
116 else
117 {
118 stopBits = 2;
119 }*/
120
121 // Berechne Anzahl der Bits per Char
122 numberOfBitsPerChar = NUMBER_OF_STARTBITS + NUMBER_OF_DATABITS + stopBits;
123 if ((parityMode == MODBUS_UART_PARITY_EVEN) || (parityMode == MODBUS_UART_PARITY_ODD))
124 {
125 numberOfBitsPerChar +=1;
126 }
127
128 mbUartInit(mb_data,usart, baudrate, parityMode, stopBits, numberOfBitsPerChar);
129
130 // Datenstrukturen zurcksetzen
131 mb_data->last_query_function_code = 0;
132 mb_data->last_query_tcp_id.w = 0;
133 mb_data->last_query_number_of_register.w = 0;
134 mb_data->current_query = MB_QUERY_NOTHING;
135 mb_data->last_query_slave_adress = 0;
136 mb_data->last_query_start_adress.w = 0;
137 mb_data->last_query_timeout = false;
138 }
139
140 /*
141 *
142 * @brief Diese Funktion Initialisert die Modbus UART Hardware
143 *
144 * @param mb_data : Datenstruktur zur Aufnahme aller Daten
145 * @param usart : UART Modul, z.B. USART1
146 * @param baudrate : UART BAUD
147 * @param parityMmode : Parity, mglich ist:
148 UART_PARITY_ODD, UART_PARITY_EVEN, UART_PARITY_NONE.
149 Default ist lt. Modbus Standart EVEN
150 * @param stopBits : Anzahl der Stop Bits, lt Modbus Standart
151 * 2 Stop Bits bei Parity None, ansonsten 2 Stop Bits
152 * @retval None
153 */
154 void mbUartInit(modbus_t * mb_data,UART_HandleTypeDef * usart, uint32_t baudrate, uint32_t parityMode, uint32_t stopBits , uint32_t nrOfBitsPerChar)
155 {
156 //--- Uart Init ------------------------------------------------------------
157 mb_data->uart = usart;
158
159 // Init aus Cube
160 mb_data->uart->Instance = USART1;
161 mb_data->uart->Init.BaudRate = 19200;
162 mb_data->uart->Init.WordLength = UART_WORDLENGTH_9B;
163 mb_data->uart->Init.StopBits = UART_STOPBITS_1;
164 mb_data->uart->Init.Parity = UART_PARITY_EVEN;
165 mb_data->uart->Init.Mode = UART_MODE_TX_RX;
166 mb_data->uart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
167 mb_data->uart->Init.OverSampling = UART_OVERSAMPLING_16;
168 mb_data->uart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
169 mb_data->uart->Init.ClockPrescaler = UART_PRESCALER_DIV1;
170 mb_data->uart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
171
172 // Init nderungen
173
174 // Baudrate
175 mb_data->uart->Init.BaudRate = baudrate;
176 // Parity Mode // Word length
177 if(parityMode == MODBUS_UART_PARITY_EVEN)
178 {
179 mb_data->uart->Init.Parity = UART_PARITY_EVEN;
180 mb_data->uart->Init.WordLength = UART_WORDLENGTH_9B;
181 }
182 else if(parityMode == MODBUS_UART_PARITY_ODD)
183 {
184 mb_data->uart->Init.Parity = UART_PARITY_ODD;
185 mb_data->uart->Init.WordLength = UART_WORDLENGTH_9B;
186 }
187 else
188 {
189 mb_data->uart->Init.Parity = UART_PARITY_NONE;
190 mb_data->uart->Init.WordLength = UART_WORDLENGTH_8B;
191 }
192 // Stopbits
193 if (stopBits == 1)
194 {
195 mb_data->uart->Init.StopBits = UART_STOPBITS_1;
196 }
197 else
198 {
199 mb_data->uart->Init.StopBits = UART_STOPBITS_2;
200 }
201 // Init
202 if (RS485_ModbusEx_Init(mb_data->uart, UART_DE_POLARITY_HIGH, 0, 0,TIMEOUT_FRAME_COMPLETE*nrOfBitsPerChar) != HAL_OK)
203 {
204 Error_Handler();
205 }
206 if (HAL_UARTEx_DisableFifoMode(mb_data->uart) != HAL_OK)
207 {
208 Error_Handler();
209 }
210
211 if(HAL_UART_Receive_IT(mb_data->uart, mb_data->rx_buffer, RXBUFFERSIZE) != HAL_OK)
212 {
213 printf("uart error \n\r");
214 while(1)
215 {
216 }
217 }
218 }
219
220 /*
221 *
222 * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
223 * @param huart: UART handle.
224 * @retval None
225 */
226 void mbUartEndRxTransfer(UART_HandleTypeDef *huart)
227 {
228 /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
229 //CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
230 //CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
231
232 /* At end of Rx process, restore huart->RxState to Ready */
233 huart->RxState = HAL_UART_STATE_READY;
234 }
235
236 void mbUartRx(modbus_t* mb_data)
237 {
238 uint32_t pos;
239 uint8_t data;
240
241 pos = mb_data->rx_head;
242
243 if (pos >= RXBUFFERSIZE)
244 {
245 return;
246 }
247 //data = mb_data->uart->Instance->RDR
248 data = mb_data->uart->Instance->RDR & (uint8_t)0x00FF; //NOTE: mb_data->uart.Instance->DR gendert
249 mb_data->rx_buffer[pos] = data;
250
251 mb_data->rx_head++;
252
253 //mbTimerStart(mb_data);
254 }
255
256 HAL_StatusTypeDef mbUartTx(UART_HandleTypeDef *huart)
257 {
258 uint16_t* tmp;
259
260 if(huart->Init.WordLength == UART_WORDLENGTH_9B)
261 {
262 tmp = (uint16_t*) huart->pTxBuffPtr;
263 huart->Instance->TDR = (uint16_t)(*tmp & (uint16_t)0x01FF); //NOTE: huart->Instance->DR gendert
264
265 if(huart->Init.Parity == UART_PARITY_NONE)
266 {
267 huart->pTxBuffPtr += 2;
268 }
269 else
270 {
271 huart->pTxBuffPtr += 1;
272 }
273 }
274 else
275 {
276 huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF); //NOTE:huart->Instance->DR gendert
277 }
278
279 if(--huart->TxXferCount == 0)
280 {
281 /* Disable the UART Transmit Complete Interrupt */
282 __HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
283
284 /* Enable the UART Transmit Complete Interrupt */
285 __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
286 }
287 return HAL_OK;
288 }
289
290 // huart->State gibt es nicht mehr. Ersetzt durch huart->gState.
291 /**
292 * @brief Wraps up transmission in non blocking mode.
293 * @param huart: pointer to a UART_HandleTypeDef structure that contains
294 * the configuration information for the specified UART module.
295 * @retval HAL status
296 */
297 static void UART_EndTransmit_IT(UART_HandleTypeDef *huart)
298 {
299 /* Disable the UART Transmit Complete Interrupt */
300 CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE);
301
302 /* Tx process is ended, restore huart->gState to Ready */
303 huart->gState = HAL_UART_STATE_READY;
304
305 /* Cleat TxISR function pointer */
306 huart->TxISR = NULL;
307
308 #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
309 /*Call registered Tx complete callback*/
310 huart->TxCpltCallback(huart);
311 #else
312 /*Call legacy weak Tx complete callback*/
313 HAL_UART_TxCpltCallback(huart);
314 #endif /* USE_HAL_UART_REGISTER_CALLBACKS */
315 }
316
317
318static HAL_StatusTypeDef RS485_ModbusEx_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime, uint32_t charReceiveTimeout)
319{
320 uint32_t temp;
321
322 /* Check the UART handle allocation */
323 if (huart == NULL)
324 {
325 return HAL_ERROR;
326 }
327 /* Check the Driver Enable UART instance */
328 assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance));
329
330 /* Check the Driver Enable polarity */
331 assert_param(IS_UART_DE_POLARITY(Polarity));
332
333 /* Check the Driver Enable assertion time */
334 assert_param(IS_UART_ASSERTIONTIME(AssertionTime));
335
336 /* Check the Driver Enable deassertion time */
337 assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime));
338
339 if (huart->gState == HAL_UART_STATE_RESET)
340 {
341 /* Allocate lock resource and initialize it */
342 huart->Lock = HAL_UNLOCKED;
343
344#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
345 UART_InitCallbacksToDefault(huart);
346
347 if (huart->MspInitCallback == NULL)
348 {
349 huart->MspInitCallback = HAL_UART_MspInit;
350 }
351
352 /* Init the low level hardware */
353 huart->MspInitCallback(huart);
354#else
355 /* Init the low level hardware : GPIO, CLOCK, CORTEX */
356 HAL_UART_MspInit(huart);
357#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
358 }
359
360 huart->gState = HAL_UART_STATE_BUSY;
361
362 /* Disable the Peripheral */
363 __HAL_UART_DISABLE(huart);
364
365 /* Set the UART Communication parameters */
366 if (UART_SetConfig(huart) == HAL_ERROR)
367 {
368 return HAL_ERROR;
369 }
370
371 if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
372 {
373 UART_AdvFeatureConfig(huart);
374 }
375
376 /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
377 //EDIT SMART_SWITCH: HIER wurde ein chip mit autoerkennung implementiert
378 // SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
379
380 /* Set the Driver Enable polarity */
381 // MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
382
383 /* Set the Driver Enable assertion and deassertion times */
384// temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
385// temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
386// MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
387
388// EDIT ECS START
389 /*Set receive timeout time*/
390 SET_BIT(huart->Instance->CR2, USART_CR2_RTOEN);
391 SET_BIT(huart->Instance->CR1, USART_CR1_RTOIE);
392 //MODIFY_REG(huart->Instance->RTOR, USART_RTOR_RTO, charReceiveTimeout);
393 if (huart->Init.BaudRate <= 19200) MODIFY_REG(huart->Instance->RTOR, USART_RTOR_RTO, charReceiveTimeout);
394 else
395 {
396 uint32_t fixedDelayInBitDurations = (FAST_BAUDRATE_INTERFRAME_DELAY_us * huart->Init.BaudRate) / 1000000UL + 1UL;
397 MODIFY_REG(huart->Instance->RTOR, USART_RTOR_RTO, fixedDelayInBitDurations);
398 }
399// EDIT ECS END
400
401 /* Enable the Peripheral */
402 __HAL_UART_ENABLE(huart);
403
404 /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
405 return (UART_CheckIdleState(huart));
406}
407
408
409static int test;
410void MODBUS_UART_IRQHandler(UART_HandleTypeDef *huart)
411{
412 uint32_t isrflags = READ_REG(huart->Instance->ISR);
413 uint32_t cr1its = READ_REG(huart->Instance->CR1);
414 uint32_t cr2its = READ_REG(huart->Instance->CR2);
415 uint32_t cr3its = READ_REG(huart->Instance->CR3);
416
417 uint32_t errorflags;
418 uint32_t errorcode;
419
420 errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE));
421
422 /* If some errors occur */
423 if ((errorflags != 0U)
424 && ((((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)
425 || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != 0U))))
426 {
427 /* UART parity error interrupt occurred -------------------------------------*/
428 if (((isrflags & USART_ISR_PE) != 0U) && ((cr1its & USART_CR1_PEIE) != 0U))
429 {
430 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF);
431
432 huart->ErrorCode |= HAL_UART_ERROR_PE;
433 }
434
435 /* UART frame error interrupt occurred --------------------------------------*/
436 if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
437 {
438 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF);
439
440 huart->ErrorCode |= HAL_UART_ERROR_FE;
441 }
442
443 /* UART noise error interrupt occurred --------------------------------------*/
444 if (((isrflags & USART_ISR_NE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
445 {
446 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF);
447
448 huart->ErrorCode |= HAL_UART_ERROR_NE;
449 }
450
451 /* UART Over-Run interrupt occurred -----------------------------------------*/
452 if (((isrflags & USART_ISR_ORE) != 0U)
453 && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U) ||
454 ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != 0U)))
455 {
456 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
457
458 huart->ErrorCode |= HAL_UART_ERROR_ORE;
459 }
460 } /* End if some error occurs */
461
462
463 /* UART in mode Receiver (receive Timeout occured)--------------------------*/
464 if (((isrflags & USART_ISR_RTOF) != 0U)
465 && (((cr1its & USART_CR1_RTOIE) != 0U)
466 || ((cr3its & USART_CR2_RTOEN) != 0U)))
467 {
468 __HAL_UART_CLEAR_FLAG(huart, USART_ICR_RTOCF);
469 huart->RxState = HAL_UART_STATE_READY;
470 huart->gState = HAL_UART_STATE_READY;
471 modbusData.mb_rx_frame_complete = 1;
472 modbusData.setRxLed = true;
473
474 }
475
476 /* UART in mode Receiver ---------------------------------------------------*/
477 if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
478 && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
479 || ((cr3its & USART_CR3_RXFTIE) != 0U)))
480 {
481 if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && (modbusData.rx_head < RXBUFFERSIZE)) //-> empfngt dann ein byte aber das ist nicht wild
482 {
483 modbusData.rx_buffer[modbusData.rx_head] = huart->Instance->RDR;
484 /*DEBUG//printf("xx%d: nr:%d %d\n",test ++,modbusData.rx_head, modbusData.rx_buffer[modbusData.rx_head]);*/
485 modbusData.rx_head++;
486 modbusData.setRxLed = true;
487 }
488 else
489 {
490 __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
491 }
492 }
493
494 /* UART in mode Transmitter ------------------------------------------------*/
495 if (((isrflags & USART_ISR_TXE_TXFNF) != 0U)
496 && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U)
497 || ((cr3its & USART_CR3_TXFTIE) != 0U)))
498 {
499 UART_TxISR_8BIT(modbusData.uart);
500 modbusData.setTxLed = true;
501 }
502
503 /* UART in mode Transmitter (transmission end) -----------------------------*/
504 if (((isrflags & USART_ISR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U))
505 {
506 modbusData.current_query = MB_QUERY_NOTHING;
507 UART_EndTransmit_IT(huart);
508 huart->RxState = HAL_UART_STATE_BUSY_RX;
509// /*Reset TX complete interrupt flag*/
510// __HAL_UART_CLEAR_FLAG(huart, USART_ISR_TC);
511// /* Disable the UART Transmit Complete Interrupt */
512// CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE);
513// /*TX complete callback function*/
514// HAL_UART_TxCpltCallback(huart);
515// /* Tx process is ended, restore huart->gState to Ready */
516// huart->gState = HAL_UART_STATE_READY;
517 }
518
519 /* Call UART Error Call back function if need be --------------------------*/
520 if (huart->ErrorCode != HAL_UART_ERROR_NONE)
521 {
522 huart->RxState = HAL_UART_STATE_BUSY_RX;
523 /* UART in mode Receiver ---------------------------------------------------*/
524 if (((isrflags & USART_ISR_RXNE_RXFNE) != 0U)
525 && (((cr1its & USART_CR1_RXNEIE_RXFNEIE) != 0U)
526 || ((cr3its & USART_CR3_RXFTIE) != 0U)))
527 {
528 __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
529 huart->ErrorCode = HAL_UART_ERROR_NONE;
530 }
531 else if (((isrflags & USART_ISR_TXE_TXFNF) != 0U)
532 && (((cr1its & USART_CR1_TXEIE_TXFNFIE) != 0U)
533 || ((cr3its & USART_CR3_TXFTIE) != 0U)))
534 {
535 modbusData.current_query = MB_QUERY_NOTHING;
536 UART_EndTransmit_IT(huart);
537 huart->RxState = HAL_UART_STATE_BUSY_RX;
538 modbusData.setTxLed = true;
539 }
540 }
541}
542
543
544
545
546
547
548
549/**
550 * @brief TX interrrupt handler for 7 or 8 bits data word length .
551 * @note Function is called under interruption only, once
552 * interruptions have been enabled by HAL_UART_Transmit_IT().
553 * @param huart UART handle.
554 * @retval None
555 */
556static void UART_TxISR_8BIT(UART_HandleTypeDef *huart)
557{
558 /* Check that a Tx process is ongoing */
559 if (huart->gState == HAL_UART_STATE_BUSY_TX)
560 {
561 if (huart->TxXferCount == 0U)
562 {
563 /* Disable the UART Transmit Data Register Empty Interrupt */
564 CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
565
566 /* Enable the UART Transmit Complete Interrupt */
567 SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
568 }
569 else
570 {
571 huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr & (uint8_t)0xFF);
572 huart->pTxBuffPtr++;
573 huart->TxXferCount--;
574 }
575 }
576 else
577 {
578 /* Disable the UART Transmit Data Register Empty Interrupt */
579 CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE);
580
581 /* Enable the UART Transmit Complete Interrupt */
582 SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
583 }
584}
585
586
587
588
589
590
591
592
593
594
595
596
597 /**
598 * @brief Output Compare callback in non blocking mode
599 * @param htim : TIM OC handle
600 * @retval None
601 */
602 void mbTimerIsr(modbus_t * mb_data)
603 {
604 /* Capture compare 1 event */
605// if(__HAL_TIM_GET_FLAG(mb_data->timer, TIM_FLAG_CC1) != RESET)
606// {
607// if(__HAL_TIM_GET_IT_SOURCE(mb_data->timer, TIM_IT_CC1) !=RESET)
608// {
609// __HAL_TIM_CLEAR_IT(mb_data->timer, TIM_IT_CC1);
610// mb_data->timer->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
611
612 mb_data->mb_rx_frame_complete=true;
613// mb_data->timer->Instance->CNT =0;
614// HAL_TIM_OC_Stop_IT(mb_data->timer, TIM_CHANNEL_1);
615// mb_data->timer->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
616//
617// }
618// }
619 }
620
621
622 void mbSend(modbus_t * mb_data )
623 {
624 mb_data->current_query = MB_QUERY_SEND_DATA;
625 HAL_UART_Transmit_IT(mb_data->uart, mb_data->tx_buffer, mb_data->tx_head);
626 }
627
628 void mbClearTxBuffer(modbus_t * mb_data)
629 {
630 mb_data->tx_head = 0;
631 }
632
633
634
635 // Compute the MODBUS RTU CRC
636 uint16_t mbCrc16 ( uint8_t *buf, uint32_t len)
637 {
638 uint16_t crc = 0xFFFF;
639
640 for (uint32_t pos = 0; pos < len; pos++)
641 {
642 crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
643
644 for (int i = 8; i != 0; i--)
645 { // Loop over each bit
646 if ((crc & 0x0001) != 0)
647 { // If the LSB is set
648 crc >>= 1; // Shift right and XOR 0xA001
649 crc ^= 0xA001;
650 }
651 else // Else LSB is not set
652 {
653 crc >>= 1; // Just shift right
654 }
655 }
656 }
657
658 // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
659 return crc;
660 }
661
662 /* If CRC is correct returns msg_length else returns INVALID_CRC */
663 int mbCheckCrc16( uint8_t *msg, const int msg_length)
664 {
665 int ret;
666 uint16_t crc_calc;
667 uint16_t crc_received;
668
669 crc_calc = mbCrc16(msg, msg_length - 2);
670 crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2];
671
672 // Check CRC of msg
673 if (crc_calc == crc_received) {
674 ret = msg_length;
675 } else {
676 ret = INVALID_CRC;
677 }
678 return ret;
679 }
680
681 uint32_t mbAppendCrc16(uint8_t * buffer, uint32_t tx_position)
682 {
683 uint16_t crc = mbCrc16( buffer , tx_position);
684
685 uint8_t l_crc = (uint8_t) (crc & 0x00FF) ;
686 uint8_t h_crc = (uint8_t) (crc >> 8);
687 buffer[tx_position] = l_crc;
688 tx_position++;
689 buffer[tx_position] = h_crc;
690 tx_position++;
691 return tx_position;
692 }
693
694 /************************************************************************************************************
695 Function: mb_get_frame_complete
696 Purpose: Rckabe ob Frame komplett empfangen wurde
697 *************************************************************************************************************/
698 bool mbGetFrameComplete(modbus_t * mb_data)
699 {
700 return mb_data->mb_rx_frame_complete;
701 }
702
703 void mbClearRxFrame(modbus_t * mb_data)
704 {
705 // Wieder bei 0 im buffer anfangen
706 mb_data->rx_head = 0;
707
708 // keine Daten mehr vorhanden
709 mb_data->mb_rx_frame_complete=false;
710 }
711
712
713 // --------------------- SLAVE FUNCTIONS ---------------------------------------
714
715#define SEND_TO_SLAVES_BUFFER_COUNT 1000
716//static TASK_MODBUS_MASTER_Message_t xMessage[255];
717//static TASK_MODBUS_MASTER_Message_t *pxMessage;
718static bword_t values[SEND_TO_SLAVES_BUFFER_COUNT];
719static uint32_t y;
720static uint32_t z;
721
722 uint32_t mbSlaveCheckModbusRtuQuery(modbus_t * mb_data)
723 {
724 uint32_t message_lengh;
725 uint8_t *modbus_rx_message;
726 modbus_rx_message = mb_data->rx_buffer;
727 message_lengh= mb_data->rx_head;
728 uint32_t slave_adress;
729 slave_adress = modbus_rx_message[0];
730
731 if (message_lengh < 5) //Mindestens 5 Zeichen (Slave Adress + Function Code + 2x CRC
732 {
733 mbClearRxFrame(mb_data);
734 return 0;
735 }
736
737 // Prfe CRC
738 if (mbCheckCrc16(modbus_rx_message,message_lengh) == INVALID_CRC)
739 {
740 mbClearRxFrame(mb_data);
741 return 0;
742 }
743
744 if (slave_adress == MODBUS_BROADCAST_ADDRESS)
745 {
746
747 return RESPOND_TO_QUERY;
748 }
749 /* auf richtige Slave Adresse checken ansonsten nicht antworten*/
750 else if (slave_adress == sys_data.s.parameter.slave_address)
751 {
752 return RESPOND_TO_QUERY;
753 }
754
755 mbClearRxFrame(mb_data);
756 return 0;
757 }
758
759 void mbSlaveProcessRtuQuery(modbus_t * mb_data)
760 {
761 uint32_t tx_position=0; //die _Nchste_ Position in der Zeichen eingefgt werden mssen
762 uint8_t *modbus_rx_message;
763 modbus_rx_message = &mb_data->rx_buffer[0];
764
765 //Vorbereiten auf neues senden
766 mbClearTxBuffer(mb_data);
767
768 //mb_data->tx_buffer[0] = sys_data.s.vmGreenview.s.lb_slave_adress;
769 mb_data->tx_buffer[0] = *modbus_rx_message;
770 tx_position++;
771 tx_position = mbSlaveProcessPdu(mb_data->tx_buffer , modbus_rx_message,tx_position, *modbus_rx_message);
772
773 tx_position = mbAppendCrc16(mb_data->tx_buffer ,tx_position);
774 mb_data->tx_head=tx_position;
775 mbSend(mb_data);
776 mbClearRxFrame(mb_data);
777 }
778
779 uint32_t mbSlaveProcessPdu (uint8_t* response_string, uint8_t * msg, uint32_t tx_position, uint8_t deviceID)
780 {
781 uint32_t function_code;
782 uint32_t ret;
783
784 function_code = msg[OFFSET_FUNCTION_CODE];
785
786 switch (function_code)
787 {
788 case FC_READ_HOLDING_REGISTERS:
789 ret= mbSlaveReadHoldingRegisters(response_string, msg,tx_position, deviceID);
790 break;
791
792 case FC_WRITE_SINGLE_REGISTER:
793 ret = mbSlaveWriteSingleRegister(response_string, msg,tx_position, deviceID);
794 break;
795
796 case FC_WRITE_MULTIPLE_REGISTER:
797 ret=mbSlaveWriteMultipleRegisters(response_string, msg,tx_position, deviceID);
798 break;
799
800 default:
801 ret=mbSlaveResponseException(response_string,function_code,ILLEGAL_FUNCTION,tx_position);
802 break;
803 }
804
805 return ret;
806 }
807
808
809 uint32_t mbSlaveReadHoldingRegisters( uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID)
810 {
811 uint32_t start_adress;
812 uint32_t adress;
813 uint32_t number_of_registers;
814
815 /*stimmt die device ID mit der eigenen berein*/
816 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
817 {
818 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
819 }
820
821 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
822 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
823
824 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC3) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC3) )
825 {
826 return mbSlaveResponseException(response_string,FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_VALUE,tx_position);
827 }
828
829 if (start_adress+number_of_registers-1 > MAX_ADRESS)
830 {
831 return mbSlaveResponseException(response_string, FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_ADDRESS,tx_position);
832 }
833
834 response_string[tx_position] = FC_READ_HOLDING_REGISTERS; // FUNCTION CODE
835 tx_position++;
836 response_string[tx_position] = number_of_registers * 2; // Bytes
837 tx_position++;
838
839 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
840 {
841 /*Daten aus dem Speicher senden*/
842 response_string[tx_position] = sys_data.mb[adress].b[1];
843 tx_position++;
844 response_string[tx_position] = sys_data.mb[adress].b[0];
845 tx_position++;
846 }
847
848 return tx_position;
849 }
850
851
852 uint32_t mbSlaveWriteMultipleRegisters(uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID)
853 {
854
855 uint32_t start_adress;
856 uint32_t number_of_registers;
857 uint32_t adress;
858 uint32_t offset;
859
860 /*stimmt die device ID mit der eigenen berein*/
861 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
862 {
863 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
864 }
865
866 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
867 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
868 offset=7;
869
870 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC16) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC16) )
871 {
872 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_VALUE,tx_position);
873 }
874
875 if (start_adress+number_of_registers-1 > MAX_ADRESS)
876 {
877 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
878 }
879
880 /*Daten in Gertespeicher schreiben*/
881 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
882 {
883 sys_data.mb[adress].b[1] = msg[offset];
884 sys_data.mb[adress].b[0] = msg[offset+1];
885 offset+=2;
886 }
887
888 response_string[tx_position] = FC_WRITE_MULTIPLE_REGISTER; // FUNCTION CODE - 1 byte
889 tx_position++;
890 response_string[tx_position] = start_adress >> 8;
891 tx_position++;
892 response_string[tx_position] = (uint8_t ) ( start_adress & 0x00FF); // start adresse 2 byte
893 tx_position++;
894 response_string[tx_position] = number_of_registers >> 8;
895 tx_position++;
896 response_string[tx_position] = (uint8_t ) ( number_of_registers & 0x00FF); // Anzahl Register 2 byte
897 tx_position++;
898 return tx_position;
899 }
900
901
902 uint32_t mbSlaveWriteSingleRegister(uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID)
903 {
904
905 uint32_t adress;
906
907 /*stimmt die device ID mit der eigenen berein*/
908 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
909 {
910 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
911 }
912
913 adress = (msg[2] << 8) + msg[3];
914
915 if (adress > MAX_ADRESS)
916 {
917 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
918 }
919
920 /*schreibe Daten in eigenen Speicher*/
921 sys_data.mb[adress].b[1] = msg[4];
922 sys_data.mb[adress].b[0] = msg[5];
923
924 response_string[tx_position]= FC_WRITE_SINGLE_REGISTER; // FUNCTION CODE
925 tx_position++;
926 response_string[tx_position]= adress >> 8;
927 tx_position++;
928 response_string[tx_position]= (uint8_t ) ( adress & 0x00FF);
929
930 tx_position++;
931 response_string[tx_position]= msg[4];
932 tx_position++;
933 response_string[tx_position]= msg[5];
934 tx_position++;
935
936 return tx_position;
937 }
938
939
940 uint32_t mbSlaveResponseException(uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position )
941 {
942 function_code += 0x80;
943 response_string[tx_position] = function_code; // FUNCTION CODE
944 tx_position++;
945 response_string[tx_position] = exception_code; //
946 tx_position++;
947 return tx_position;
948 }
949
950
951 //---------------------------- UNKNOWN -----------------------------------------
952 //- -
953 //------------------------------------------------------------------------------
954
955#endif
956
Note: See TracBrowser for help on using the repository browser.