Example code for modbus serial

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
vsupacha
Date:
Fri Mar 16 04:34:08 2018 +0000
Parent:
0:f306cb0263a6
Commit message:
Draft of complete solution

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
modbus.cpp Show annotated file Show diff for this revision Revisions of this file
modbus.h Show annotated file Show diff for this revision Revisions of this file
diff -r f306cb0263a6 -r 0007712e84a8 main.cpp
--- a/main.cpp	Wed Mar 14 06:17:48 2018 +0000
+++ b/main.cpp	Fri Mar 16 04:34:08 2018 +0000
@@ -1,29 +1,84 @@
 #include "mbed.h"
 #include "modbus.h"
+#include "RawSerial.h"
 
 DigitalOut myled(LED1);
 RawSerial pc(USBTX, USBRX);
+InterruptIn button(USER_BUTTON);
+Ticker timebase;
+
+uint32_t Tick = 0;
+uint32_t pressedTick = 0; 
+uint32_t releasedTick = 0; 
 
 void serial_callback()
 {
     uint8_t frame[6];
+    uint16_t offset, count;
+    uint8_t reg_map;
     
     char ch = pc.getc();
     if (modbus_parser(ch, frame)) {
-        
+        offset = (frame[2] << 8) | (frame[3]);
+        count = (frame[4] << 8) | (frame[5]);
+        reg_map = modbus_check(offset, count);
+        modbus_response(reg_map);
+    }
+}
+
+void pressed_callback()
+{
+    uint16_t skipCount;
+    
+    if ((Tick > pressedTick) && (Tick > releasedTick)) {
+        skipCount = Tick - releasedTick;
+        modbus_update(0x0000, skipCount);
+        pressedTick = Tick;
+        // printf("Pressed: %d - %d - %d\r\n", pressedTick, releasedTick, skipCount);
     }
 }
 
+void released_callback()
+{
+    uint16_t widthCount;
+    
+    if ((Tick > pressedTick) && (Tick > releasedTick)) {
+        widthCount = Tick - pressedTick;
+        modbus_update(0x0001, widthCount);
+        releasedTick = Tick;
+        // printf("Released: %d - %d - %d\r\n", pressedTick, releasedTick, widthCount);
+    }
+}
+
+void ticker_callback()
+{
+    Tick++;
+}
+
 int main() {
     // setup code
-    pc.attach(serial_callback);
+    pc.attach(&serial_callback);
+    
     // 1. button code
+    button.rise(&pressed_callback);
+    button.fall(&released_callback);
+    
     // 2. timer code
+    timebase.attach(&ticker_callback, 0.1);
+    printf("Starting\n");
+    printf("Test: %02X\r\n", modbus_check(0x0000, 0x0001));
+    printf("Test: %02X\r\n", modbus_check(0x0001, 0x0001));
+    printf("Test: %02X\r\n", modbus_check(0x0000, 0x0002));
+    printf("Test: %02X\r\n", modbus_check(0x0000, 0x0003));
+    printf("Test: %02X\r\n", modbus_check(0x0001, 0x0002));
+    printf("Test: %02X\r\n", modbus_check(0x0002, 0x0002));    
     while(1) {
-        // loop code
-        myled = 1; // LED is ON
-        wait(0.2); // 200 ms
-        myled = 0; // LED is OFF
-        wait(1.0); // 1 sec
+        // blinking LED
+        myled = !myled; 
+        wait(2.5);
+        printf("Detection: %d - %d\r\n", pressedTick, releasedTick);
+        modbus_response(0x01);
+        modbus_response(0x02);
+        modbus_response(0x03);
     }
 }
diff -r f306cb0263a6 -r 0007712e84a8 modbus.cpp
--- a/modbus.cpp	Wed Mar 14 06:17:48 2018 +0000
+++ b/modbus.cpp	Fri Mar 16 04:34:08 2018 +0000
@@ -24,7 +24,8 @@
         for (i = 0; i < 6; i++) {
             sum += frame[i];
         }
-        if ((sum + lrc) == 0) {
+        sum = sum + lrc;
+        if (sum == 0) {
             status = 1;
         }
     }
@@ -34,15 +35,20 @@
 
 void modbus_init(uint8_t id)
 {
+    int i;
+    
     nodeId = id;
+    for (i = 0; i < ADDR_RANGE; i++) {
+        regValue[i] = 0;
+    }
 }
 
 uint16_t modbus_read(uint16_t offset)
-{
+{  
     if (offset < ADDR_RANGE) {
         return regValue[offset];
     } 
-    return 0xFFFF;
+    return 0;
 }
 
 uint16_t modbus_update(uint8_t offset, uint16_t val)
@@ -54,7 +60,23 @@
         regValue[offset] = val;
         return tmp;
     } 
-    return 0xFFFF;
+    return 0;
+}
+
+uint8_t modbus_check(uint16_t offset, uint16_t count) 
+{
+    uint8_t reg_map = 0x00;
+    int i, j;
+    
+    for (i = 0; i < ADDR_RANGE; i++) {
+        for (j = offset; j < (offset+count); j++) {
+            if (j == (ADDR_BASE + i)) {
+                reg_map |= (1 << i);
+            } 
+        }
+    }
+    
+    return reg_map;
 }
 
 int modbus_parser(char ch, uint8_t *frame)
@@ -72,6 +94,7 @@
             }
             break;
         case RECEPTION:
+            printf("%c", ch);
             if ((ch >= '0') && (ch <= '9')) {
                 buf[idx++] = ch;
             } else if ((ch >= 'a') && (ch <= 'f')) {
@@ -101,3 +124,66 @@
     
     return status;
 }
+
+uint8_t calc_lrc(uint8_t *frame, int count)
+{
+    int8_t lrc = 0;
+    int i;
+    
+    for (i = 0; i < count; i++) {
+        lrc += frame[i];
+    }
+    return -lrc;
+}
+
+void modbus_response(uint8_t reg_map) 
+{
+    char fmt00[] = ":%02X%02X%02X\r\n";
+    char fmt01[] = ":%02X%02X%02X%02X%02X\r\n";
+    char fmt02[] = ":%02X%02X%02X%02X%02X\r\n";
+    char fmt03[] = ":%02X%02X%02X%02X%02X%02X%02X\r\n";
+    char *fmtstr;
+    char str[20];
+    uint8_t frame[ADDR_RANGE*2 + 3];
+    uint16_t tmp;
+    
+    frame[0] = nodeId;
+    frame[1] = FUNC_CODE;
+    switch(reg_map) {
+        case 1:
+            tmp = modbus_read(0);
+            frame[2] = tmp >> 8;
+            frame[3] = tmp & 0xFF;
+            frame[4] = calc_lrc(frame, 4);
+            fmtstr = fmt01;
+            sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4]);
+            printf("Response: %s", str);
+            break;
+        case 2:
+            tmp = modbus_read(1);
+            frame[2] = tmp >> 8;
+            frame[3] = tmp & 0xFF;
+            frame[4] = calc_lrc(frame, 4);
+            fmtstr = fmt02;
+            sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4]);
+            printf("Response: %s", str);        
+            break;
+        case 3:
+            tmp = modbus_read(0);
+            frame[2] = tmp >> 8;
+            frame[3] = tmp & 0xFF;
+            tmp = modbus_read(1);
+            frame[4] = tmp >> 8;
+            frame[5] = tmp & 0xFF;                                
+            frame[6] = calc_lrc(frame, 6);
+            fmtstr = fmt03;
+            sprintf(str, fmtstr, frame[0], frame[1], frame[2], frame[3], frame[4], frame[5], frame[6]);
+            printf("Response: %s", str);              
+            break;
+        default:
+            fmtstr = fmt00;
+            frame[2] = calc_lrc(frame, 2);
+            sprintf(str, fmtstr, frame[0], frame[1], frame[2]);
+            printf("Response: %s", str);      
+    }
+}
diff -r f306cb0263a6 -r 0007712e84a8 modbus.h
--- a/modbus.h	Wed Mar 14 06:17:48 2018 +0000
+++ b/modbus.h	Fri Mar 16 04:34:08 2018 +0000
@@ -10,5 +10,7 @@
 uint16_t modbus_read(uint16_t offset);
 uint16_t modbus_update(uint8_t offset, uint16_t val);
 int modbus_parser(char ch, uint8_t *frame);
+uint8_t modbus_check(uint16_t offset, uint16_t count);
+void modbus_response(uint8_t reg_map);
 
 #endif // MODBUS_H