source: trunk/firmware/Modbus/modbus.c @ 6

Last change on this file since 6 was 6, checked in by f.jahn, 3 months ago
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 "stm32g0xx_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.=   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.