source: trunk/firmware/CubeMX/Src/modbus.c@ 10

Last change on this file since 10 was 1, checked in by f.jahn, 3 years ago
File size: 32.4 KB
Line 
1/*
2 * modbus.c
3 *
4 * Created: 03.09.2012 08:39:20
5 * Author: Falko Jahn
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 "log.h"
17 //#include "stm32_hal_legacy.h"
18 // ---------------------------------------------------------
19 // -------------------- MODUL DEFINES ----------------------
20 // ---------------------------------------------------------
21
22
23 #define TAG "MOD"
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 // --- Externe Variablen --------------------------------------------
68 extern modbus_t modbusData;
69 extern sys_data_t sys_data;
70
71
72 // --- Private Funktions Prototypen --------------------------------------------
73
74 void mbUartInit (modbus_t * mb_data,UART_HandleTypeDef * usart, uint32_t baudrate, uint32_t parityMode, uint32_t stopBits , uint32_t nrOfBitsPerChar);
75 uint16_t mbCrc16 (uint8_t *buf, uint32_t len);
76 void mbSend (modbus_t * mb_data );
77 uint32_t mbSlaveReadHoldingRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID);
78 uint32_t mbSlaveWriteMultipleRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID, modbus_t * mb_data);
79 uint32_t mbSlaveWriteSingleRegister (uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID, modbus_t * mb_data);
80 uint32_t mbSlaveResponseException (uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position) ;
81static HAL_StatusTypeDef RS485_ModbusEx_Init (UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime, uint32_t charReceiveTimeout);
82static void UART_TxISR_8BIT (UART_HandleTypeDef *huart);
83
84 // --- GEMEINSAME MODBUS FUNKTIONEN --------------------------------------------
85 // Diese Funktionen werden sowohl von Modbus Master als auch Modbus Slave verwendet
86
87 /*
88 *
89 * @brief Diese Funktion Initialisert die Modbus Datenstrukturen und die Hardware
90 *
91 * Das Modbus Modul benötigt einen UART und einen Timer pro Modbus Anschluss
92 * Die Funktion erfordert eine vorhandene Callback funktion namens HAL_UART_MspInit
93 * In dieser muss:
94 * - Der UART CLK eingeschaltet werden
95 * - Die Pins initialisert werden (Alternate Port Funktion)
96 * - Der NVIC Interrupt eingeschaltet werden
97 * @param mb_data : Datenstruktur zur Aufnahme aller Daten
98 * @param baudrate : Bautrate
99 * @param parityMode : Parity, möglich ist UART_PARITY_ODD, UART_PARITY_EVEN, UART_PARITY_NONE. Default ist lt. Modbus Standart EVEN
100 * @param usart : Timer Modul, z.B. USART1
101 * @retval None
102 */
103 void mbInit(modbus_t * mb_data, uint32_t baudrate, uint32_t parityMode, UART_HandleTypeDef * usart, accessMode_t * accessModeTable, uint16_t * currentAccessState)
104 {
105 uint32_t numberOfBitsPerChar;
106 uint32_t stopBits;
107
108 // Berechne Stop Bits
109 if ((parityMode == MODBUS_UART_PARITY_EVEN) || (parityMode == MODBUS_UART_PARITY_ODD))
110 {
111 stopBits = 1;
112 }
113 else
114 {
115 stopBits = 2;
116 }
117
118 // Berechne Anzahl der Bits per Char
119 numberOfBitsPerChar = NUMBER_OF_STARTBITS + NUMBER_OF_DATABITS + stopBits;
120 if ((parityMode == MODBUS_UART_PARITY_EVEN) || (parityMode == MODBUS_UART_PARITY_ODD))
121 {
122 numberOfBitsPerChar +=1;
123 }
124
125 mbUartInit(mb_data, usart, baudrate, parityMode, stopBits, numberOfBitsPerChar);
126
127 // Datenstrukturen zurücksetzen
128 mb_data->last_query_function_code = 0;
129 mb_data->last_query_tcp_id.w = 0;
130 mb_data->last_query_number_of_register.w = 0;
131 mb_data->current_query = MB_QUERY_NOTHING;
132 mb_data->last_query_slave_adress = 0;
133 mb_data->last_query_start_adress.w = 0;
134 mb_data->last_query_timeout = false;
135
136 mb_data->accessModeTable = accessModeTable;
137 mb_data->currentAccessState = currentAccessState;
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, möglich 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 LOG_E(TAG, "USART error!");
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 geändert
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 geändert
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 geändert
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 SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
378
379 /* Set the Driver Enable polarity */
380 MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
381
382 /* Set the Driver Enable assertion and deassertion times */
383 temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
384 temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
385 MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
386
387// EDIT ECS START
388 /*Set receive timeout time*/
389 SET_BIT(huart->Instance->CR2, USART_CR2_RTOEN);
390 SET_BIT(huart->Instance->CR1, USART_CR1_RTOIE);
391 MODIFY_REG(huart->Instance->RTOR, USART_RTOR_RTO, charReceiveTimeout);
392// EDIT ECS END
393
394 /* Enable the Peripheral */
395 __HAL_UART_ENABLE(huart);
396
397 /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
398 return (UART_CheckIdleState(huart));
399}
400
401
402//static int test;
403
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 /*DEBUG//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// if(__HAL_TIM_GET_FLAG(mb_data->timer, TIM_FLAG_CC1) != RESET)
600// {
601// if(__HAL_TIM_GET_IT_SOURCE(mb_data->timer, TIM_IT_CC1) !=RESET)
602// {
603// __HAL_TIM_CLEAR_IT(mb_data->timer, TIM_IT_CC1);
604// mb_data->timer->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
605
606 mb_data->mb_rx_frame_complete=true;
607// mb_data->timer->Instance->CNT =0;
608// HAL_TIM_OC_Stop_IT(mb_data->timer, TIM_CHANNEL_1);
609// mb_data->timer->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
610//
611// }
612// }
613 }
614
615
616 void mbSend(modbus_t * mb_data )
617 {
618 mb_data->current_query = MB_QUERY_SEND_DATA;
619 HAL_UART_Transmit_IT(mb_data->uart, mb_data->tx_buffer, mb_data->tx_head);
620 }
621
622 void mbClearTxBuffer(modbus_t * mb_data)
623 {
624 mb_data->tx_head = 0;
625 }
626
627
628
629 // Compute the MODBUS RTU CRC
630 uint16_t mbCrc16 ( uint8_t *buf, uint32_t len)
631 {
632 uint16_t crc = 0xFFFF;
633
634 for (uint32_t pos = 0; pos < len; pos++)
635 {
636 crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
637
638 for (int i = 8; i != 0; i--)
639 { // Loop over each bit
640 if ((crc & 0x0001) != 0)
641 { // If the LSB is set
642 crc >>= 1; // Shift right and XOR 0xA001
643 crc ^= 0xA001;
644 }
645 else // Else LSB is not set
646 {
647 crc >>= 1; // Just shift right
648 }
649 }
650 }
651
652 // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
653 return crc;
654 }
655
656 /* If CRC is correct returns msg_length else returns INVALID_CRC */
657 int mbCheckCrc16( uint8_t *msg, const int msg_length)
658 {
659 int ret;
660 uint16_t crc_calc;
661 uint16_t crc_received;
662
663 crc_calc = mbCrc16(msg, msg_length - 2);
664 crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2];
665
666 // Check CRC of msg
667 if (crc_calc == crc_received) {
668 ret = msg_length;
669 } else {
670 ret = INVALID_CRC;
671 }
672 return ret;
673 }
674
675 uint32_t mbAppendCrc16(uint8_t * buffer, uint32_t tx_position)
676 {
677 uint16_t crc = mbCrc16( buffer , tx_position);
678
679 uint8_t l_crc = (uint8_t) (crc & 0x00FF) ;
680 uint8_t h_crc = (uint8_t) (crc >> 8);
681 buffer[tx_position] = l_crc;
682 tx_position++;
683 buffer[tx_position] = h_crc;
684 tx_position++;
685 return tx_position;
686 }
687
688 /************************************************************************************************************
689 Function: mb_get_frame_complete
690 Purpose: Rückgabe ob Frame komplett empfangen wurde
691 *************************************************************************************************************/
692 bool mbGetFrameComplete(modbus_t * mb_data)
693 {
694 return mb_data->mb_rx_frame_complete;
695 }
696
697 void mbClearRxFrame(modbus_t * mb_data)
698 {
699 // Wieder bei 0 im buffer anfangen
700 mb_data->rx_head = 0;
701
702 // keine Daten mehr vorhanden
703 mb_data->mb_rx_frame_complete=false;
704 }
705
706
707 // --------------------- SLAVE FUNCTIONS ---------------------------------------
708
709#define SEND_TO_SLAVES_BUFFER_COUNT 1000
710//static TASK_MODBUS_MASTER_Message_t xMessage[255];
711//static TASK_MODBUS_MASTER_Message_t *pxMessage;
712//static bword_t values[SEND_TO_SLAVES_BUFFER_COUNT];
713//static uint32_t y;
714//static uint32_t z;
715
716 uint32_t mbSlaveCheckModbusRtuQuery(modbus_t * mb_data)
717 {
718 uint32_t message_lengh;
719 uint8_t *modbus_rx_message;
720 modbus_rx_message = mb_data->rx_buffer;
721 message_lengh= mb_data->rx_head;
722 uint32_t slave_adress;
723 slave_adress = modbus_rx_message[0];
724
725 if (message_lengh < 5) //Mindestens 5 Zeichen (Slave Adress + Function Code + 2x CRC
726 {
727 mbClearRxFrame(mb_data);
728 return 0;
729 }
730
731 // Prüfe CRC
732 if (mbCheckCrc16(modbus_rx_message,message_lengh) == INVALID_CRC)
733 {
734 mbClearRxFrame(mb_data);
735 return 0;
736 }
737
738 if (slave_adress == MODBUS_BROADCAST_ADDRESS)
739 {
740
741 return RESPOND_TO_QUERY;
742 }
743 /* auf richtige Slave Adresse checken ansonsten nicht antworten*/
744 else if (slave_adress == sys_data.s.slave_address)
745 {
746 return RESPOND_TO_QUERY;
747 }
748
749 mbClearRxFrame(mb_data);
750 return 0;
751 }
752
753 void mbSlaveProcessRtuQuery(modbus_t * mb_data)
754 {
755 uint32_t tx_position=0; //die Nächste Position in der Zeichen eingefügt werden müssen
756 uint8_t *modbus_rx_message;
757 modbus_rx_message = &mb_data->rx_buffer[0];
758
759 //Vorbereiten auf neues senden
760 mbClearTxBuffer(mb_data);
761
762 //mb_data->tx_buffer[0] = sys_data.s.vmGreenview.s.lb_slave_adress;
763 mb_data->tx_buffer[0] = *modbus_rx_message;
764 tx_position++;
765 tx_position = mbSlaveProcessPdu(mb_data->tx_buffer , modbus_rx_message,tx_position, *modbus_rx_message, mb_data);
766
767 tx_position = mbAppendCrc16(mb_data->tx_buffer ,tx_position);
768 mb_data->tx_head=tx_position;
769 mbSend(mb_data);
770 mbClearRxFrame(mb_data);
771 }
772
773 uint32_t mbSlaveProcessPdu (uint8_t* response_string, uint8_t * msg, uint32_t tx_position, uint8_t deviceID, modbus_t * mb_data)
774 {
775 uint32_t function_code;
776 uint32_t ret;
777
778 function_code = msg[OFFSET_FUNCTION_CODE];
779
780 switch (function_code)
781 {
782 case FC_READ_HOLDING_REGISTERS:
783 ret= mbSlaveReadHoldingRegisters(response_string, msg,tx_position, deviceID);
784 break;
785
786 case FC_WRITE_SINGLE_REGISTER:
787 ret = mbSlaveWriteSingleRegister(response_string, msg,tx_position, deviceID, mb_data);
788 break;
789
790 case FC_WRITE_MULTIPLE_REGISTER:
791 ret=mbSlaveWriteMultipleRegisters(response_string, msg,tx_position, deviceID, mb_data);
792 break;
793
794 default:
795 ret=mbSlaveResponseException(response_string, function_code, ILLEGAL_FUNCTION, tx_position);
796 break;
797 }
798
799 return ret;
800 }
801
802
803 uint32_t mbSlaveReadHoldingRegisters( uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID)
804 {
805 uint32_t start_adress;
806 uint32_t adress;
807 uint32_t number_of_registers;
808
809 /*stimmt die device ID mit der eigenen Äberein*/
810 if((deviceID != sys_data.s.slave_address) && (deviceID != 0))
811 {
812 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
813 }
814
815 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
816 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
817
818 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC3) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC3) )
819 {
820 return mbSlaveResponseException(response_string,FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_VALUE,tx_position);
821 }
822
823 if (start_adress+number_of_registers-1 > MAX_ADRESS)
824 {
825 return mbSlaveResponseException(response_string, FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_ADDRESS,tx_position);
826 }
827
828 response_string[tx_position] = FC_READ_HOLDING_REGISTERS; // FUNCTION CODE
829 tx_position++;
830 response_string[tx_position] = number_of_registers * 2; // Bytes
831 tx_position++;
832
833 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
834 {
835 /*Daten aus dem Speicher senden*/
836 response_string[tx_position] = sys_data.mb[adress].b[1];
837 tx_position++;
838 response_string[tx_position] = sys_data.mb[adress].b[0];
839 tx_position++;
840 }
841
842 return tx_position;
843 }
844
845
846 uint32_t mbSlaveWriteMultipleRegisters(uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID, modbus_t * mb_data)
847 {
848
849 uint32_t start_adress;
850 uint32_t number_of_registers;
851 uint32_t adress;
852 uint32_t offset;
853
854 /*stimmt die device ID mit der eigenen Äberein*/
855 if((deviceID != sys_data.s.slave_address) && (deviceID != 0))
856 {
857 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
858 }
859
860 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
861 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
862 offset=7;
863
864 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC16) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC16) )
865 {
866 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_VALUE,tx_position);
867 }
868
869 if (start_adress+number_of_registers-1 > MAX_ADRESS)
870 {
871 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
872 }
873
874 /*Daten in Gerätespeicher schreiben*/
875 for(adress = start_adress; adress < (start_adress + number_of_registers); adress++)
876 {
877 //Schreibzugriff prüfen
878 if (mb_data->accessModeTable[adress] == ACCESS_MODE_READ_ONLY)
879 {
880 // Schreibzugriff nicht erlaubt
881 offset+=2;
882 continue;
883
884 }
885
886 //Schreibzugriff prüfen
887 if ((mb_data->accessModeTable[adress] == ACCESS_MODE_WRITE_PROTECTABLE ) && (*mb_data->currentAccessState == 0))
888 {
889 // Schreibzugriff nicht erlaubt
890 offset+=2;
891 continue;
892 }
893
894 sys_data.mb[adress].b[1] = msg[offset];
895 sys_data.mb[adress].b[0] = msg[offset+1];
896 offset+=2;
897 }
898
899 response_string[tx_position] = FC_WRITE_MULTIPLE_REGISTER; // FUNCTION CODE - 1 byte
900 tx_position++;
901 response_string[tx_position] = start_adress >> 8;
902 tx_position++;
903 response_string[tx_position] = (uint8_t ) ( start_adress & 0x00FF); // start adresse 2 byte
904 tx_position++;
905 response_string[tx_position] = number_of_registers >> 8;
906 tx_position++;
907 response_string[tx_position] = (uint8_t ) ( number_of_registers & 0x00FF); // Anzahl Register 2 byte
908 tx_position++;
909 return tx_position;
910 }
911
912
913 uint32_t mbSlaveWriteSingleRegister(uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID, modbus_t * mb_data)
914 {
915
916 uint32_t adress;
917
918 /*stimmt die device ID mit der eigenen Äberein*/
919 if((deviceID != sys_data.s.slave_address) && (deviceID != 0))
920 {
921 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
922 }
923
924 adress = (msg[2] << 8) + msg[3];
925
926 if (adress > MAX_ADRESS)
927 {
928 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
929 }
930
931 //Schreibzugriff prüfen
932 if (mb_data->accessModeTable[adress] == ACCESS_MODE_READ_ONLY)
933 {
934 // Schreibzugriff nicht erlaubt
935 //printf("Error, read only Register!\n");
936 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
937 }
938
939
940 //Schreibzugriff prüfen
941 if ((mb_data->accessModeTable[adress] == ACCESS_MODE_WRITE_PROTECTABLE ) && (*mb_data->currentAccessState == 0))
942 {
943 // Schreibzugriff nicht erlaubt
944 //printf("Protected Register, write not allowed!\n");
945 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
946 }
947
948 /*schreibe Daten in eigenen Speicher*/
949 sys_data.mb[adress].b[1] = msg[4];
950 sys_data.mb[adress].b[0] = msg[5];
951
952 response_string[tx_position]= FC_WRITE_SINGLE_REGISTER; // FUNCTION CODE
953 tx_position++;
954 response_string[tx_position]= adress >> 8;
955 tx_position++;
956 response_string[tx_position]= (uint8_t ) ( adress & 0x00FF);
957
958 tx_position++;
959 response_string[tx_position]= msg[4];
960 tx_position++;
961 response_string[tx_position]= msg[5];
962 tx_position++;
963
964 return tx_position;
965 }
966
967
968 uint32_t mbSlaveResponseException(uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position )
969 {
970 function_code += 0x80;
971 response_string[tx_position] = function_code; // FUNCTION CODE
972 tx_position++;
973 response_string[tx_position] = exception_code; //
974 tx_position++;
975 return tx_position;
976 }
977
978
979 //---------------------------- UNKNOWN -----------------------------------------
980 //- -
981 //------------------------------------------------------------------------------
982
983#endif
Note: See TracBrowser for help on using the repository browser.