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

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