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

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