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

Last change on this file since 22 was 22, checked in by f.jahn, 4 months ago

DMA Rx funktioniert, aber BETA und nur feste Baudrate

File size: 20.2 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 --------------------------------------------
[22]69 extern volatile modbus_t modbusData;
70 extern volatile 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
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.w = 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
[22]160 mb_data->uart->Instance = USART2;
161 mb_data->uart->Init.BaudRate = baudrate;
[20]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;
[22]170 mb_data->uart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_SWAP_INIT;
171 mb_data->uart->AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;
[20]172
[22]173 // Init änderungen
[20]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
[22]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 uint32_t fixedDelayInBitDurations = (FAST_BAUDRATE_INTERFRAME_DELAY_us * baudrate) / 1000000UL + 1UL;
212// HAL_UART_EnableReceiverTimeout( usart);
213// HAL_UART_ReceiverTimeout_Config(usart, fixedDelayInBitDurations);
[20]214
[22]215 if(HAL_UARTEx_ReceiveToIdle_DMA(mb_data->uart, mb_data->rx_buffer, RXBUFFERSIZE) != HAL_OK)
[20]216 {
217 printf("uart error \n\r");
218 while(1)
219 {
220 }
221 }
222 }
223
224
225
[22]226void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
[20]227{
[22]228 if (huart->ErrorCode == HAL_UART_ERROR_RTO)
[20]229 {
[22]230 modbusData.mb_rx_frame_complete = 1;
231 modbusData.setRxLed = true;
232 modbusData.rx_head= 8;
233 printf("MB RTO Event! \n\r");
[20]234 }
235
[22]236 if(HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
237 {
238 printf("uart error \n\r");
239 // while(1)
240 // {
241 // }
242 }
243
[20]244}
245
[22]246void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
[20]247{
[22]248 printf("MB rxEvent!RX=%d \n\r",Size);
249 modbusData.setRxLed = true;
[20]250
[22]251 modbusData.mb_rx_frame_complete = 1;
252 modbusData.rx_head= Size +1;
[20]253
[22]254 if(HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
255 {
256 printf("uart error \n\r");
257 // while(1)
258 // {
259 // }
260 }
261
[20]262
263}
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 void mbSend(modbus_t * mb_data )
286 {
287 mb_data->current_query = MB_QUERY_SEND_DATA;
288 HAL_UART_Transmit_IT(mb_data->uart, mb_data->tx_buffer, mb_data->tx_head);
289 }
290
291 void mbClearTxBuffer(modbus_t * mb_data)
292 {
293 mb_data->tx_head = 0;
294 }
295
296
297
298 // Compute the MODBUS RTU CRC
299 uint16_t mbCrc16 ( uint8_t *buf, uint32_t len)
300 {
301 uint16_t crc = 0xFFFF;
302
303 for (uint32_t pos = 0; pos < len; pos++)
304 {
305 crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
306
307 for (int i = 8; i != 0; i--)
308 { // Loop over each bit
309 if ((crc & 0x0001) != 0)
310 { // If the LSB is set
311 crc >>= 1; // Shift right and XOR 0xA001
312 crc ^= 0xA001;
313 }
314 else // Else LSB is not set
315 {
316 crc >>= 1; // Just shift right
317 }
318 }
319 }
320
321 // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
322 return crc;
323 }
324
325 /* If CRC is correct returns msg_length else returns INVALID_CRC */
326 int mbCheckCrc16( uint8_t *msg, const int msg_length)
327 {
328 int ret;
329 uint16_t crc_calc;
330 uint16_t crc_received;
331
332 crc_calc = mbCrc16(msg, msg_length - 2);
333 crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2];
334
335 // Check CRC of msg
336 if (crc_calc == crc_received) {
337 ret = msg_length;
338 } else {
339 ret = INVALID_CRC;
340 }
341 return ret;
342 }
343
344 uint32_t mbAppendCrc16(uint8_t * buffer, uint32_t tx_position)
345 {
346 uint16_t crc = mbCrc16( buffer , tx_position);
347
348 uint8_t l_crc = (uint8_t) (crc & 0x00FF) ;
349 uint8_t h_crc = (uint8_t) (crc >> 8);
350 buffer[tx_position] = l_crc;
351 tx_position++;
352 buffer[tx_position] = h_crc;
353 tx_position++;
354 return tx_position;
355 }
356
357 /************************************************************************************************************
358 Function: mb_get_frame_complete
359 Purpose: Rckabe ob Frame komplett empfangen wurde
360 *************************************************************************************************************/
361 bool mbGetFrameComplete(modbus_t * mb_data)
362 {
363 return mb_data->mb_rx_frame_complete;
364 }
365
366 void mbClearRxFrame(modbus_t * mb_data)
367 {
368 // Wieder bei 0 im buffer anfangen
369 mb_data->rx_head = 0;
370
371 // keine Daten mehr vorhanden
372 mb_data->mb_rx_frame_complete=false;
373 }
374
375
376 // --------------------- SLAVE FUNCTIONS ---------------------------------------
377
378#define SEND_TO_SLAVES_BUFFER_COUNT 1000
379//static TASK_MODBUS_MASTER_Message_t xMessage[255];
380//static TASK_MODBUS_MASTER_Message_t *pxMessage;
381static bword_t values[SEND_TO_SLAVES_BUFFER_COUNT];
382static uint32_t y;
383static uint32_t z;
384
385 uint32_t mbSlaveCheckModbusRtuQuery(modbus_t * mb_data)
386 {
387 uint32_t message_lengh;
388 uint8_t *modbus_rx_message;
389 modbus_rx_message = mb_data->rx_buffer;
390 message_lengh= mb_data->rx_head;
391 uint32_t slave_adress;
392 slave_adress = modbus_rx_message[0];
393
394 if (message_lengh < 5) //Mindestens 5 Zeichen (Slave Adress + Function Code + 2x CRC
395 {
396 mbClearRxFrame(mb_data);
397 return 0;
398 }
399
400 // Prfe CRC
401 if (mbCheckCrc16(modbus_rx_message,message_lengh) == INVALID_CRC)
402 {
403 mbClearRxFrame(mb_data);
404 return 0;
405 }
406
407 if (slave_adress == MODBUS_BROADCAST_ADDRESS)
408 {
409
410 return RESPOND_TO_QUERY;
411 }
412 /* auf richtige Slave Adresse checken ansonsten nicht antworten*/
413 else if (slave_adress == sys_data.s.parameter.slave_address)
414 {
415 return RESPOND_TO_QUERY;
416 }
417
418 mbClearRxFrame(mb_data);
419 return 0;
420 }
421
422 void mbSlaveProcessRtuQuery(modbus_t * mb_data)
423 {
424 uint32_t tx_position=0; //die _Nchste_ Position in der Zeichen eingefgt werden mssen
425 uint8_t *modbus_rx_message;
426 modbus_rx_message = &mb_data->rx_buffer[0];
427
428 //Vorbereiten auf neues senden
429 mbClearTxBuffer(mb_data);
430
431 //mb_data->tx_buffer[0] = sys_data.s.vmGreenview.s.lb_slave_adress;
432 mb_data->tx_buffer[0] = *modbus_rx_message;
433 tx_position++;
434 tx_position = mbSlaveProcessPdu(mb_data->tx_buffer , modbus_rx_message,tx_position, *modbus_rx_message);
435
436 tx_position = mbAppendCrc16(mb_data->tx_buffer ,tx_position);
437 mb_data->tx_head=tx_position;
438 mbSend(mb_data);
439 mbClearRxFrame(mb_data);
440 }
441
442 uint32_t mbSlaveProcessPdu (uint8_t* response_string, uint8_t * msg, uint32_t tx_position, uint8_t deviceID)
443 {
444 uint32_t function_code;
445 uint32_t ret;
446
447 function_code = msg[OFFSET_FUNCTION_CODE];
448
449 switch (function_code)
450 {
451 case FC_READ_HOLDING_REGISTERS:
452 ret= mbSlaveReadHoldingRegisters(response_string, msg,tx_position, deviceID);
453 break;
454
455 case FC_WRITE_SINGLE_REGISTER:
456 ret = mbSlaveWriteSingleRegister(response_string, msg,tx_position, deviceID);
457 break;
458
459 case FC_WRITE_MULTIPLE_REGISTER:
460 ret=mbSlaveWriteMultipleRegisters(response_string, msg,tx_position, deviceID);
461 break;
462
463 default:
464 ret=mbSlaveResponseException(response_string,function_code,ILLEGAL_FUNCTION,tx_position);
465 break;
466 }
467
468 return ret;
469 }
470
471
472 uint32_t mbSlaveReadHoldingRegisters( uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID)
473 {
474 uint32_t start_adress;
475 uint32_t adress;
476 uint32_t number_of_registers;
477
478 /*stimmt die device ID mit der eigenen berein*/
479 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
480 {
481 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
482 }
483
484 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
485 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
486
487 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC3) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC3) )
488 {
489 return mbSlaveResponseException(response_string,FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_VALUE,tx_position);
490 }
491
492 if (start_adress+number_of_registers-1 > MAX_ADRESS)
493 {
494 return mbSlaveResponseException(response_string, FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_ADDRESS,tx_position);
495 }
496
497 response_string[tx_position] = FC_READ_HOLDING_REGISTERS; // FUNCTION CODE
498 tx_position++;
499 response_string[tx_position] = number_of_registers * 2; // Bytes
500 tx_position++;
501
502 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
503 {
504 /*Daten aus dem Speicher senden*/
505 response_string[tx_position] = sys_data.mb[adress].b[1];
506 tx_position++;
507 response_string[tx_position] = sys_data.mb[adress].b[0];
508 tx_position++;
509 }
510
511 return tx_position;
512 }
513
514
515 uint32_t mbSlaveWriteMultipleRegisters(uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID)
516 {
517
518 uint32_t start_adress;
519 uint32_t number_of_registers;
520 uint32_t adress;
521 uint32_t offset;
522
523 /*stimmt die device ID mit der eigenen berein*/
524 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
525 {
526 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
527 }
528
529 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
530 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
531 offset=7;
532
533 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC16) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC16) )
534 {
535 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_VALUE,tx_position);
536 }
537
538 if (start_adress+number_of_registers-1 > MAX_ADRESS)
539 {
540 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
541 }
542
543 /*Daten in Gertespeicher schreiben*/
544 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
545 {
546 sys_data.mb[adress].b[1] = msg[offset];
547 sys_data.mb[adress].b[0] = msg[offset+1];
548 offset+=2;
549 }
550
551 response_string[tx_position] = FC_WRITE_MULTIPLE_REGISTER; // FUNCTION CODE - 1 byte
552 tx_position++;
553 response_string[tx_position] = start_adress >> 8;
554 tx_position++;
555 response_string[tx_position] = (uint8_t ) ( start_adress & 0x00FF); // start adresse 2 byte
556 tx_position++;
557 response_string[tx_position] = number_of_registers >> 8;
558 tx_position++;
559 response_string[tx_position] = (uint8_t ) ( number_of_registers & 0x00FF); // Anzahl Register 2 byte
560 tx_position++;
561 return tx_position;
562 }
563
564
565 uint32_t mbSlaveWriteSingleRegister(uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID)
566 {
567
568 uint32_t adress;
569
570 /*stimmt die device ID mit der eigenen berein*/
571 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
572 {
573 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
574 }
575
576 adress = (msg[2] << 8) + msg[3];
577
578 if (adress > MAX_ADRESS)
579 {
580 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
581 }
582
583 /*schreibe Daten in eigenen Speicher*/
584 sys_data.mb[adress].b[1] = msg[4];
585 sys_data.mb[adress].b[0] = msg[5];
586
587 response_string[tx_position]= FC_WRITE_SINGLE_REGISTER; // FUNCTION CODE
588 tx_position++;
589 response_string[tx_position]= adress >> 8;
590 tx_position++;
591 response_string[tx_position]= (uint8_t ) ( adress & 0x00FF);
592
593 tx_position++;
594 response_string[tx_position]= msg[4];
595 tx_position++;
596 response_string[tx_position]= msg[5];
597 tx_position++;
598
599 return tx_position;
600 }
601
602
603 uint32_t mbSlaveResponseException(uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position )
604 {
605 function_code += 0x80;
606 response_string[tx_position] = function_code; // FUNCTION CODE
607 tx_position++;
608 response_string[tx_position] = exception_code; //
609 tx_position++;
610 return tx_position;
611 }
612
613
614 //---------------------------- UNKNOWN -----------------------------------------
615 //- -
616 //------------------------------------------------------------------------------
617
618#endif
619
Note: See TracBrowser for help on using the repository browser.