Example code for modbus serial

Dependencies:   mbed

Committer:
vsupacha
Date:
Fri Mar 16 04:34:08 2018 +0000
Revision:
1:0007712e84a8
Parent:
0:f306cb0263a6
Draft of complete solution

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vsupacha 0:f306cb0263a6 1 #include "mbed.h"
vsupacha 0:f306cb0263a6 2 #include "modbus.h"
vsupacha 0:f306cb0263a6 3
vsupacha 0:f306cb0263a6 4 uint8_t nodeId = 0;
vsupacha 0:f306cb0263a6 5 uint16_t regValue[ADDR_RANGE];
vsupacha 0:f306cb0263a6 6
vsupacha 0:f306cb0263a6 7 enum state {IDLE, RECEPTION, END} protState = IDLE;
vsupacha 0:f306cb0263a6 8
vsupacha 0:f306cb0263a6 9 int process_buffer(char *buf, uint8_t *frame)
vsupacha 0:f306cb0263a6 10 {
vsupacha 0:f306cb0263a6 11 int status = 0;
vsupacha 0:f306cb0263a6 12 uint8_t sum = 0;
vsupacha 0:f306cb0263a6 13 uint8_t lrc, i;
vsupacha 0:f306cb0263a6 14 char tmpbuf[] = {0, 0, 0};
vsupacha 0:f306cb0263a6 15
vsupacha 0:f306cb0263a6 16 if (strlen(buf) == 14) {
vsupacha 0:f306cb0263a6 17 for (i = 0; i < 6; i++) {
vsupacha 0:f306cb0263a6 18 tmpbuf[0] = buf[i*2];
vsupacha 0:f306cb0263a6 19 tmpbuf[1] = buf[i*2 + 1];
vsupacha 0:f306cb0263a6 20 frame[i] = strtoul(tmpbuf, NULL, 16);
vsupacha 0:f306cb0263a6 21 }
vsupacha 0:f306cb0263a6 22 tmpbuf[0] = buf[12]; tmpbuf[1] = buf[13];
vsupacha 0:f306cb0263a6 23 lrc = strtoul(tmpbuf, NULL, 16);
vsupacha 0:f306cb0263a6 24 for (i = 0; i < 6; i++) {
vsupacha 0:f306cb0263a6 25 sum += frame[i];
vsupacha 0:f306cb0263a6 26 }
vsupacha 1:0007712e84a8 27 sum = sum + lrc;
vsupacha 1:0007712e84a8 28 if (sum == 0) {
vsupacha 0:f306cb0263a6 29 status = 1;
vsupacha 0:f306cb0263a6 30 }
vsupacha 0:f306cb0263a6 31 }
vsupacha 0:f306cb0263a6 32
vsupacha 0:f306cb0263a6 33 return status;
vsupacha 0:f306cb0263a6 34 }
vsupacha 0:f306cb0263a6 35
vsupacha 0:f306cb0263a6 36 void modbus_init(uint8_t id)
vsupacha 0:f306cb0263a6 37 {
vsupacha 1:0007712e84a8 38 int i;
vsupacha 1:0007712e84a8 39
vsupacha 0:f306cb0263a6 40 nodeId = id;
vsupacha 1:0007712e84a8 41 for (i = 0; i < ADDR_RANGE; i++) {
vsupacha 1:0007712e84a8 42 regValue[i] = 0;
vsupacha 1:0007712e84a8 43 }
vsupacha 0:f306cb0263a6 44 }
vsupacha 0:f306cb0263a6 45
vsupacha 0:f306cb0263a6 46 uint16_t modbus_read(uint16_t offset)
vsupacha 1:0007712e84a8 47 {
vsupacha 0:f306cb0263a6 48 if (offset < ADDR_RANGE) {
vsupacha 0:f306cb0263a6 49 return regValue[offset];
vsupacha 0:f306cb0263a6 50 }
vsupacha 1:0007712e84a8 51 return 0;
vsupacha 0:f306cb0263a6 52 }
vsupacha 0:f306cb0263a6 53
vsupacha 0:f306cb0263a6 54 uint16_t modbus_update(uint8_t offset, uint16_t val)
vsupacha 0:f306cb0263a6 55 {
vsupacha 0:f306cb0263a6 56 uint16_t tmp;
vsupacha 0:f306cb0263a6 57
vsupacha 0:f306cb0263a6 58 if (offset < ADDR_RANGE) {
vsupacha 0:f306cb0263a6 59 tmp = regValue[offset];
vsupacha 0:f306cb0263a6 60 regValue[offset] = val;
vsupacha 0:f306cb0263a6 61 return tmp;
vsupacha 0:f306cb0263a6 62 }
vsupacha 1:0007712e84a8 63 return 0;
vsupacha 1:0007712e84a8 64 }
vsupacha 1:0007712e84a8 65
vsupacha 1:0007712e84a8 66 uint8_t modbus_check(uint16_t offset, uint16_t count)
vsupacha 1:0007712e84a8 67 {
vsupacha 1:0007712e84a8 68 uint8_t reg_map = 0x00;
vsupacha 1:0007712e84a8 69 int i, j;
vsupacha 1:0007712e84a8 70
vsupacha 1:0007712e84a8 71 for (i = 0; i < ADDR_RANGE; i++) {
vsupacha 1:0007712e84a8 72 for (j = offset; j < (offset+count); j++) {
vsupacha 1:0007712e84a8 73 if (j == (ADDR_BASE + i)) {
vsupacha 1:0007712e84a8 74 reg_map |= (1 << i);
vsupacha 1:0007712e84a8 75 }
vsupacha 1:0007712e84a8 76 }
vsupacha 1:0007712e84a8 77 }
vsupacha 1:0007712e84a8 78
vsupacha 1:0007712e84a8 79 return reg_map;
vsupacha 0:f306cb0263a6 80 }
vsupacha 0:f306cb0263a6 81
vsupacha 0:f306cb0263a6 82 int modbus_parser(char ch, uint8_t *frame)
vsupacha 0:f306cb0263a6 83 {
vsupacha 0:f306cb0263a6 84 static char buf[514];
vsupacha 0:f306cb0263a6 85 static int idx = 0;
vsupacha 0:f306cb0263a6 86 static int status = 0;
vsupacha 0:f306cb0263a6 87
vsupacha 0:f306cb0263a6 88 switch(protState) {
vsupacha 0:f306cb0263a6 89 case IDLE:
vsupacha 0:f306cb0263a6 90 if (ch == ':') {
vsupacha 0:f306cb0263a6 91 protState = RECEPTION;
vsupacha 0:f306cb0263a6 92 idx = 0;
vsupacha 0:f306cb0263a6 93 status = 0;
vsupacha 0:f306cb0263a6 94 }
vsupacha 0:f306cb0263a6 95 break;
vsupacha 0:f306cb0263a6 96 case RECEPTION:
vsupacha 1:0007712e84a8 97 printf("%c", ch);
vsupacha 0:f306cb0263a6 98 if ((ch >= '0') && (ch <= '9')) {
vsupacha 0:f306cb0263a6 99 buf[idx++] = ch;
vsupacha 0:f306cb0263a6 100 } else if ((ch >= 'a') && (ch <= 'f')) {
vsupacha 0:f306cb0263a6 101 buf[idx++] = ch;
vsupacha 0:f306cb0263a6 102 } else if ((ch >= 'A') && (ch <= 'F')) {
vsupacha 0:f306cb0263a6 103 buf[idx++] = ch;
vsupacha 0:f306cb0263a6 104 } else if (ch == '\r') {
vsupacha 0:f306cb0263a6 105 buf[idx] = 0;
vsupacha 0:f306cb0263a6 106 protState = END;
vsupacha 0:f306cb0263a6 107 } else {
vsupacha 0:f306cb0263a6 108 protState = IDLE;
vsupacha 0:f306cb0263a6 109 }
vsupacha 0:f306cb0263a6 110 break;
vsupacha 0:f306cb0263a6 111 case END:
vsupacha 0:f306cb0263a6 112 if (ch == '\n') {
vsupacha 0:f306cb0263a6 113 if (process_buffer(buf, frame)) {
vsupacha 0:f306cb0263a6 114 if ((frame[0] == nodeId) && (frame[1] == FUNC_CODE)) {
vsupacha 0:f306cb0263a6 115 status = 1;
vsupacha 0:f306cb0263a6 116 }
vsupacha 0:f306cb0263a6 117 }
vsupacha 0:f306cb0263a6 118 }
vsupacha 0:f306cb0263a6 119 protState = IDLE;
vsupacha 0:f306cb0263a6 120 break;
vsupacha 0:f306cb0263a6 121 default:
vsupacha 0:f306cb0263a6 122 protState = IDLE;
vsupacha 0:f306cb0263a6 123 }
vsupacha 0:f306cb0263a6 124
vsupacha 0:f306cb0263a6 125 return status;
vsupacha 0:f306cb0263a6 126 }
vsupacha 1:0007712e84a8 127
vsupacha 1:0007712e84a8 128 uint8_t calc_lrc(uint8_t *frame, int count)
vsupacha 1:0007712e84a8 129 {
vsupacha 1:0007712e84a8 130 int8_t lrc = 0;
vsupacha 1:0007712e84a8 131 int i;
vsupacha 1:0007712e84a8 132
vsupacha 1:0007712e84a8 133 for (i = 0; i < count; i++) {
vsupacha 1:0007712e84a8 134 lrc += frame[i];
vsupacha 1:0007712e84a8 135 }
vsupacha 1:0007712e84a8 136 return -lrc;
vsupacha 1:0007712e84a8 137 }
vsupacha 1:0007712e84a8 138
vsupacha 1:0007712e84a8 139 void modbus_response(uint8_t reg_map)
vsupacha 1:0007712e84a8 140 {
vsupacha 1:0007712e84a8 141 char fmt00[] = ":%02X%02X%02X\r\n";
vsupacha 1:0007712e84a8 142 char fmt01[] = ":%02X%02X%02X%02X%02X\r\n";
vsupacha 1:0007712e84a8 143 char fmt02[] = ":%02X%02X%02X%02X%02X\r\n";
vsupacha 1:0007712e84a8 144 char fmt03[] = ":%02X%02X%02X%02X%02X%02X%02X\r\n";
vsupacha 1:0007712e84a8 145 char *fmtstr;
vsupacha 1:0007712e84a8 146 char str[20];
vsupacha 1:0007712e84a8 147 uint8_t frame[ADDR_RANGE*2 + 3];
vsupacha 1:0007712e84a8 148 uint16_t tmp;
vsupacha 1:0007712e84a8 149
vsupacha 1:0007712e84a8 150 frame[0] = nodeId;
vsupacha 1:0007712e84a8 151 frame[1] = FUNC_CODE;
vsupacha 1:0007712e84a8 152 switch(reg_map) {
vsupacha 1:0007712e84a8 153 case 1:
vsupacha 1:0007712e84a8 154 tmp = modbus_read(0);
vsupacha 1:0007712e84a8 155 frame[2] = tmp >> 8;
vsupacha 1:0007712e84a8 156 frame[3] = tmp & 0xFF;
vsupacha 1:0007712e84a8 157 frame[4] = calc_lrc(frame, 4);
vsupacha 1:0007712e84a8 158 fmtstr = fmt01;
vsupacha 1:0007712e84a8 159 sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4]);
vsupacha 1:0007712e84a8 160 printf("Response: %s", str);
vsupacha 1:0007712e84a8 161 break;
vsupacha 1:0007712e84a8 162 case 2:
vsupacha 1:0007712e84a8 163 tmp = modbus_read(1);
vsupacha 1:0007712e84a8 164 frame[2] = tmp >> 8;
vsupacha 1:0007712e84a8 165 frame[3] = tmp & 0xFF;
vsupacha 1:0007712e84a8 166 frame[4] = calc_lrc(frame, 4);
vsupacha 1:0007712e84a8 167 fmtstr = fmt02;
vsupacha 1:0007712e84a8 168 sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4]);
vsupacha 1:0007712e84a8 169 printf("Response: %s", str);
vsupacha 1:0007712e84a8 170 break;
vsupacha 1:0007712e84a8 171 case 3:
vsupacha 1:0007712e84a8 172 tmp = modbus_read(0);
vsupacha 1:0007712e84a8 173 frame[2] = tmp >> 8;
vsupacha 1:0007712e84a8 174 frame[3] = tmp & 0xFF;
vsupacha 1:0007712e84a8 175 tmp = modbus_read(1);
vsupacha 1:0007712e84a8 176 frame[4] = tmp >> 8;
vsupacha 1:0007712e84a8 177 frame[5] = tmp & 0xFF;
vsupacha 1:0007712e84a8 178 frame[6] = calc_lrc(frame, 6);
vsupacha 1:0007712e84a8 179 fmtstr = fmt03;
vsupacha 1:0007712e84a8 180 sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4], frame[5], frame[6]);
vsupacha 1:0007712e84a8 181 printf("Response: %s", str);
vsupacha 1:0007712e84a8 182 break;
vsupacha 1:0007712e84a8 183 default:
vsupacha 1:0007712e84a8 184 fmtstr = fmt00;
vsupacha 1:0007712e84a8 185 frame[2] = calc_lrc(frame, 2);
vsupacha 1:0007712e84a8 186 sprintf(str, fmtstr, frame[0], frame[1], frame[2]);
vsupacha 1:0007712e84a8 187 printf("Response: %s", str);
vsupacha 1:0007712e84a8 188 }
vsupacha 1:0007712e84a8 189 }