Files
templates/c/set-protocol/tests/test_modbus_server.c

91 lines
2.9 KiB
C

#include <stdio.h>
#include <string.h>
#include "pcan_id.h"
#include "pcan_modbus_server.h"
static uint16_t holding[32];
static uint16_t input[32];
static uint16_t coils;
static bool read_word(void *user, pcan_modbus_bank_t bank,
uint16_t address, uint16_t *value)
{
(void)user;
if (address >= 32U) return false;
if (bank == PCAN_MODBUS_HOLDING) *value = holding[address];
else if (bank == PCAN_MODBUS_INPUT) *value = input[address];
else if (bank == PCAN_MODBUS_COIL) *value = (uint16_t)((coils >> address) & 1U);
else return false;
return true;
}
static bool write_word(void *user, pcan_modbus_bank_t bank,
uint16_t address, uint16_t value)
{
(void)user;
if (address >= 32U) return false;
if (bank == PCAN_MODBUS_HOLDING) holding[address] = value;
else if (bank == PCAN_MODBUS_COIL && address < 16U) {
if (value) coils |= (uint16_t)(1U << address);
else coils &= (uint16_t)~(1U << address);
} else return false;
return true;
}
static pcan_frame_t request(uint8_t type, uint16_t address, uint8_t count)
{
pcan_id_t id = {0};
pcan_frame_t frame = {0};
id.priority = PCAN_PRIORITY_STANDARD;
id.route = PCAN_ROUTE_FROM_PM;
id.device_type = 7U;
id.device_id = 3U;
id.msg_type = type;
id.msg_body = pcan_body_modbus(address, count);
frame.id = pcan_id_pack(&id);
frame.flags = PCAN_FLAG_IDE;
return frame;
}
#define CHECK(x) do { if (!(x)) { \
fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #x); return 1; \
} } while (0)
int main(void)
{
pcan_modbus_server_t server;
pcan_frame_t req;
pcan_frame_t rsp;
pcan_id_t id;
memset(holding, 0, sizeof(holding));
memset(input, 0, sizeof(input));
input[10] = 0x1234U;
input[11] = 0xABCDU;
CHECK(pcan_modbus_server_init(&server, 7U, 3U, read_word, write_word, NULL));
req = request(PCAN_MODBUS_INPUT, 10U, 2U);
CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE);
CHECK(rsp.dlc == 4U && rsp.data[0] == 0x34U && rsp.data[1] == 0x12U);
CHECK(rsp.data[2] == 0xCDU && rsp.data[3] == 0xABU);
pcan_id_unpack(rsp.id, &id);
CHECK(id.route == PCAN_ROUTE_FROM_DEVICE);
req = request(PCAN_MODBUS_HOLDING, 3U, 2U);
req.dlc = 4U;
req.data[0] = 0x22U; req.data[1] = 0x11U;
req.data[2] = 0x44U; req.data[3] = 0x33U;
CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE);
CHECK(holding[3] == 0x1122U && holding[4] == 0x3344U);
req = request(PCAN_MODBUS_COIL, 2U, 3U);
req.dlc = 2U; req.data[0] = 0x05U; req.data[1] = 0U;
CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_RESPONSE);
CHECK(coils == 0x0014U);
req = request(PCAN_MODBUS_INPUT, 0U, 5U);
CHECK(pcan_modbus_server_handle(&server, &req, &rsp) == PCAN_MODBUS_HANDLED_NO_RESPONSE);
CHECK(server.requests == 4U && server.responses == 3U && server.rejected == 1U);
return 0;
}