source: ecs_cellMon/firmware/src/modbus.c@ 14

Last change on this file since 14 was 3, checked in by f.jahn, 3 years ago

fw hinzugfügt-->zed

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