/**************************************************************************** * apps/examples/modbusmaster/mbmaster_main.c * * Copyright (c) 2016 Vytautas Lukenskas * Copyright (c) 2019 Alan Carvalho de Assis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include "modbus/mb.h" #include "modbus/mb_m.h" #include "modbus/mbport.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* modbus master port */ #ifdef CONFIG_EXAMPLES_MODBUSMASTER_PORT # define MBMASTER_PORT CONFIG_EXAMPLES_MODBUSMASTER_PORT #else # define MBMASTER_PORT 1 /* port, 1 -- /dev/ttyS1 */ #endif #ifdef CONFIG_EXAMPLES_MODBUSMASTER_BAUDRATE # define MBMASTER_BAUD CONFIG_EXAMPLES_MODBUSMASTER_BAUDRATE #else # define MBMASTER_BAUD B115200 /* baudrate, 115200kbps */ #endif #ifdef CONFIG_EXAMPLES_MODBUSMASTER_PARITY # define MBMASTER_PARITY CONFIG_EXAMPLES_MODBUSMASTER_PARITY #else # define MBMASTER_PARITY MB_PAR_EVEN /* parity, even */ #endif #ifdef CONFIG_EXAMPLES_MODBUSMASTER_SLAVEADDR # define SLAVE_ID CONFIG_EXAMPLES_MODBUSMASTER_SLAVEADDR #else # define SLAVE_ID 1 /* slave address */ #endif #ifdef CONFIG_EXAMPLES_MODBUSMASTER_SLAVEREG # define SLAVE_STATUS_REG CONFIG_EXAMPLES_MODBUSMASTER_SLAVEREG #else # define SLAVE_STATUS_REG 1 /* slave status register part1 */ #endif #ifdef CONFIG_EXAMPLES_MODBUSMASTER_TESTCOUT # define MBMASTER_REQUESTS_COUNT CONFIG_EXAMPLES_MODBUSMASTER_TESTCOUT #else # define MBMASTER_REQUESTS_COUNT 100 /* number of requests to send */ #endif /**************************************************************************** * Private Types ****************************************************************************/ enum mbmaster_threadcmd_e { STOPPED = 0, RUN, SHUTDOWN }; struct mbmaster_statistics_s { int reqcount; int rspcount; int errcount; }; struct mbmaster_run_s { pthread_t pollthreadid; enum mbmaster_threadcmd_e threadcmd; struct mbmaster_statistics_s statistics; }; /**************************************************************************** * Private Global Variables ****************************************************************************/ static struct mbmaster_run_s g_mbmaster; /**************************************************************************** * Private functions ****************************************************************************/ /**************************************************************************** * Name: mbmaster_initialize * * Description: * Should initialize modbus stack. * ****************************************************************************/ static inline int mbmaster_initialize(void) { eMBErrorCode mberr; /* Initialize the FreeModBus library (master) */ mberr = eMBMasterInit(MB_RTU, MBMASTER_PORT, MBMASTER_BAUD, MBMASTER_PARITY); if (mberr != MB_ENOERR) { fprintf(stderr, "mbmaster_main: " "ERROR: eMBMasterInit failed: %d\n", mberr); return ENODEV; } /* Enable FreeModBus Master */ mberr = eMBMasterEnable(); if (mberr != MB_ENOERR) { fprintf(stderr, "mbmaster_main: " "ERROR: eMBMasterEnable failed: %d\n", mberr); return ENODEV; } return OK; } /**************************************************************************** * Name: mbmaster_deinitialize * * Description: * Should release resources taken by modbus stack. * ****************************************************************************/ static inline void mbmaster_deinitialize(void) { /* Disable modbus stack */ eMBMasterDisable(); /* Release hardware resources */ eMBMasterClose(); } /**************************************************************************** * Name: mbmaster_pollthread * * Description: * This is the ModBus Master polling thread. * ****************************************************************************/ static FAR void *mbmaster_pollthread(FAR void *pvarg) { eMBErrorCode mberr; do { /* Poll */ mberr = eMBMasterPoll(); if (mberr != MB_ENOERR) { break; } } while (g_mbmaster.threadcmd != SHUTDOWN); /* Free/uninitialize data structures */ g_mbmaster.threadcmd = STOPPED; printf("mbmaster_main: " "Exiting poll thread.\n"); return NULL; } /**************************************************************************** * Name: mbmaster_showstatistics * * Description: * Show final connection statistics * ****************************************************************************/ static void mbmaster_showstatistics(void) { printf("Modbus master statistics: \n"); printf("Requests count: %d\n", g_mbmaster.statistics.reqcount); printf("Responses count: %d\n", g_mbmaster.statistics.rspcount); printf("Errors count: %d\n", g_mbmaster.statistics.errcount); } /**************************************************************************** * Name: eMBMasterRegHoldingCB * * Description: * Required FreeModBus callback function * ****************************************************************************/ eMBErrorCode eMBMasterRegHoldingCB(FAR uint8_t *buffer, uint16_t address, uint16_t nregs, eMBRegisterMode mode) { eMBErrorCode mberr = MB_ENOERR; switch (mode) { case MB_REG_READ: g_mbmaster.statistics.rspcount++; break; case MB_REG_WRITE: printf("mbmaster_main: writing holding register, value: %d\n", *(buffer)); break; } return mberr; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: main/mbmaster_main ****************************************************************************/ int main(int argc, FAR char *argv[]) { eMBMasterReqErrCode mberr; int reqcounter = 0; int ret; g_mbmaster.statistics.reqcount = 0; g_mbmaster.statistics.rspcount = 0; g_mbmaster.statistics.errcount = 0; g_mbmaster.threadcmd = STOPPED; reqcounter = 0; /* Initialize modbus stack, etc */ printf("Initializing modbus master...\n"); ret = mbmaster_initialize(); if (ret != OK) { fprintf(stderr, "mbmaster_main: ", "ERROR: mbmaster_initialize failed: %d\n", ret); goto errout; } printf("Creating poll thread.\n"); g_mbmaster.threadcmd = RUN; ret = pthread_create(&g_mbmaster.pollthreadid, NULL, mbmaster_pollthread, NULL); if (ret != OK) { fprintf(stderr, "mbmaster_main: ", "ERROR: mbmaster_pollthread create failed: %d\n", ret); goto errout_with_initialize; } printf("Sending %d requests to slave %d\n", MBMASTER_REQUESTS_COUNT, SLAVE_ID); /* modbus is initialized and polling thread is running */ while (reqcounter < MBMASTER_REQUESTS_COUNT) { g_mbmaster.statistics.reqcount++; mberr = eMBMasterReqReadHoldingRegister(SLAVE_ID, SLAVE_STATUS_REG, 1, -1); if (mberr != MB_MRE_NO_ERR) { fprintf(stderr, "mbmaster_main: " "ERROR: holding reg %d read failed: %d\n", SLAVE_STATUS_REG, mberr); g_mbmaster.statistics.errcount++; } reqcounter++; } /* Stop polling thread */ g_mbmaster.threadcmd = SHUTDOWN; pthread_join(g_mbmaster.pollthreadid, NULL); g_mbmaster.threadcmd = STOPPED; /* Display connection statistics */ mbmaster_showstatistics(); printf("Deinitializing modbus master...\n"); mbmaster_deinitialize(); return OK; errout_with_initialize: /* Release hardware resources */ mbmaster_deinitialize(); errout: exit(EXIT_FAILURE); }