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

Last change on this file since 23 was 23, checked in by f.jahn, 23 hours ago

modbus via DMA still BETA, aber bautratenumschaltung implementiert

File size: 19.8 KB
RevLine 
[20]1/*
2 * modbus.c
3 *
4 * Created: 03.09.2012 08:39:20
5 *  Author: Falko
6 */ 
7
8
9
10#if MODBUS_SUPPORT == TRUE
11 
12  #include "modbus.h"
13  //#include "stm32g4xx_hal.h"
14  #include "main.h"
15  //#include "stm32g0xx_hal_tim.h"
16  //#include "stm32_hal_legacy.h"
17  #include <stdio.h>
18  // ---------------------------------------------------------
19  // -------------------- MODUL DEFINES ----------------------
20  // ---------------------------------------------------------
21
22
23               
24
25  #define MODBUS_BROADCAST_ADDRESS        0x00
26  #define FC_READ_COILS                   0x01
27  #define FC_READ_HOLDING_REGISTERS       0x03
28  #define FC_WRITE_SINGLE_REGISTER        0x06
29  #define FC_WRITE_MULTIPLE_REGISTER      0x10
30
31  /* Protocol exceptions */
32  #define ILLEGAL_FUNCTION                0x01
33  #define ILLEGAL_DATA_ADDRESS            0x02
34  #define ILLEGAL_DATA_VALUE              0x03
35  #define SLAVE_DEVICE_FAILURE            0x04
36  #define SERVER_FAILURE                    0x04
37  #define ACKNOWLEDGE                     0x05
38  #define SLAVE_DEVICE_BUSY               0x06
39  #define SERVER_BUSY                     0x06
40  #define NEGATIVE_ACKNOWLEDGE            0x07
41  #define MEMORY_PARITY_ERROR             0x08
42  #define GATEWAY_PROBLEM_PATH            0x0A
43  #define GATEWAY_PROBLEM_TARGET            0x0B
44
45  /* Local Error codes */
46  #define INVALID_CRC                     -1
47
48  // Position der Daten im Rx String
49  #define OFFSET_SLAVE_ADRESS             0x00
50  #define OFFSET_FUNCTION_CODE            0x01
51  #define OFFSET_START_ADRESS_HI          0x02
52  #define OFFSET_START_ADRESS_LO          0x03
53  #define OFFSET_NO_OF_REGISTERS_HI       0x04
54  #define OFFSET_NO_OF_REGISTERS_LO       0x05
55
56  #define MIN_NUMBER_OF_REGISTERS_FC3     0x01
57  #define MAX_NUMBER_OF_REGISTERS_FC3     0x7D
58  #define MIN_NUMBER_OF_REGISTERS_FC16    0x01
59  #define MAX_NUMBER_OF_REGISTERS_FC16    0x7B
60
61  #ifdef DEBUG
62    #define RESPONSE_TIMEOUT                300 // * 1ms
63  #else
64    #define RESPONSE_TIMEOUT                1000 // * 1ms
65  #endif
66
67  #define FAST_BAUDRATE_INTERFRAME_DELAY_us   (1750UL)
68  // --- Externe Variablen --------------------------------------------
[23]69  extern  modbus_t modbusData;
70  extern  sys_data_t sys_data;
[20]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
[23]111
[20]112    // Berechne Anzahl der Bits per Char
113    numberOfBitsPerChar = NUMBER_OF_STARTBITS + NUMBER_OF_DATABITS + stopBits;
114    if ((parityMode == MODBUS_UART_PARITY_EVEN) || (parityMode == MODBUS_UART_PARITY_ODD)) 
115    {
116      numberOfBitsPerChar +=1; 
117    }
118     
119    mbUartInit(mb_data,usart, baudrate, parityMode, stopBits, numberOfBitsPerChar);
120
121    // Datenstrukturen zurcksetzen
122    mb_data->last_query_function_code         =   0;
123    mb_data->last_query_tcp_id.w              =   0;
124    mb_data->last_query_number_of_register.=   0;
125    mb_data->current_query                    =   MB_QUERY_NOTHING;
126    mb_data->last_query_slave_adress          =   0;
127    mb_data->last_query_start_adress.w        =   0;
128    mb_data->last_query_timeout               =   false;
129  }
130
131  /*
132    *
133    * @brief  Diese Funktion Initialisert die Modbus UART Hardware
134    *
135    * @param  mb_data : Datenstruktur zur Aufnahme aller Daten
136    * @param  usart : UART Modul, z.B. USART1
137    * @param  baudrate : UART BAUD
138    * @param  parityMmode : Parity, mglich ist:
139              UART_PARITY_ODD, UART_PARITY_EVEN, UART_PARITY_NONE.
140              Default ist lt. Modbus Standart EVEN
141    * @param  stopBits : Anzahl der Stop Bits, lt Modbus Standart
142    *         2 Stop Bits bei Parity None, ansonsten 2 Stop Bits
143    * @retval None   
144  */
145  void mbUartInit(modbus_t * mb_data,UART_HandleTypeDef * usart, uint32_t baudrate,  uint32_t parityMode,  uint32_t stopBits , uint32_t nrOfBitsPerChar)
146  {
147    //--- Uart Init ------------------------------------------------------------
148    mb_data->uart      = usart;
149   
150    // Baudrate
151    mb_data->uart->Init.BaudRate   = baudrate;
[23]152
[20]153    // Parity Mode // Word length
154    if(parityMode == MODBUS_UART_PARITY_EVEN)
155    {
156       mb_data->uart->Init.Parity = UART_PARITY_EVEN;
157       mb_data->uart->Init.WordLength = UART_WORDLENGTH_9B;
158    } 
159    else if(parityMode == MODBUS_UART_PARITY_ODD)
160    {
161       mb_data->uart->Init.Parity = UART_PARITY_ODD;
162       mb_data->uart->Init.WordLength = UART_WORDLENGTH_9B;
163    }
164    else
165    {
166       mb_data->uart->Init.Parity = UART_PARITY_NONE;
167       mb_data->uart->Init.WordLength = UART_WORDLENGTH_8B;
168    }
[23]169
[20]170    // Stopbits
171    if (stopBits == 1)
172    { 
173      mb_data->uart->Init.StopBits = UART_STOPBITS_1;
174    }
175    else
176    {
177      mb_data->uart->Init.StopBits = UART_STOPBITS_2;
178    }
[23]179
180        if (HAL_UART_Init(mb_data->uart) != HAL_OK)
181        {
182          Error_Handler();
183        }
184       
[22]185        uint32_t fixedDelayInBitDurations = (FAST_BAUDRATE_INTERFRAME_DELAY_us * baudrate) / 1000000UL + 1UL;
186//      HAL_UART_EnableReceiverTimeout( usart);
187//      HAL_UART_ReceiverTimeout_Config(usart,  fixedDelayInBitDurations);
[20]188
[22]189    if(HAL_UARTEx_ReceiveToIdle_DMA(mb_data->uart, mb_data->rx_buffer, RXBUFFERSIZE) != HAL_OK)
[20]190    {
191      printf("uart error \n\r");
192      while(1)
193      {
194      }     
195    }   
196  }
197
198
199
[22]200void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
[20]201{
[23]202    modbusData.mb_rx_frame_complete = 1;
203    modbusData.setRxLed = false;
204        modbusData.rx_head= 0;
205
206
[22]207  if (huart->ErrorCode == HAL_UART_ERROR_RTO)
[20]208  {
[22]209        printf("MB RTO Event! \n\r");
[20]210  }
[23]211  if (huart->ErrorCode == HAL_UART_ERROR_FE)
212  {
213        printf("MB FE Error! \n\r");
214  }
215 
216  if (huart->ErrorCode == HAL_UART_ERROR_PE)
217  {
218        printf("MB PE Error! \n\r");
219  }
[20]220
[23]221  if (huart->ErrorCode == HAL_UART_ERROR_NE)
222  {
223        printf("MB NE Error! \n\r");
224  }
225
226  if (huart->ErrorCode == HAL_UART_ERROR_DMA)
227  {
228        printf("MB DMA Error! \n\r");
229  }
230
231  if (huart->ErrorCode == HAL_UART_ERROR_DMA)
232  {
233        printf("MB DMA Error! \n\r");
234  }
235
236  if (huart->ErrorCode == HAL_UART_ERROR_ORE)
237  {
238        printf("MB ORE Error! \n\r");
239  }
240
241
[22]242  if(HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
243   {
[23]244     printf("Uart Error bei neustart nach Fehler \n\r");
[22]245  //   while(1)
246  //   {
247  //   }     
248   }   
249 
[20]250}
251
[22]252void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
[20]253{
[23]254  //printf("MB rxEvent!RX=%d \n\r",Size);
[22]255  modbusData.setRxLed = true;
[20]256
[22]257  modbusData.mb_rx_frame_complete = 1;
258  modbusData.rx_head= Size +1;
[20]259
[22]260  if(HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
261   {
262     printf("uart error \n\r");
263  //   while(1)
264  //   {
265  //   }     
266   }   
267 
[20]268
269}
270
[23]271void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
272{
273  //printf("uart complete \n\r");
274  modbusData.current_query = MB_QUERY_NOTHING;
[20]275
[23]276}
[20]277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
[23]296
297
[20]298  void mbSend(modbus_t * mb_data )
299  {   
300    mb_data->current_query = MB_QUERY_SEND_DATA;
[23]301    HAL_UART_Transmit_DMA(mb_data->uart, mb_data->tx_buffer, mb_data->tx_head);
[20]302  }
303
304  void mbClearTxBuffer(modbus_t * mb_data)
305  {
306    mb_data->tx_head = 0;
307  }
308
309
310
311  // Compute the MODBUS RTU CRC
312  uint16_t mbCrc16 ( uint8_t *buf, uint32_t len)
313  {
314    uint16_t crc = 0xFFFF;
315
316    for (uint32_t pos = 0; pos < len; pos++) 
317    {
318      crc ^= (uint16_t)buf[pos];          // XOR byte into least sig. byte of crc
319   
320      for (int i = 8; i != 0; i--) 
321      {    // Loop over each bit
322        if ((crc & 0x0001) != 0) 
323        {      // If the LSB is set
324                crc >>= 1;                    // Shift right and XOR 0xA001
325                crc ^= 0xA001;
326        }
327        else                            // Else LSB is not set
328        {
329                crc >>= 1;                    // Just shift right
330        }
331      }
332    }                                   
333 
334    // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
335    return crc; 
336  }
337
338  /* If CRC is correct returns msg_length else returns INVALID_CRC */
339  int mbCheckCrc16( uint8_t *msg, const int msg_length) 
340  {
341    int ret;
342    uint16_t crc_calc;
343    uint16_t crc_received;
344
345    crc_calc = mbCrc16(msg, msg_length - 2);
346    crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2];
347
348    // Check CRC of msg
349    if (crc_calc == crc_received) {
350            ret = msg_length;
351    } else {
352            ret = INVALID_CRC;
353    }
354    return ret;
355  }
356
357  uint32_t mbAppendCrc16(uint8_t * buffer, uint32_t tx_position)
358  {
359    uint16_t crc = mbCrc16( buffer , tx_position);
360 
361    uint8_t l_crc = (uint8_t) (crc & 0x00FF) ;
362    uint8_t h_crc = (uint8_t) (crc >> 8);
363    buffer[tx_position] = l_crc;
364    tx_position++;
365    buffer[tx_position] = h_crc; 
366    tx_position++;
367    return tx_position; 
368  }
369
370  /************************************************************************************************************
371  Function: mb_get_frame_complete
372  Purpose:  Rckabe ob Frame komplett empfangen wurde
373  *************************************************************************************************************/
374  bool mbGetFrameComplete(modbus_t * mb_data)
375  {
376          return mb_data->mb_rx_frame_complete;
377  }
378
379  void mbClearRxFrame(modbus_t * mb_data)
380  {
381    // Wieder bei 0 im buffer anfangen
382    mb_data->rx_head = 0;
383 
384    // keine Daten mehr vorhanden
385    mb_data->mb_rx_frame_complete=false; 
386  }
387
388
389  // --------------------- SLAVE FUNCTIONS ---------------------------------------     
390
391#define SEND_TO_SLAVES_BUFFER_COUNT 1000
392//static TASK_MODBUS_MASTER_Message_t xMessage[255];
393//static TASK_MODBUS_MASTER_Message_t *pxMessage;
394static bword_t values[SEND_TO_SLAVES_BUFFER_COUNT];
395static uint32_t y;
396static uint32_t z;
397
398  uint32_t mbSlaveCheckModbusRtuQuery(modbus_t * mb_data)
399  {
400    uint32_t message_lengh;
401    uint8_t *modbus_rx_message;
402    modbus_rx_message = mb_data->rx_buffer;
403    message_lengh= mb_data->rx_head;
404    uint32_t slave_adress;
405    slave_adress = modbus_rx_message[0];
406 
407    if (message_lengh < 5) //Mindestens 5 Zeichen (Slave Adress + Function Code + 2x CRC
408    {
409      mbClearRxFrame(mb_data);
410      return 0;
411    } 
412 
413    // Prfe CRC
414    if (mbCheckCrc16(modbus_rx_message,message_lengh) == INVALID_CRC)
415    {
416      mbClearRxFrame(mb_data);
417      return 0;
418    }
419
420    if  (slave_adress == MODBUS_BROADCAST_ADDRESS)
421    {
422
423      return  RESPOND_TO_QUERY; 
424    } 
425    /* auf richtige Slave Adresse checken ansonsten nicht antworten*/
426    else if (slave_adress == sys_data.s.parameter.slave_address)
427    {
428      return RESPOND_TO_QUERY;
429    }
430   
431    mbClearRxFrame(mb_data);
432    return 0;
433  }
434
435  void mbSlaveProcessRtuQuery(modbus_t * mb_data)
436  {
437    uint32_t tx_position=0; //die _Nchste_ Position in der Zeichen eingefgt werden mssen
438    uint8_t *modbus_rx_message;
439    modbus_rx_message = &mb_data->rx_buffer[0];
440
441    //Vorbereiten auf neues senden
442    mbClearTxBuffer(mb_data);
443 
444    //mb_data->tx_buffer[0] = sys_data.s.vmGreenview.s.lb_slave_adress;
445    mb_data->tx_buffer[0] = *modbus_rx_message;
446    tx_position++;
447    tx_position = mbSlaveProcessPdu(mb_data->tx_buffer , modbus_rx_message,tx_position, *modbus_rx_message);
448 
449    tx_position = mbAppendCrc16(mb_data->tx_buffer ,tx_position);       
450    mb_data->tx_head=tx_position;
451    mbSend(mb_data);   
452    mbClearRxFrame(mb_data);   
453  }
454
455  uint32_t mbSlaveProcessPdu (uint8_t* response_string,    uint8_t * msg,    uint32_t tx_position,     uint8_t deviceID)
456  {
457    uint32_t function_code;
458    uint32_t ret;
459   
460    function_code = msg[OFFSET_FUNCTION_CODE];
461
462    switch (function_code)
463    {
464      case FC_READ_HOLDING_REGISTERS:
465      ret= mbSlaveReadHoldingRegisters(response_string, msg,tx_position, deviceID);
466      break;
467   
468      case FC_WRITE_SINGLE_REGISTER:
469      ret = mbSlaveWriteSingleRegister(response_string, msg,tx_position, deviceID);
470      break;
471   
472      case FC_WRITE_MULTIPLE_REGISTER:
473      ret=mbSlaveWriteMultipleRegisters(response_string, msg,tx_position, deviceID);
474      break;
475   
476      default:
477      ret=mbSlaveResponseException(response_string,function_code,ILLEGAL_FUNCTION,tx_position);
478      break;
479    }
480 
481    return ret;
482  }
483
484
485  uint32_t mbSlaveReadHoldingRegisters( uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID)
486  {
487    uint32_t start_adress;
488    uint32_t adress;
489    uint32_t number_of_registers;
490
491    /*stimmt die device ID mit der eigenen berein*/
492    if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
493    {
494       return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
495    }
496
497    start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
498    number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
499 
500    if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC3) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC3) )
501    {
502      return mbSlaveResponseException(response_string,FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_VALUE,tx_position);
503    }
504 
505    if (start_adress+number_of_registers-1 > MAX_ADRESS) 
506    {
507      return mbSlaveResponseException(response_string, FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_ADDRESS,tx_position);
508    }   
509
510    response_string[tx_position] = FC_READ_HOLDING_REGISTERS;                                                                                   // FUNCTION CODE
511    tx_position++;
512    response_string[tx_position] = number_of_registers * 2;                                                                                             // Bytes
513    tx_position++;
514
515    for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
516    {
517      /*Daten aus dem Speicher senden*/
518      response_string[tx_position] = sys_data.mb[adress].b[1];
519      tx_position++;
520      response_string[tx_position] = sys_data.mb[adress].b[0];
521      tx_position++;
522    }
523 
524    return tx_position;
525  }
526
527
528  uint32_t mbSlaveWriteMultipleRegisters(uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID)
529  {
530   
531    uint32_t start_adress;
532    uint32_t number_of_registers;
533    uint32_t adress;
534    uint32_t offset;
535
536    /*stimmt die device ID mit der eigenen berein*/
537    if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
538    {
539       return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
540    }
541
542    start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
543    number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
544    offset=7;
545
546    if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC16) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC16) )
547    {
548      return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_VALUE,tx_position);
549    }
550
551    if (start_adress+number_of_registers-1 > MAX_ADRESS) 
552    {
553      return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
554    }
555   
556    /*Daten in Gertespeicher schreiben*/
557    for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
558    { 
559      sys_data.mb[adress].b[1] = msg[offset];
560      sys_data.mb[adress].b[0] = msg[offset+1];
561      offset+=2;
562    }
563
564    response_string[tx_position] = FC_WRITE_MULTIPLE_REGISTER; // FUNCTION CODE - 1 byte
565    tx_position++;
566    response_string[tx_position] = start_adress >> 8; 
567    tx_position++;
568    response_string[tx_position] = (uint8_t ) ( start_adress  & 0x00FF); // start adresse 2 byte
569    tx_position++;
570    response_string[tx_position] = number_of_registers >> 8; 
571    tx_position++;
572    response_string[tx_position] = (uint8_t ) ( number_of_registers  & 0x00FF); // Anzahl Register 2 byte
573    tx_position++;
574    return tx_position;
575  }
576
577
578  uint32_t mbSlaveWriteSingleRegister(uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID)
579  {
580 
581    uint32_t adress;
582
583    /*stimmt die device ID mit der eigenen berein*/
584    if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
585    {
586       return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
587    }
588
589    adress = (msg[2] << 8) + msg[3];
590
591    if (adress >  MAX_ADRESS) 
592    {
593      return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
594    }   
595
596    /*schreibe Daten in eigenen Speicher*/
597    sys_data.mb[adress].b[1] = msg[4];
598    sys_data.mb[adress].b[0] = msg[5];
599
600    response_string[tx_position]= FC_WRITE_SINGLE_REGISTER; // FUNCTION CODE
601    tx_position++;
602    response_string[tx_position]= adress >> 8; 
603    tx_position++;
604    response_string[tx_position]= (uint8_t ) ( adress  & 0x00FF);
605   
606    tx_position++;
607    response_string[tx_position]= msg[4]; 
608    tx_position++;
609    response_string[tx_position]= msg[5];
610    tx_position++;
611
612    return tx_position;
613  }
614
615
616  uint32_t mbSlaveResponseException(uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position ) 
617  {
618    function_code += 0x80;
619    response_string[tx_position] = function_code; //  FUNCTION CODE
620    tx_position++;
621    response_string[tx_position] = exception_code; //
622    tx_position++;
623    return tx_position;
624  }
625
626
627  //---------------------------- UNKNOWN -----------------------------------------
628  //-                                                                            -
629  //------------------------------------------------------------------------------
630
631#endif
632       
Note: See TracBrowser for help on using the repository browser.