Concept code which launches two threads, one of which implements a Modbus Tunnel protocol to talk with an ISEM, the other which launches a Modbus RTU protocol to talk to a CPUM (most of the Modbus code has been removed prior to publishing.) A canned AC and DC spectra is provided to display wave forms on start-up however the project normally polls for spectra from the ISEM and then plots is (that functionality has been removed prior to publishing.)
Dependencies: LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI
Plot of the initial start-up canned AC and DC spectra.
Diff: NextGen-Exerciser-Modbus.cpp
- Revision:
- 0:387684ec9d92
diff -r 000000000000 -r 387684ec9d92 NextGen-Exerciser-Modbus.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NextGen-Exerciser-Modbus.cpp Thu May 30 05:16:27 2019 +0000 @@ -0,0 +1,189 @@ + +// ---------------------------------------------------------------------- +// NextGen-Exerciser-Modbus.cpp +// +// Fredric L. Rice, May 2019 +// +// o A digital output for an LED is instantiated +// o A Serial object is instantiated on Serial-1 +// o A thread's mailbox object is instantiated +// o A Thread object is instantiated +// o The serial interface is configured +// o The module's thread is start()ed +// +// The LED is toggled according to timing established by a periodic +// wait() and according to messages pending in the thread's mailbox +// +// The mailbox is checked for any messages that need to go out the +// serial interface, and if there are any, the message is extracted +// from the mailbox and gets sent out the serial interface. If there +// are no messages waiting to go out, a Modbus polling message is +// sent out the serial interface instead. +// +// If there is serial data waiting to be read, the data is collected +// in to a Modbus frame and it gets handled by examining the content +// of the inbound frame. +// +// ---------------------------------------------------------------------- + +#include "mbed.h" // The mbed operating system +#include "NextGen-Exerciser-Modbus.h" // Always include ourself +#include "NextGen-Exerciser-Defines.h" // For defined constants and MACROs + +// ---------------------------------------------------------------------- +// Allocate local data storage +// +// ---------------------------------------------------------------------- + + static DigitalOut st_digitalOutModbusLED(LED1); + static Serial st_modbusSerial(PA_9, PA_10); // TX, RX Serial 1 (This one is working) + static Mail<st_pendingMessage, 16> st_modbusMailbox; + static Thread st_threadModbus; + static bool b_modbusInitialized = false; + static char c_flipFlop = 0; + + static unsigned char uch_modbusPollFrame[] = + { + 0xF7, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xDE + } ; + +// ---------------------------------------------------------------------- +// ModbusCheckInbound() +// +// This function will: +// o Check to see if the serial interface is readable +// o If there are bytes waiting, the bytes are read and get +// assembled in to a full Modbus frame. +// o The inbound message is handled by passing it to a function +// which examines the content of the inbound message +// +// ---------------------------------------------------------------------- +static void ModbusCheckInbound(void) +{ + // See if there is inbound serial data + if (st_modbusSerial.readable()) + { + + } +} + +// ---------------------------------------------------------------------- +// ModbusCheckOutbound() +// +// This function will: +// o Get a message from the thread's mailbox, waiting for up to +// 2 milliseconds for a message +// o If a message is pending, the message is extracted and then +// gets formatted in to an output Modbus message frame +// o The newly-formatted Modbus frame gets transmitted out the +// serial interface +// o The mailbox message gets released back in to the memory pool +// o If there was no output message waiting in the mailbox, a +// Modbus polling message is sent out the serial interface +// +// ---------------------------------------------------------------------- +static void ModbusCheckOutbound(void) +{ + // Is there an outbound message waiting? Wait up to 2 milliseconds for one + osEvent st_eventResult = st_modbusMailbox.get(2); + + if (st_eventResult.status == osEventMail) + { + // Get a pointer to the message + st_pendingMessage * pst_outFrame = (st_pendingMessage *)st_eventResult.value.p; + + // Format and send the MODBUS frame + + // Finished with the message so release it even if it was not sent + st_modbusMailbox.free(pst_outFrame); + } + else + { + // Send a poll frame + st_modbusSerial.write((uint8_t *)uch_modbusPollFrame, sizeof(uch_modbusPollFrame), NULL); + } +} + +// ---------------------------------------------------------------------- +// ModbusThread() +// +// This function will: +// o Get invoked as a thread under the mbed operating system +// o Turn ON the lED associated with this module and protocol +// o Enter in to a forever loop which wakes up ten times a second +// o Drives the module's LED so that it flashes frim time to time +// to indicate that the thread is running +// o Check to ensure that the module has been initialized +// o If the module is initialized (and it should be) checks to +// see if there are inbound serial Modbus messages +// o Checks to see if there are any outbound serial Modbus messages +// +// ---------------------------------------------------------------------- +static void ModbusThread(void) +{ + char ch_halfSecond = 5; + + // Set the MODBUS LED to ON to indicate that the thread has started + st_digitalOutModbusLED = 1; + + // Enter in to a forever loop + while (true) + { + // Sleep for one tenth of a second + wait(0.1); + + // Count down the half second timer and see if it expired + if (0 == --ch_halfSecond) + { + // It has expired so restart the half second time + ch_halfSecond = 5; + + // See if we turn on or turn off the LED + if (0 == c_flipFlop) + { + c_flipFlop = 1; + } + else + { + c_flipFlop = 0; + } + + st_digitalOutModbusLED = c_flipFlop; + } + + // We check to see if there is inbound or outbound serial traffic 10 times a second + if (TRUE == b_modbusInitialized) + { + // Check for inbound MODBUS frames + ModbusCheckInbound(); + + // See if we need to send outbound MODBUS frames + ModbusCheckOutbound(); + } + } +} + +// ---------------------------------------------------------------------- +// ModbusInit() +// +// This function will: +// o Initialize the module protocol's serial interface +// o Flag the fact that things are initialized +// o Launch the module's thread +// +// ---------------------------------------------------------------------- +void ModbusInit(void) +{ + // We configure the CPUM MODBUS serial interface + st_modbusSerial.baud(115200); + st_modbusSerial.format(8, SerialBase::None, 1); + + // Flag the fact that the module has been initialized + b_modbusInitialized = true; + + // Launch the CPUM Modbus thread + st_threadModbus.start(ModbusThread); +} + +// End of file +