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

Last change on this file since 26 was 26, checked in by f.jahn, 3 months ago
  • Bug in ADC Kalibrierung (STM32 ADC Strom) behoben
  • DMA Buffer für ADC 1 und ADC wird vor Überschreibung während bearbeitung geschützt, indem Datenübertragung nur einmalig erfolgt und erst nach Auswertung wieder gestartet wird
  • RS485Modbus: Timeout Zeit wird für Baudraten >19200 korrekt berechnet
  • Hardware ID geändert
  • Separates Register für "Batterie Empty detection mode" auf Adresse 92 angelegt
File size: 20.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 "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 --------------------------------------------
69 extern modbus_t modbusData;
70 extern sys_data_t sys_data;
71
72
73 // --- Private Funktions Prototypen --------------------------------------------
74
75 void mbUartInit (modbus_t * mb_data,UART_HandleTypeDef * usart, uint32_t baudrate, uint32_t parityMode, uint32_t stopBits , uint32_t nrOfBitsPerChar);
76 uint16_t mbCrc16 (uint8_t *buf, uint32_t len);
77 void mbSend (modbus_t * mb_data );
78 uint32_t mbSlaveReadHoldingRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID);
79 uint32_t mbSlaveWriteMultipleRegisters (uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID);
80 uint32_t mbSlaveWriteSingleRegister (uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID);
81 uint32_t mbSlaveResponseException (uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position) ;
82static HAL_StatusTypeDef RS485_ModbusEx_Init (UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime, uint32_t charReceiveTimeout);
83static void UART_TxISR_8BIT (UART_HandleTypeDef *huart);
84
85 // --- GEMEINSAME MODBUS FUNKTIONEN --------------------------------------------
86 // Diese Funktionen werden sowohl von Modbus Master als auch Modbus Slave verwendet
87
88 /*
89 *
90 * @brief Diese Funktion Initialisert die Modbus Datenstrukturen und die Hardware
91 *
92 * Das Modbus Modul bentigt einen UART und einen Timer pro Modbus Anschluss
93 * Die Funktion erfordert eine vorhandene Callback funktion namens HAL_UART_MspInit
94 * In dieser muss:
95 * - Der UART CLK eingeschaltet werden
96 * - Die Pins initialisert werden (Alternate Port Funktion)
97 * - Der NVIC Interrupt eingeschaltet werden
98 * @param mb_data : Datenstruktur zur Aufnahme aller Daten
99 * @param baudrate : Bautrate
100 * @param parityMode : Parity, mglich ist UART_PARITY_ODD, UART_PARITY_EVEN, UART_PARITY_NONE. Default ist lt. Modbus Standart EVEN
101 * @param usart : Timer Modul, z.B. USART1
102 * @retval None
103 */
104 void mbInit(modbus_t* mb_data, uint32_t baudrate, uint32_t parityMode, uint16_t stopBits, UART_HandleTypeDef* usart)
105 {
106 uint32_t numberOfBitsPerChar;
107 //uint32_t stopBits;
108
109 if (stopBits < 1U || stopBits > 2U) stopBits = 1U;
110
111
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.w = 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;
152
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 }
169
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 }
179
180 if (HAL_UART_Init(mb_data->uart) != HAL_OK)
181 {
182 Error_Handler();
183 }
184
185
186 HAL_UART_EnableReceiverTimeout( usart);
187 if (baudrate <= 19200)
188 {
189 HAL_UART_ReceiverTimeout_Config(usart, 3.5 * nrOfBitsPerChar);
190 }
191 else
192 {
193 uint32_t fixedDelayInBitDurations = (FAST_BAUDRATE_INTERFRAME_DELAY_us * baudrate) / 1000000UL + 1UL;
194 HAL_UART_ReceiverTimeout_Config(usart, fixedDelayInBitDurations);
195 }
196
197
198 SET_BIT(usart->Instance->CR1, USART_CR1_RTOIE);
199
200
201 if(HAL_UART_Receive_DMA(mb_data->uart, mb_data->rx_buffer, RXBUFFERSIZE) != HAL_OK)
202 {
203 printf("uart error \n\r");
204 while(1)
205 {
206 }
207 }
208 }
209
210
211
212void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
213{
214 modbusData.mb_rx_frame_complete = 1;
215 modbusData.setRxLed = false;
216 modbusData.rx_head = huart->RxXferSize - __HAL_DMA_GET_COUNTER(huart->hdmarx);
217
218
219 if (huart->ErrorCode == HAL_UART_ERROR_RTO)
220 {
221
222 // printf("MB RTO Event! \n\r");
223 // Kein Fehler, normale Funktion
224 }
225 if (huart->ErrorCode == HAL_UART_ERROR_FE)
226 {
227 printf("MB FE Error! \n\r");
228 }
229
230 if (huart->ErrorCode == HAL_UART_ERROR_PE)
231 {
232 printf("MB PE Error! \n\r");
233 }
234
235 if (huart->ErrorCode == HAL_UART_ERROR_NE)
236 {
237 printf("MB NE Error! \n\r");
238 }
239
240 if (huart->ErrorCode == HAL_UART_ERROR_DMA)
241 {
242 printf("MB DMA Error! \n\r");
243 }
244
245 if (huart->ErrorCode == HAL_UART_ERROR_DMA)
246 {
247 printf("MB DMA Error! \n\r");
248 }
249
250 if (huart->ErrorCode == HAL_UART_ERROR_ORE)
251 {
252 printf("MB ORE Error! \n\r");
253 }
254
255
256
257 if(HAL_UART_Receive_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
258 {
259 printf("Uart Error bei neustart nach Fehler \n\r");
260 // while(1)
261 // {
262 // }
263 }
264
265}
266
267//void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
268//{
269// //printf("MB rxEvent!RX=%d \n\r",Size);
270// modbusData.setRxLed = true;
271
272// modbusData.mb_rx_frame_complete = 1;
273// modbusData.rx_head= Size +1;
274
275// if(HAL_UART_Receive_DMA(huart, huart->pRxBuffPtr, RXBUFFERSIZE) != HAL_OK)
276// {
277// printf("uart error \n\r");
278// // while(1)
279// // {
280// // }
281// }
282
283
284//}
285
286void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
287{
288 //printf("uart complete \n\r");
289 modbusData.current_query = MB_QUERY_NOTHING;
290
291}
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 void mbSend(modbus_t * mb_data )
314 {
315 mb_data->current_query = MB_QUERY_SEND_DATA;
316 HAL_UART_Transmit_DMA(mb_data->uart, mb_data->tx_buffer, mb_data->tx_head);
317 }
318
319 void mbClearTxBuffer(modbus_t * mb_data)
320 {
321 mb_data->tx_head = 0;
322 }
323
324
325
326 // Compute the MODBUS RTU CRC
327 uint16_t mbCrc16 ( uint8_t *buf, uint32_t len)
328 {
329 uint16_t crc = 0xFFFF;
330
331 for (uint32_t pos = 0; pos < len; pos++)
332 {
333 crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
334
335 for (int i = 8; i != 0; i--)
336 { // Loop over each bit
337 if ((crc & 0x0001) != 0)
338 { // If the LSB is set
339 crc >>= 1; // Shift right and XOR 0xA001
340 crc ^= 0xA001;
341 }
342 else // Else LSB is not set
343 {
344 crc >>= 1; // Just shift right
345 }
346 }
347 }
348
349 // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
350 return crc;
351 }
352
353 /* If CRC is correct returns msg_length else returns INVALID_CRC */
354 int mbCheckCrc16( uint8_t *msg, const int msg_length)
355 {
356 int ret;
357 uint16_t crc_calc;
358 uint16_t crc_received;
359
360 crc_calc = mbCrc16(msg, msg_length - 2);
361 crc_received = (msg[msg_length - 1] << 8) | msg[msg_length - 2];
362
363 // Check CRC of msg
364 if (crc_calc == crc_received) {
365 ret = msg_length;
366 } else {
367 ret = INVALID_CRC;
368 }
369 return ret;
370 }
371
372 uint32_t mbAppendCrc16(uint8_t * buffer, uint32_t tx_position)
373 {
374 uint16_t crc = mbCrc16( buffer , tx_position);
375
376 uint8_t l_crc = (uint8_t) (crc & 0x00FF) ;
377 uint8_t h_crc = (uint8_t) (crc >> 8);
378 buffer[tx_position] = l_crc;
379 tx_position++;
380 buffer[tx_position] = h_crc;
381 tx_position++;
382 return tx_position;
383 }
384
385 /************************************************************************************************************
386 Function: mb_get_frame_complete
387 Purpose: Rckabe ob Frame komplett empfangen wurde
388 *************************************************************************************************************/
389 bool mbGetFrameComplete(modbus_t * mb_data)
390 {
391 return mb_data->mb_rx_frame_complete;
392 }
393
394 void mbClearRxFrame(modbus_t * mb_data)
395 {
396 // Wieder bei 0 im buffer anfangen
397 mb_data->rx_head = 0;
398
399 // keine Daten mehr vorhanden
400 mb_data->mb_rx_frame_complete=false;
401 }
402
403
404 // --------------------- SLAVE FUNCTIONS ---------------------------------------
405
406#define SEND_TO_SLAVES_BUFFER_COUNT 1000
407//static TASK_MODBUS_MASTER_Message_t xMessage[255];
408//static TASK_MODBUS_MASTER_Message_t *pxMessage;
409static bword_t values[SEND_TO_SLAVES_BUFFER_COUNT];
410static uint32_t y;
411static uint32_t z;
412
413 uint32_t mbSlaveCheckModbusRtuQuery(modbus_t * mb_data)
414 {
415 uint32_t message_lengh;
416 uint8_t *modbus_rx_message;
417 modbus_rx_message = mb_data->rx_buffer;
418 message_lengh= mb_data->rx_head;
419 uint32_t slave_adress;
420 slave_adress = modbus_rx_message[0];
421
422 if (message_lengh < 5) //Mindestens 5 Zeichen (Slave Adress + Function Code + 2x CRC
423 {
424 mbClearRxFrame(mb_data);
425 return 0;
426 }
427
428 // Prfe CRC
429 if (mbCheckCrc16(modbus_rx_message,message_lengh) == INVALID_CRC)
430 {
431 mbClearRxFrame(mb_data);
432 return 0;
433 }
434
435 if (slave_adress == MODBUS_BROADCAST_ADDRESS)
436 {
437
438 return RESPOND_TO_QUERY;
439 }
440 /* auf richtige Slave Adresse checken ansonsten nicht antworten*/
441 else if (slave_adress == sys_data.s.parameter.slave_address)
442 {
443 return RESPOND_TO_QUERY;
444 }
445
446 mbClearRxFrame(mb_data);
447 return 0;
448 }
449
450 void mbSlaveProcessRtuQuery(modbus_t * mb_data)
451 {
452 uint32_t tx_position=0; //die _Nchste_ Position in der Zeichen eingefgt werden mssen
453 uint8_t *modbus_rx_message;
454 modbus_rx_message = &mb_data->rx_buffer[0];
455
456 //Vorbereiten auf neues senden
457 mbClearTxBuffer(mb_data);
458
459 //mb_data->tx_buffer[0] = sys_data.s.vmGreenview.s.lb_slave_adress;
460 mb_data->tx_buffer[0] = *modbus_rx_message;
461 tx_position++;
462 tx_position = mbSlaveProcessPdu(mb_data->tx_buffer , modbus_rx_message,tx_position, *modbus_rx_message);
463
464 tx_position = mbAppendCrc16(mb_data->tx_buffer ,tx_position);
465 mb_data->tx_head=tx_position;
466 mbSend(mb_data);
467 mbClearRxFrame(mb_data);
468 }
469
470 uint32_t mbSlaveProcessPdu (uint8_t* response_string, uint8_t * msg, uint32_t tx_position, uint8_t deviceID)
471 {
472 uint32_t function_code;
473 uint32_t ret;
474
475 function_code = msg[OFFSET_FUNCTION_CODE];
476
477 switch (function_code)
478 {
479 case FC_READ_HOLDING_REGISTERS:
480 ret= mbSlaveReadHoldingRegisters(response_string, msg,tx_position, deviceID);
481 break;
482
483 case FC_WRITE_SINGLE_REGISTER:
484 ret = mbSlaveWriteSingleRegister(response_string, msg,tx_position, deviceID);
485 break;
486
487 case FC_WRITE_MULTIPLE_REGISTER:
488 ret=mbSlaveWriteMultipleRegisters(response_string, msg,tx_position, deviceID);
489 break;
490
491 default:
492 ret=mbSlaveResponseException(response_string,function_code,ILLEGAL_FUNCTION,tx_position);
493 break;
494 }
495
496 return ret;
497 }
498
499
500 uint32_t mbSlaveReadHoldingRegisters( uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint8_t deviceID)
501 {
502 uint32_t start_adress;
503 uint32_t adress;
504 uint32_t number_of_registers;
505
506 /*stimmt die device ID mit der eigenen berein*/
507 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
508 {
509 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
510 }
511
512 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
513 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
514
515 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC3) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC3) )
516 {
517 return mbSlaveResponseException(response_string,FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_VALUE,tx_position);
518 }
519
520 if (start_adress+number_of_registers-1 > MAX_ADRESS)
521 {
522 return mbSlaveResponseException(response_string, FC_READ_HOLDING_REGISTERS,ILLEGAL_DATA_ADDRESS,tx_position);
523 }
524
525 response_string[tx_position] = FC_READ_HOLDING_REGISTERS; // FUNCTION CODE
526 tx_position++;
527 response_string[tx_position] = number_of_registers * 2; // Bytes
528 tx_position++;
529
530 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
531 {
532 /*Daten aus dem Speicher senden*/
533 response_string[tx_position] = sys_data.mb[adress].b[1];
534 tx_position++;
535 response_string[tx_position] = sys_data.mb[adress].b[0];
536 tx_position++;
537 }
538
539 return tx_position;
540 }
541
542
543 uint32_t mbSlaveWriteMultipleRegisters(uint8_t * response_string, uint8_t *msg, uint32_t tx_position, uint32_t deviceID)
544 {
545
546 uint32_t start_adress;
547 uint32_t number_of_registers;
548 uint32_t adress;
549 uint32_t offset;
550
551 /*stimmt die device ID mit der eigenen berein*/
552 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
553 {
554 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
555 }
556
557 start_adress = (msg[OFFSET_START_ADRESS_HI] << 8) + msg[OFFSET_START_ADRESS_LO];
558 number_of_registers = ( msg[OFFSET_NO_OF_REGISTERS_HI] << 8) + msg[OFFSET_NO_OF_REGISTERS_LO];
559 offset=7;
560
561 if ((number_of_registers < MIN_NUMBER_OF_REGISTERS_FC16) || (number_of_registers > MAX_NUMBER_OF_REGISTERS_FC16) )
562 {
563 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_VALUE,tx_position);
564 }
565
566 if (start_adress+number_of_registers-1 > MAX_ADRESS)
567 {
568 return mbSlaveResponseException(response_string, FC_WRITE_MULTIPLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
569 }
570
571 /*Daten in Gertespeicher schreiben*/
572 for(adress=start_adress;adress < (start_adress + number_of_registers);adress++)
573 {
574 sys_data.mb[adress].b[1] = msg[offset];
575 sys_data.mb[adress].b[0] = msg[offset+1];
576 offset+=2;
577 }
578
579 response_string[tx_position] = FC_WRITE_MULTIPLE_REGISTER; // FUNCTION CODE - 1 byte
580 tx_position++;
581 response_string[tx_position] = start_adress >> 8;
582 tx_position++;
583 response_string[tx_position] = (uint8_t ) ( start_adress & 0x00FF); // start adresse 2 byte
584 tx_position++;
585 response_string[tx_position] = number_of_registers >> 8;
586 tx_position++;
587 response_string[tx_position] = (uint8_t ) ( number_of_registers & 0x00FF); // Anzahl Register 2 byte
588 tx_position++;
589 return tx_position;
590 }
591
592
593 uint32_t mbSlaveWriteSingleRegister(uint8_t * response_string,uint8_t *msg,uint32_t tx_position, uint32_t deviceID)
594 {
595
596 uint32_t adress;
597
598 /*stimmt die device ID mit der eigenen berein*/
599 if((deviceID != sys_data.s.parameter.slave_address) && (deviceID != 0))
600 {
601 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,GATEWAY_PROBLEM_TARGET,tx_position);
602 }
603
604 adress = (msg[2] << 8) + msg[3];
605
606 if (adress > MAX_ADRESS)
607 {
608 return mbSlaveResponseException(response_string,FC_WRITE_SINGLE_REGISTER,ILLEGAL_DATA_ADDRESS,tx_position);
609 }
610
611 /*schreibe Daten in eigenen Speicher*/
612 sys_data.mb[adress].b[1] = msg[4];
613 sys_data.mb[adress].b[0] = msg[5];
614
615 response_string[tx_position]= FC_WRITE_SINGLE_REGISTER; // FUNCTION CODE
616 tx_position++;
617 response_string[tx_position]= adress >> 8;
618 tx_position++;
619 response_string[tx_position]= (uint8_t ) ( adress & 0x00FF);
620
621 tx_position++;
622 response_string[tx_position]= msg[4];
623 tx_position++;
624 response_string[tx_position]= msg[5];
625 tx_position++;
626
627 return tx_position;
628 }
629
630
631 uint32_t mbSlaveResponseException(uint8_t* response_string, uint32_t function_code, uint32_t exception_code,uint32_t tx_position )
632 {
633 function_code += 0x80;
634 response_string[tx_position] = function_code; // FUNCTION CODE
635 tx_position++;
636 response_string[tx_position] = exception_code; //
637 tx_position++;
638 return tx_position;
639 }
640
641
642 //---------------------------- UNKNOWN -----------------------------------------
643 //- -
644 //------------------------------------------------------------------------------
645
646#endif
647
Note: See TracBrowser for help on using the repository browser.