-
Notifications
You must be signed in to change notification settings - Fork 4
/
modbus_slave.c
119 lines (96 loc) · 2.39 KB
/
modbus_slave.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* modbus_slave.c
*
* Created on: 04 îêò. 2014 ã.
* Author: salnikov
*/
#include "modbus_slave.h"
#include "crc16.h"
#include "ParametersTable.h"
Uint16 modbus_func(Uint16 *Buffer, Uint16 len, Uint16 ModbusAddress)
{
Uint16 tmp;
// îòâå÷àåì òîëüêî åñëè íàñ ñïðàøèâàþò
if (*Buffer != ModbusAddress)
return 0;
// ïðîâåðÿåì öåëîñíîñòü ïîñûëêè
if (Crc16(Buffer,len) != 0)
return 0;
// îïðåäåëÿåì ôóíêöèþ
switch (Buffer[1])
{
// ÷òåíèå
case 0x03:
len = modbus_0x03_func(Buffer, len);
break;
// çàïèñü
case 0x06:
len = modbus_0x06_func(Buffer, len);
break;
default:
len = modbus_error(Buffer,MODBUS_FUNCTION_ERROR);
}
// äîáàâëÿåì ê ïîñûëêå CRC
tmp = Crc16(Buffer,len);
Buffer[len] = tmp & 0xFF;
Buffer[len+1] = tmp >> 8;
return len+2;
}
Uint16 modbus_0x03_func(Uint16 *Buffer, Uint16 len)
{
Uint16 Addr, size, tmp, s_tmp;
const Parameter_type *parameter;
Addr = (Buffer[2] << 8) | Buffer[3];
size = (Buffer[4] << 8) | Buffer[5];
// ïðîâåðêà äîñòóïíîñòè àäðåñà
if (Addr > ParametersCount)
return modbus_error(Buffer, MODBUS_ADDRESS_ERROR);
parameter = &ParametersTable[Addr];
// ïðîâåðêà ÷èòàåìîñòè ðåãèñòðà
if (parameter->Flags.bit.r != 1)
return modbus_error(Buffer, MODBUS_DATA_VALUE_ERROR);
// êëàäåì â áóôåð Uart êîëè÷åñòâî ïåðåìåííûõ
Buffer[2] = size;
s_tmp = size;
Buffer += 3;
for (; size>0; size--, Buffer+=2, Addr++)
{
tmp = *ParametersTable[Addr].Addr;
*Buffer = tmp >> 8;
Buffer[1] = tmp & 0xFF;
}
// âîçâðàùàåì äëèíó ïîñûëêè
// àäðåñ + ôóíêöèÿ + êîëè÷åñòâî äàííûõ + äàííûå
return (3 + s_tmp*2);
}
Uint16 modbus_0x06_func(Uint16 *Buffer, Uint16 len)
{
Uint16 Addr, Value;
const Parameter_type *parameter;
Addr = (Buffer[2] << 8) | Buffer[3];
Value = (Buffer[4] << 8) | Buffer[5];
// ïðîâåðêà äîñòóïíîñòè àäðåñà
if (Addr > ParametersCount)
return modbus_error(Buffer, MODBUS_ADDRESS_ERROR);
parameter = &ParametersTable[Addr];
// ïðîâåðêà äîñòóïíîñòè ðåãèñòðà äëÿ çàïèñè
if (parameter->Flags.bit.w == 1)
{
// ïðîâåðÿåì ïðåäåëû
if (Value >= parameter->LowerLimit && Value <= parameter->UpperLimit)
{
// çàïèñûâàåì
*(parameter->Addr) = Value;
}
else return modbus_error(Buffer, MODBUS_DATA_VALUE_ERROR);
}
else return modbus_error(Buffer, MODBUS_DATA_VALUE_ERROR);
// îòâåò - êîïèÿ çàïðîñà
return 6;
}
Uint16 modbus_error(Uint16 *Buffer, Uint16 err)
{
Buffer[1] |= 0x80;
Buffer[2] = err;
return 3;
}