2019年7月1日 星期一

Modbus sample code

介紹modbus slave 端 coding

Modbus server 簡介

modbus tcp 的流程也差不多,只是換成tcp 需要的參數
tcp寫法有很多種,可搭配Socket 的各種模式去接收request

以下簡介modbus rtu server
//new 一個modbus rtu 物件,設置device (俗稱serial port)、baud rate .. 等等
modbus_t *ctx = modbus_new_rtu("/dev/ttyS0",//device
                         9600,//baud
                         'N',//parity
                         8,//data bits
                         1);//stop bits


//設置slave id
modbus_set_slave(ctx, mb_rtu_slaveId);


//連線com port
modbus_connect(ctx);


//建立map及寫值
modbus_mapping_t *mb_mapping = modbus_mapping_new(0, 0, 0, MB_MAX_INPUT_REGISTER);
mb_mapping->tab_input_registers[1] = oa_num;


//開一個loop在main thread,等著request 進來
//若收到request,就用modbus_reply 丟入map,libmodbus 會自行判斷回應對應的register 值或error code
//若要非同步更新map,就是開另一個thread 或callback function,去更新map 內容即可 (設全域變數)
for (;;)
{
        uint8_t query[MODBUS_MAX_ADU_LENGTH];

        int rc = modbus_receive(ctx, query);
        if (rc > 0)
        {
            modbus_reply(ctx, query, rc, mb_mapping);
        }
        else if (rc == -1)
        {
            LOG_ERROR(my_log_type, "modbus error : %s\n", modbus_strerror(errno));
        }
        usleep(100);
}

modbus_mapping_free(mb_mapping);

modbus_close(ctx);
modbus_free(ctx);

Modbus map

input register 為一種限制client read only 的array,array 每一個單位為2 bytes
所以若寫入的資料長度不等於2 bytes,須注意寫入及讀取的記憶體排列方式,會依照OS 平台或程式語言會不同
在下面code的registers 是個array,編號從0開始
但Modbus 卻是從1開始,所以要減1才會等於array 實際位置

另外一般是master端來遵守slave 端的資料排列,所以不一定要實作swap bytes 或是swap word等功能


以libmodbus 的程式碼對照下圖register 來簡單說明用法
#define MB_MAX_INPUT_REGISTER 10000


modbus_mapping_t *mb_mapping = modbus_mapping_new(0, 0, 0, MB_MAX_INPUT_REGISTER);
//mb_mapping 是一個具有4種資料存取位置的結構,根據modbus_mapping_new 填入的參數會影像這4種資料存取的大小
//以復盛這個例子,只須要最後一個參數設10000 即可


mb_mapping->tab_input_registers[1] = oa_num;
//寫入Address 0002 ,內容為Number of lines


char oaName[] = "hello";
mb_mapping->tab_input_registers[101] = (uint16_t) oaName[0];//'h'
mb_mapping->tab_input_registers[102] = (uint16_t) oaName[1];//'e'
mb_mapping->tab_input_registers[103] = (uint16_t) oaName[2];//'l'
mb_mapping->tab_input_registers[104] = (uint16_t) oaName[3];//'l'
mb_mapping->tab_input_registers[105] = (uint16_t) oaName[4];//'o'
mb_mapping->tab_input_registers[106] = (uint16_t) oaName[5];//'\0'
//寫入Address 0102~0107 ,內容為Name of this line,以ASCII 的方式存入
//Register map 寫,Quantity 32,代表只接受32個字,從0101寫到0132


double oaValue = 1.3145926;
float *reg_oa_value = (float *)&mb_mapping->tab_input_registers[141];
*reg_oa_value = oaValue;
//寫入Address 142,內容為Value of this line
//這邊暫時作法是將array 轉成float pointer,將oa 直接寫入
//問過AE 改成float 不用double


modbus_mapping_free(mb_mapping);
//release map

1 則留言:

  1. Karl 的魔法書: Modbus Sample Code >>>>> Download Now

    >>>>> Download Full

    Karl 的魔法書: Modbus Sample Code >>>>> Download LINK

    >>>>> Download Now

    Karl 的魔法書: Modbus Sample Code >>>>> Download Full

    >>>>> Download LINK

    回覆刪除

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。 支援rdb 及aof 兩種儲存方式 From  https://zh.wikipedia.org/wiki/Redis Redis 目前擁有兩種資料...