下午好,我正在使用草图进行使用 RS-232 连接的测试。我需要了解如何以及在 com 终端中键入什么命令,以便在文本变量列表附近的此草图的应用程序窗口中获取和查看数据,我附上了屏幕截图。我对这项业务完全陌生,请告诉我解决方案。
这是调试所必需的,有时是配置所必需的。我附上了草图和代码,你可以检查它。如果应用程序安装在计算机上 com0com.exe 并且通过终端打开 com 端口,则草图可以正常工作。代码的含义是向 COM 端口发送一个字节序列,并在屏幕上显示应用程序中的变量的数据(数字)。
Com_Interface:
import processing.serial.*;
import controlP5.*;
ControlP5 cp5;
DropdownList serialPortsList;
Textlabel tempIn;
Textlabel tempOut;
Textlabel timeIn;
Textlabel timeInC;
Textlabel Vin;
Textlabel I;
Textlabel PitETH;
Textlabel PitUSB;
Textlabel PitGSM;
Textlabel PitPI;
Textlabel PitETH2;
Textlabel PitUSB2;
Textlabel PitGSM2;
Textlabel PitPI2;
Textlabel Vent;
Textlabel ResetAll;
Textlabel Accele;
Textarea accel;
Button lalal;
Button PitPIb;
Button PitETHb;
Button PitUSBb;
Button PitGSMb;
Button Ventb;
Button resetb;
Group lal;
boolean strat=false;
boolean Vents=false;
boolean resets=false;
boolean PitETHs=false;
boolean PitUSBs=false;
boolean PitGSMs=false;
boolean PitPIs=false;
Serial serialPort;
final int BAUD_RATE = 19200;
char parity = 'N';
int dataBits = 8;
float stopBits = 1.0;
ModbusPort port_one; // create a Modbus port instance
int timeout = 500;
int polling = 100;
int no_of_retries = 10;
int total_no_of_packets = 3;
Packet[] packets = new Packet[total_no_of_packets]; // create an array of packets to transmit
int[] readRegs = new int[10]; // to store the requested data
int[] writeRegs = new int[10]; // data to be written using
int previousMillis = 0;
int count = 0;
void setup() {
size(800, 520, JAVA2D);
smooth();
frameRate(30);
PFont fontn = createFont("Verdana", 12);
cp5 = new ControlP5(this);
PFont p= createFont("Verdana", 15);
ControlFont font=new
ControlFont(p);
cp5.setFont(font);
String[] portNames = Serial.list();
lalal = cp5.addButton("lala")
.setCaptionLabel("ПУСК")
//.setValue(0)
.setPosition(180, 10)
.setSize(150, 30)
.lock()
;
PitPIb = cp5.addButton("PitPIb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 415)
.setSize(150, 30)
.lock()
;
PitETHb = cp5.addButton("PitETHb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 295)
.setSize(150, 30)
.lock()
;
PitUSBb = cp5.addButton("PitUSBb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 335)
.setSize(150, 30)
.lock()
;
PitGSMb = cp5.addButton("PitGSMb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 375)
.setSize(150, 30)
.lock()
;
Ventb = cp5.addButton("Ventb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 215)
.setSize(150, 30)
.lock()
;
resetb = cp5.addButton("resetb")
.setCaptionLabel("ВКЛ")
.setPosition(620, 255)
.setSize(150, 30)
.lock()
;
tempIn = cp5.addTextlabel("TempIn")
.setText("Температура внутр.")
.setPosition(20, 100)
;
tempOut = cp5.addTextlabel("TempOut")
.setText("Температура внеш.")
.setPosition(20, 140)
;
timeIn = cp5.addTextlabel("TimeIn")
.setText("Дата/время")
.setPosition(20, 180)
;
timeInC = cp5.addTextlabel("TimeInC")
.setText("Дата/время ПК")
.setPosition(20, 180)
;
Vin = cp5.addTextlabel("VIn")
.setText("Входное напряжение")
.setPosition(20, 220)
;
I = cp5.addTextlabel("I")
.setText("Ток потребления")
.setPosition(20, 260)
;
PitETH = cp5.addTextlabel("PitETH")
.setText("Питание ETH")
.setPosition(20, 295)
;
PitUSB = cp5.addTextlabel("PitUSB")
.setText("Питание USB")
.setPosition(20, 340)
;
PitGSM = cp5.addTextlabel("PitGSM")
.setText("Питание GSM")
.setPosition(20, 380)
;
PitPI = cp5.addTextlabel("PitPI")
.setText("Питание PI")
.setPosition(20, 420)
;
Accele = cp5.addTextlabel("Accele")
.setText("Версия ПО")
.setPosition(20, 460)
;
PitETH2 = cp5.addTextlabel("PitETH2")
.setText("Питание ETH")
.setPosition(500, 300)
;
PitUSB2 = cp5.addTextlabel("PitUSB2")
.setText("Питание USB")
.setPosition(500, 340)
;
PitGSM2 = cp5.addTextlabel("PitGSM2")
.setText("Питание GSM")
.setPosition(500, 380)
;
PitPI2 = cp5.addTextlabel("PitPI2")
.setText("Питание PI")
.setPosition(500, 420)
;
Vent = cp5.addTextlabel("Vent")
.setText("Вентилятор")
.setPosition(500, 220)
;
ResetAll = cp5.addTextlabel("ResetAll")
.setText("Сброс")
.setPosition(500, 260)
;
serialPortsList = cp5.addDropdownList("serialports")
.setPosition(10, 10)
.setSize(150, 200)
.setItemHeight(30)
.setBarHeight(30)
;
for (int i = 0; i < portNames.length; i++) serialPortsList.addItem(portNames[i], i);
textFont(fontn);
}
void draw() {
background(128);
if (strat) {
port_one.update();
tempIn.setText("Температура внутр.: "+ readRegs[7] +"°C");
tempOut.setText("Температура внеш.: "+ readRegs[8] +"°C");
timeIn.setText("Дата/время: "+(2000+readRegs[1])+"/"+readRegs[2]+"/"+readRegs[3]+" "+readRegs[4]+"/"+readRegs[5]+"/"+readRegs[6]);
Vin.setText("Входное напряжение: "+readRegs[9]);
Accele.setText("Версия ПО: "+readRegs[0]);
}
}
void controlEvent(ControlEvent theEvent) {
// DropdownList is of type ControlGroup.
// A controlEvent will be triggered from inside the ControlGroup class.
// therefore you need to check the originator of the Event with
// if (theEvent.isGroup())
// to avoid an error message thrown by controlP5.
if (theEvent.isGroup()) {
// check if the Event was triggered from a ControlGroup
println("event from group : "+theEvent.getGroup().getValue()+" from "+theEvent.getGroup());
//check if there's a serial port open already, if so, close it
if (serialPort != null) {
serialPort.stop();
serialPort = null;
}
//open the selected core
//String portName = serialPortsList.getItem((int)theEvent.getValue()).getName();
String portName = theEvent.getController().getName();
try {
/*serialPort = new Serial(this,Serial.list()[(int)theEvent.getController().getValue()],BAUD_RATE, parity, dataBits, stopBits);
port_one = new ModbusPort(serialPort, timeout, polling, no_of_retries, packets, total_no_of_packets);
// The packet format for function 1, 2, 3, 4, 15 & 16 is:
// Packet(id, function, address, data, data array)
packets[0] = new Packet(11, 16, 1, 10, writeRegs);
packets[1] = new Packet(11, 3, 0, 10, readRegs);
println("COM connected: "+ packets[0].connection );*/
}
catch(Exception e) {
System.err.println("Error opening serial port " + portName);
e.printStackTrace();
}
} else if (theEvent.isController()) {
println("event from controller : "+ (int)theEvent.getController().getValue()+" from "+theEvent.getController());
}
}
public void lala(int theValue) {
println("a button event from colorB: "+theValue);
strat =!strat;
if (!strat) {
lalal.setLabel("Пуск");
} else {
lalal.setLabel("СТОП");
}
//Button.lala.setLabel("СТОП");
}
/*public void serialports(int theValue) {
serialPort = new Serial(this,Serial.list()[theValue],BAUD_RATE, parity, dataBits, stopBits);
port_one = new ModbusPort(serialPort, timeout, polling, no_of_retries, packets, total_no_of_packets);
// The packet format for function 1, 2, 3, 4, 15 & 16 is:
// Packet(id, function, address, data, data array)
packets[0] = new Packet(11, 16, 1, 10, writeRegs);
packets[1] = new Packet(11, 3, 0, 10, readRegs);
println("COM connected: "+ Serial.list()[theValue] );*/
public void serialports(int theValue) {
try {
serialPort = new Serial(this, Serial.list()[theValue], BAUD_RATE, parity, dataBits, stopBits);
port_one = new ModbusPort(serialPort, timeout, polling, no_of_retries, packets, total_no_of_packets);
// The packet format for function 1, 2, 3, 4, 15 & 16 is:
// Packet(id, function, address, data, data array)
packets[0] = new Packet(11, 3, 0, 10, readRegs);
packets[1] = new Packet(11, 16, 1, 1, writeRegs);
packets[2] = new Packet(11, 5, 1, 1, writeRegs);
println("COM connected: "+ Serial.list()[theValue] );
PitPIb.unlock();
PitETHb.unlock();
PitUSBb.unlock();
lalal.unlock();
resetb.unlock();
Ventb.unlock();
resetb.unlock();
PitGSMb.unlock();
}
catch(Exception e) {
System.err.println("Error opening serial port zxzx" + Serial.list()[theValue]);
e.printStackTrace();
}
}
public void PitPIb() {
PitPIs =!PitPIs;
if (!PitPIs) {
PitPIb.setLabel("ВКЛ");
} else {
PitPIb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
public void PitETHb() {
PitETHs =!PitETHs;
if (!PitETHs) {
PitETHb.setLabel("ВКЛ");
} else {
PitETHb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
public void PitUSBb() {
PitUSBs =!PitUSBs;
if (!PitUSBs) {
PitUSBb.setLabel("ВКЛ");
} else {
PitUSBb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
public void PitGSMb() {
PitGSMs =!PitGSMs;
if (!PitGSMs) {
PitGSMb.setLabel("ВКЛ");
} else {
PitGSMb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
public void Ventb() {
Vents =!Vents;
if (!Vents) {
Ventb.setLabel("ВКЛ");
} else {
Ventb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
public void resetb() {
resets =!resets;
if (!resets) {
resetb.setLabel("ВКЛ");
packet_index=2;
} else {
resetb.setLabel("ВЫКЛ");
}
//Button.lala.setLabel("СТОП");
}
总线:
public int packet_index;
class ModbusPort
{
Serial serial_port;
final int READ_COIL_STATUS = 1; // Reads the ON/OFF status of discrete outputs (0X references, coils) in the slave.
final int READ_INPUT_STATUS = 2; // Reads the ON/OFF status of discrete inputs (1X references) in the slave.
final int READ_HOLDING_REGISTERS = 3; // Reads the binary contents of holding registers (4X references) in the slave.
final int READ_INPUT_REGISTERS = 4; // Reads the binary contents of input registers (3X references) in the slave. Not writable.
final int FORCE_MULTIPLE_COILS = 15; // Forces each coil (0X reference) in a sequence of coils to either ON or OFF.
final int PRESET_MULTIPLE_REGISTERS = 16; // Presets values into a sequence of holding registers (4X references).
final int FORCE_OUTPUT_COILS=5;//tytytyty
// State Machine States
final int IDLE = 1;
final int WAITING_FOR_REPLY = 2;
final int WAITING_FOR_TURNAROUND = 3;
int state;
// frame[] is used to recieve and transmit packages.
// The maximum number of bytes in a modbus packet is 255
final int BUFFER_SIZE = 255;
int[] frame = new int[BUFFER_SIZE];
int buffer;
int timeout;
int polling;
int retry_count;
/* It must be noted in order to overcome the inter-character
time out and the delays prevalent in the Processing/Java
environment when using the serial library (RXTX-lib) the
inter-character time out has been increased to 30ms diverging
from the modbus standard. To increase the packet rate transfer
from the FTDI chip the latency-timer has to be decreased from
16ms to 1ms and the usb transfer size has to be decreased from
4096 to 256 bytes. This can be done from device manager in port settings.
So if you are experiencing packet errors then increase the T1_5
inter-character time out variable.
*/
int T1_5 = 30; // inter character time out in milliseconds
int delayStart;
Packet[] packets;
int total_no_of_packets;
Packet packet; // global active packet
ModbusPort(Serial serial_port, int timeout, int polling, int retry_count, Packet[] packets, int total_no_of_packets)
{
this.serial_port = serial_port;
this.timeout = timeout;
this.polling = polling;
this.retry_count = retry_count;
this.packets = packets;
this.total_no_of_packets = total_no_of_packets;
state = IDLE;
delayStart = 0;
packet_index = 0;
}
// Modbus Master State Machine
void update()
{
switch (state)
{
case IDLE:
idle();
break;
case WAITING_FOR_REPLY:
waiting_for_reply();
break;
case WAITING_FOR_TURNAROUND:
waiting_for_turnaround();
break;
}
}
private void idle()
{
// Initialize the connection_status variable to the
// total_no_of_packets. This value cannot be used as
// an index (and normally you won't). Returning this
// value to the main sketch informs the user that the
// previously scanned packet has no connection error.
int connection_status = total_no_of_packets;
int failed_connections = 0;
boolean current_connection;
do
{
if (packet_index == total_no_of_packets) // wrap around to the beginning
packet_index = 0;
packet = packets[packet_index]; // get the next packet
// get the current connection status
current_connection = packet.connection;
if (!current_connection)
{
connection_status = packet_index;
// If all the connection attributes are false return
// immediately to the main sketch
if (++failed_connections == total_no_of_packets)
return;
}
//packet_index++;/// тут дописать способ выбора пакеты для отсылки
}
while (!current_connection); // while a packet has no connection get the next one
constructPacket();
}
private void constructPacket()
{
packet.requests++;
frame[0] = packet.id;
frame[1] = packet.function;
frame[2] = packet.address >> 8; // address High
frame[3] = packet.address & 0xFF; // address Low
// For functions 1 & 2 data is the number of points
// For functions 3, 4 & 16 data is the number of registers
// For function 15 data is the number of coils
frame[4] = packet.data >> 8; // MSB
frame[5] = packet.data & 0xFF; // LSB
int frameSize;
// construct the frame according to the modbus function
if (packet.function == PRESET_MULTIPLE_REGISTERS)
frameSize = construct_F16();
else if (packet.function == FORCE_MULTIPLE_COILS)
frameSize = construct_F15();
else // else functions 1,2,3 & 4 is assumed. They all share the exact same request format.
frameSize = 8; // the request is always 8 bytes in size for the above mentioned functions.
int crc16 = calculateCRC(frameSize - 2);
frame[frameSize - 2] = crc16 >> 8; // split crc into 2 bytes
frame[frameSize - 1] = crc16 & 0xFF;
sendPacket(frameSize);
state = WAITING_FOR_REPLY; // state change
// if broadcast is requested (id == 0) for function 15 or 16 then override
// the previous state and force a success since the slave won't respond
if (packet.id == 0)
processSuccess();
}
private int construct_F16()
{
int no_of_bytes = packet.data * 2;
frame[6] = no_of_bytes; // number of bytes
int index = 7; // user data starts at index 7
int no_of_registers = packet.data;
int temp;
for (int i = 0; i < no_of_registers; i++)
{
temp = packet.register_array[i]; // get the data
frame[index] = temp >> 8;
index++;
frame[index] = temp & 0xFF;
index++;
}
int frameSize = 9 + no_of_bytes; // first 7 bytes of the array + 2 bytes CRC + noOfBytes
return frameSize;
}
private int construct_F15()
{
// function 15 coil information is packed LSB first until the first 16 bits are completed
// It is received the same way..
int no_of_registers = packet.data / 16;
int no_of_bytes = no_of_registers * 2;
// if the number of points dont fit in even 2byte amounts (one register) then use another register and pad
if (packet.data % 16 > 0)
{
no_of_registers++;
no_of_bytes++;
}
frame[6] = no_of_bytes;
int bytes_processed = 0;
int index = 7; // user data starts at index 7
int temp;
for (int i = 0; i < no_of_registers; i++)
{
temp = packet.register_array[i]; // get the data
frame[index] = temp & 0xFF;
bytes_processed++;
if (bytes_processed < no_of_bytes)
{
frame[index + 1] = temp >> 8;
bytes_processed++;
index += 2;
}
}
int frameSize = 9 + no_of_bytes; // first 7 bytes of the array + 2 bytes CRC + noOfBytes
return frameSize;
}
// get the serial data from the buffer
void waiting_for_reply()
{
if (serial_port.available() > 0) // is there something to check?
{
boolean overflowFlag = false;
buffer = 0;
while (serial_port.available() > 0)
{
// The maximum number of bytes is limited to the serial buffer size
// of BUFFER_SIZE. If more bytes is received than the BUFFER_SIZE the
// overflow flag will be set and the serial buffer will be read until
// all the data is cleared from the receive buffer, while the slave is
// still responding.
if (overflowFlag)
serial_port.read();
else
{
if (buffer == BUFFER_SIZE)
overflowFlag = true;
frame[buffer] = serial_port.read();
buffer++;
}
// This is not 100% correct but it will suffice.
// worst case scenario is if more than one character time expires
// while reading from the buffer then the buffer is most likely empty
// If there are more bytes after such a delay it is not supposed to
// be received and thus will force a frame_error.
delay(T1_5); // inter character time out
}
// The minimum buffer size from a slave can be an exception response of
// 5 bytes. If the buffer was partially filled set a frame_error.
// The maximum number of bytes in a modbus packet is 256 bytes.
if ((buffer < 5) || overflowFlag)
processError();
// Modbus over serial line datasheet states that if an unexpected slave
// responded the master must do nothing and continue with the time out.
// This seems silly cause if an incorrect slave responded you would want to
// have a quick turnaround and poll the right one again. If an unexpected
// slave responded it will most likely be a frame error in any event
else if (frame[0] != packet.id) // check id returned
processError();
else
processReply();
} else if ((millis() - delayStart) > timeout) // check timeout
{
processError();
state = IDLE; //state change, override processError() state
}
}
private void processReply()
{
// combine the crc Low & High bytes
int received_crc = ((frame[buffer - 2] << 8) | frame[buffer - 1]);
int calculated_crc = calculateCRC(buffer - 2);
if (calculated_crc == received_crc) // verify checksum
{
// To indicate an exception response a slave will 'OR'
// the requested function with 0x80
if ((frame[1] & 0x80) == 0x80) // extract 0x80
{
packet.exception_errors++;
processError();
} else
{
switch (frame[1]) // check function returned
{
case READ_COIL_STATUS:
case READ_INPUT_STATUS:
case FORCE_OUTPUT_COILS:
process_F1_F2();
break;
case READ_INPUT_REGISTERS:
case READ_HOLDING_REGISTERS:
process_F3_F4();
break;
case FORCE_MULTIPLE_COILS:
case PRESET_MULTIPLE_REGISTERS:
process_F15_F16();
break;
default: // illegal function returned
processError();
break;
}
}
} else // checksum failed
{
processError();
}
}
private void process_F1_F2()
{
// packet.data for function 1 & 2 is actually the number of boolean points
int no_of_registers = packet.data / 16;
int number_of_bytes = no_of_registers * 2;
// if the number of points dont fit in even 2byte amounts (one register) then use another register and pad
if (packet.data % 16 > 0)
{
no_of_registers++;
number_of_bytes++;
}
if (frame[2] == number_of_bytes) // check number of bytes returned
{
int bytes_processed = 0;
int index = 3; // start at the 4th element in the frame and combine the Lo byte
int temp;
for (int i = 0; i < no_of_registers; i++)
{
temp = frame[index];
bytes_processed++;
if (bytes_processed < number_of_bytes)
{
temp = (frame[index + 1] << 8) | temp;
bytes_processed++;
index += 2;
}
packet.register_array[i] = temp;
}
processSuccess();
} else // incorrect number of bytes returned
processError();
}
private void process_F3_F4()
{
// check number of bytes returned - unsigned int == 2 bytes
// data for function 3 & 4 is the number of registers
if (frame[2] == (packet.data * 2))
{
int index = 3;
for (int i = 0; i < packet.data; i++)
{
// start at the 4th element in the frame and combine the Lo byte
packet.register_array[i] = (frame[index] << 8) | frame[index + 1];
index += 2;
}
processSuccess();
} else // incorrect number of bytes returned
processError();
}
private void process_F15_F16()
{
// Functions 15 & 16 have the exact same response from the slave
// which is an echo of the query
int recieved_address = ((frame[2] << 8) | frame[3]);
int recieved_data = ((frame[4] << 8) | frame[5]);
if ((recieved_address == packet.address) && (recieved_data == packet.data))
processSuccess();
else
processError();
}
void waiting_for_turnaround()
{
if ((millis() - delayStart) >= polling)
state = IDLE;
}
private void processError()
{
packet.retries++;
packet.failed_requests++;
// if the number of retries have reached the max number of retries
// allowable, stop requesting the specific packet
if (packet.retries == retry_count)
{
packet.connection = false;
packet.retries = 0;
}
state = WAITING_FOR_TURNAROUND;
delayStart = millis(); // start the turnaround delay
}
private void processSuccess()
{
packet.successful_requests++; // transaction sent successfully
packet.retries = 0; // if a request was successful reset the retry counter
state = WAITING_FOR_TURNAROUND;
delayStart = millis(); // start the turnaround delay
}
private int calculateCRC(int bufferSize)
{
int temp, temp2, flag;
temp = 0xFFFF;
for (int i = 0; i < bufferSize; i++)
{
temp = temp ^ frame[i];
for (int j = 1; j <= 8; j++)
{
flag = temp & 0x0001;
temp >>= 1;
if (flag == 1)
temp ^= 0xA001;
}
}
// Reverse byte order.
temp2 = temp >> 8;
temp = (temp << 8) | temp2;
temp &= 0xFFFF;
return temp; // the returned value is already swopped - crcLo byte is first & crcHi byte is last
}
private void sendPacket(int bufferSize)
{
serial_port.clear();
// This is where the magic happens!
// Initially the delay between characters were too great
// when int's were being transmitted by indexing the
// frame array. Java does not have an unsigned char
// to work with numbers from 0 - 255 it only has a byte type
// which expects 127 to -128. This does not actually matter
// since the number is still 8bits. It's only the protocol
// that reconstructs the frame on the other side that dictates
// if it's signed or not. From modbus perspective it's still
// an 8bit byte value that being received and transmitted.
// The write() method in the serial class expects any type
// but the fastest type that will be transfered to the Serial
// buffer is bytes or more specifically an array of bytes.
// By casting the frame array containing our data to a byte
// array of the exact size that we want to transmit we can
// overcome the delay between the transmission of characters.
// We can do this because the data in frame will never exceed
// the value of an 8 bit byte.
byte[] byteFrame = new byte[bufferSize];
for (int i = 0; i < bufferSize; i++)
byteFrame[i] = (byte)frame[i];
serial_port.write(byteFrame);
delayStart = millis(); // initialize timeout delay
}
}
class Packet
{
// specific packet info
int id, function, address;
// For functions 1 & 2 data is the number of points
// For functions 3, 4 & 16 data is the number of registers
// For function 15 data is the number of coils
int data;
int[] register_array;
// non specific modbus information
int requests;
int successful_requests;
int failed_requests;
int exception_errors;
int retries;
boolean connection; // comms status of the packet
Packet(int id, int function, int address, int data, int[] register_array)
{
this.id = id;
this.function = function;
this.address = address;
this.data = data;
this.register_array = register_array;
connection = true; // enable packet requesting
}
}