Serial communication learning (GPS module) 2021.5.10

1. Introduction to serial communication

        Serial communication (Serial Communication) is to use the serial port to send and receive bytes bit by bit. Although slower than byte-wise parallel communication, because serial communication is asynchronous, the port can send data on one wire while receiving data on the other. **The most important parameters of serial communication are baud rate, data bits, stop bits and parity**.

1.1 Baud rate

        The baud rate refers to the change in the unit time after the signal is modulated, that is, the number of times the carrier parameter changes in the unit time, such as transmitting 240 characters per second, and each character format contains 10 bits (1 start bit , 1 stop bit, 8 data bits), the baud rate at this time is 240Bd, and the bit rate is 10 bits*240/second=2400bps.

1.2 Data bits

        When a computer sends a packet of information, the actual data is often not 8 bits, the standard values ​​are 6, 7 and 8 bits. The standard ASCII code is 0~127 (7 bits), and the extended ASCII code is 0~255 (8 bits). If the data uses simple text (standard ASCII code), then each data packet uses 7 bits of data. Each packet refers to a byte, including start/stop bits, data bits, and parity bits.

1.3 Stop bit

        The stop bit is used to represent the last bit of a single packet. Typical values ​​are 1, 1.5 and 2 bits.

1.4 Parity bits

        There are four error detection methods for serial communication: even, odd, high and low. Of course, no check digit is also possible. For the case of even and odd parity, assume that the transmitted data bits are 01001100, if it is odd parity, the odd parity bit is 0 (to ensure that there are an odd number of 1s in total), if it is even parity, then even parity bit is 1 (make sure there is an even number of 1s in total).

2. GPS module serial port communication configuration

GPS module
front
on the other hand

2.1 Driver installation

        Before inserting the USB on the GPS module into the computer, first ask the customer service staff for the driver. After getting the PL2303_Prolific_GPS_AllInOne_1013.exe driver installation package, double-click to run it. After the installation is complete, you can check the installed program in the control panel. PL-2303 USB -to-Serial, indicating that the installation was successful.



insert image description here

        Of course, you can also download the relevant driver installation package from the Internet and install it yourself. There is no problem, such as the following PL2303_Prolific_DriveInstaller_v130.exe and PL2303_64bit_Installer.exe.

2.2 Insert GPS module

        After the driver is successfully installed, you can insert the USB interface of the GPS module into the USB interface of the computer. At this time, the bottom right of the computer will prompt that the device driver has been successfully installed, and you can also check it in the computer->device manager

        You can see the Prolific USB-to-Serial Comm Port (COM3) under the ports (COM and LPT) of the device manager, right-click -> Properties to view the specific information of the corresponding port of the GPS module, the most important of which is the port setting The four parameters of baud rate, data bits, stop bits and parity .
insert image description here

conventional
port settings
driver
details

2.3 Introduction to serial communication data of GPS module

insert image description here

        Since the data received by the GPS module follows the NMEA-0183 protocol , which uses ASCII codes, its serial communication default parameters are: baud rate=9600bps, data bit=8bit, start bit=1bit, stop bit=1bit, no parity verify . Because the data contains GPRMC, GPVTG, GPGNS, GPGGA, GPGSA, GPGLL, etc., but I only need one piece of data in RMC, so open the serial port assistant SSCOM3.2, open the COM3 serial port and send a new line to the GPS module $PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29so that the module only outputs GPRMC (Here is the instruction that the customer service staff told me)

Serial debugging assistant

insert image description here

3. Java implements GPS module serial port communication

3.1 Required environment (Eclipse+Java)

Eclipse
Java

3.2 Create a new Java project COMM

        Open Eclipse , File -> New Java Project, enter the project name as COMM, and select the corresponding JAVA JDK 1.8 and confirm it, then create three Package packages (bean, serialport and test) under the src folder, and add them to the bean Create a GPSRMCMessage class under the package, create a CostomException class, a ParamConfig class, and a SerialPortUtil class under the serialport package, and create a hellodouble class and an Operate class under the test package.

3.3 java class code under each package

3.3.1 SerialPortUtils.java

package serialport;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import java.util.TooManyListenersException;

import bean.GPSRMCMessage;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

/**
 * 串口参数的配置 串口一般有如下参数可以在该串口打开以前进行配置: 包括串口号,波特率,输入/输出流控制,数据位数,停止位和奇偶校验。
 */
// 注:串口操作类一定要继承SerialPortEventListener
public class SerialPortUtils implements SerialPortEventListener {
    
    
	// 检测系统中可用的通讯端口类
	private CommPortIdentifier commPortId;
	// 枚举类型
	private Enumeration<CommPortIdentifier> portList;
	// RS232串口
	private SerialPort serialPort;
	// 输入流
	private InputStream inputStream;
	// 输出流
	private OutputStream outputStream;
	// 保存串口返回信息
	private String data;
	// 保存串口返回信息十六进制
	private String dataHex;
	// 解析后的数据
	private GPSRMCMessage gpsrmc_msg;
    public int resulti=1;//写txt的个数

	@SuppressWarnings("unchecked")
	public void init(ParamConfig paramConfig) throws CostomException {
    
    
		// 获取系统中所有的通讯端口
		portList = CommPortIdentifier.getPortIdentifiers();
		// 记录是否含有指定串口
		boolean isExsist = false;
		// 循环通讯端口
		while (portList.hasMoreElements()) {
    
    
			commPortId = portList.nextElement();
			// 判断是否是串口
			if (commPortId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
    
    
				// 比较串口名称是否是指定串口
				if (paramConfig.getSerialNumber().equals(commPortId.getName())) {
    
    
					// 串口存在
					isExsist = true;
					// 打开串口
					try {
    
    
						// open:(应用程序名【随意命名】,阻塞时等待的毫秒数)
						serialPort = (SerialPort) commPortId.open(Object.class.getSimpleName(), 2000);
						// 设置串口监听
						serialPort.addEventListener(this);
						// 设置串口数据时间有效(可监听)
						serialPort.notifyOnDataAvailable(true);
						// 设置串口通讯参数:波特率,数据位,停止位,校验方式
						serialPort.setSerialPortParams(paramConfig.getBaudRate(), paramConfig.getDataBit(),
								paramConfig.getStopBit(), paramConfig.getCheckoutBit());
					} catch (PortInUseException e) {
    
    
						throw new CostomException("端口被占用");
					} catch (TooManyListenersException e) {
    
    
						throw new CostomException("监听器过多");
					} catch (UnsupportedCommOperationException e) {
    
    
						throw new CostomException("不支持的COMM端口操作异常");
					}
					// 结束循环
					break;
				}
			}
		}
		// 若不存在该串口则抛出异常
		if (!isExsist) {
    
    
			throw new CostomException("不存在该串口!");
		}
	}

	/**
	 * 实现接口SerialPortEventListener中的方法 读取从串口中接收的数据
	 */
	@Override
	public void serialEvent(SerialPortEvent event) {
    
    
		switch (event.getEventType()) {
    
    
		case SerialPortEvent.BI: // 通讯中断
		case SerialPortEvent.OE: // 溢位错误
		case SerialPortEvent.FE: // 帧错误
		case SerialPortEvent.PE: // 奇偶校验错误
		case SerialPortEvent.CD: // 载波检测
		case SerialPortEvent.CTS: // 清除发送
		case SerialPortEvent.DSR: // 数据设备准备好
		case SerialPortEvent.RI: // 响铃侦测
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空
			break;
		case SerialPortEvent.DATA_AVAILABLE: // 有数据到达
			// 调用读取数据的方法
			try {
    
    
				myReadComm();
			} catch (CostomException e) {
    
    
				e.printStackTrace();
			}
			break;
		default:
			break;
		}
	}

	public void myReadComm() throws CostomException {
    
    
		try {
    
    
			inputStream = serialPort.getInputStream();
			// 通过输入流对象的available方法获取数组字节长度
			byte[] readBuffer = new byte[inputStream.available()];
			// 从线路上读取数据流
			int len = 0;
			data = "";
			// 从输入流读取数据,直到遇到"\r\n"或数据为空,即读取一行数据
			while (true) {
    
    
				len = inputStream.read(readBuffer);
				if (len == -1 || len == 0)
					break;
				data = data.concat(new String(readBuffer, 0, len));
				if (data.endsWith("\r\n"))
					break;
			}
			System.out.print(data);
			// 转为十六进制数据
			//dataHex = bytesToHexString(data.getBytes());
			//System.out.println(dataHex);
			 //解析数据
			gpsrmc_msg = GPSRMCMessage.parse(data);
			System.out.print(gpsrmc_msg.toMyString());
			inputStream.close();
			inputStream = null;
//			//2021.4.11 By jzbg
//			FileOutputStream fos = null;
//			OutputStreamWriter writer = null;
//			String writetxtfilepath = "D:\\guotuziyuan\\zhongjiban\\system\\ActiveDemoEarth\\WindowsFormsApplication1\\bin\\x64\\Release\\tag\\result"+resulti+".txt";
//			File file = new File(writetxtfilepath);
//			fos = new FileOutputStream(file);
//			writer = new OutputStreamWriter(fos,"utf-8");
//			writer.write(msg.toJJGString());
//			writer.close();
//			fos.close();
			this.resulti++;
		} catch (IOException e) {
    
    
			throw new CostomException("读取串口数据时发生IO异常");
		}
	}

	public void readComm() throws CostomException {
    
    
		try {
    
    
			inputStream = serialPort.getInputStream();
			// 通过输入流对象的available方法获取数组字节长度
			byte[] readBuffer = new byte[inputStream.available()];
			// 从线路上读取数据流
			int len = 0;
			while ((len = inputStream.read(readBuffer)) != -1) {
    
    
				// 直接获取到的数据
				data = new String(readBuffer, 0, len).trim();
				// 转为十六进制数据
				dataHex = bytesToHexString(readBuffer);
				System.out.println("data:" + data);
				System.out.println("dataHex:" + dataHex);// 读取后置空流对象
				inputStream.close();
				inputStream = null;
				break;
			}
		} catch (IOException e) {
    
    
			throw new CostomException("读取串口数据时发生IO异常");
		}
	}

	public void sendComm(String data) throws CostomException {
    
    
		byte[] writerBuffer = null;
		try {
    
    
			writerBuffer = hexToByteArray(data);
		} catch (NumberFormatException e) {
    
    
			throw new CostomException("命令格式错误!");
		}
		try {
    
    
			outputStream = serialPort.getOutputStream();
			outputStream.write(writerBuffer);
			outputStream.flush();
		} catch (NullPointerException e) {
    
    
			throw new CostomException("找不到串口。");
		} catch (IOException e) {
    
    
			throw new CostomException("发送信息到串口时发生IO异常");
		}
	}

	public void closeSerialPort() throws CostomException {
    
    
		if (serialPort != null) {
    
    
			serialPort.notifyOnDataAvailable(false);
			serialPort.removeEventListener();
			if (inputStream != null) {
    
    
				try {
    
    
					inputStream.close();
					inputStream = null;
				} catch (IOException e) {
    
    
					throw new CostomException("关闭输入流时发生IO异常");
				}
			}
			if (outputStream != null) {
    
    
				try {
    
    
					outputStream.close();
					outputStream = null;
				} catch (IOException e) {
    
    
					throw new CostomException("关闭输出流时发生IO异常");
				}
			}
			serialPort.close();
			serialPort = null;
		}
	}

	/**
	 * 十六进制串口返回值获取
	 */
	public String getDataHex() {
    
    
		String result = dataHex;
		// 置空执行结果
		dataHex = null;
		// 返回执行结果
		return result;
	}

	/**
	 * 串口返回值获取
	 */
	public String getData() {
    
    
		String result = data;
		// 置空执行结果
		data = null;
		// 返回执行结果
		return result;
	}

	/**
	 * Hex字符串转byte
	 * 
	 * @param inHex
	 *            待转换的Hex字符串
	 * @return 转换后的byte
	 */
	public static byte hexToByte(String inHex) {
    
    
		return (byte) Integer.parseInt(inHex, 16);
	}

	/**
	 * hex字符串转byte数组
	 * 
	 * @param inHex
	 *            待转换的Hex字符串
	 * @return 转换后的byte数组结果
	 */
	public static byte[] hexToByteArray(String inHex) {
    
    
		int hexlen = inHex.length();
		byte[] result;
		if (hexlen % 2 == 1) {
    
    
			// 奇数
			hexlen++;
			result = new byte[(hexlen / 2)];
			inHex = "0" + inHex;
		} else {
    
    
			// 偶数
			result = new byte[(hexlen / 2)];
		}
		int j = 0;
		for (int i = 0; i < hexlen; i += 2) {
    
    
			result[j] = hexToByte(inHex.substring(i, i + 2));
			j++;
		}
		return result;
	}

	/**
	 * 数组转换成十六进制字符串
	 * 
	 * @param byte[]
	 * @return HexString
	 */
	public static final String bytesToHexString(byte[] bArray) {
    
    
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
    
    
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}
}

3.3.2 CostomException.java

package serialport;

public class CostomException extends Exception{
    
    

	private static final long serialVersionUID = 4087486187456785575L;

	public CostomException() {
    
    
        super();
    }
	
	public CostomException(String message) {
    
    
        super(message);
    }
}

3.3.3 ParamConfig.java

package serialport;

public class ParamConfig {
    
    

    private String serialNumber;// 串口号
    private int baudRate;        // 波特率
    private int checkoutBit;    // 校验位
    private int dataBit;        // 数据位
    private int stopBit;        // 停止位
    
    public ParamConfig() {
    
    }
        
    /**
     * 构造方法
     * @param serialNumber    串口号
     * @param baudRate        波特率
     * @param checkoutBit    校验位
     * @param dataBit        数据位
     * @param stopBit        停止位
     */
    public ParamConfig(String serialNumber, int baudRate, int checkoutBit, int dataBit, int stopBit) {
    
    
        this.serialNumber = serialNumber;
        this.baudRate = baudRate;
        this.checkoutBit = checkoutBit;
        this.dataBit = dataBit;
        this.stopBit = stopBit;
    }

	public String getSerialNumber() {
    
    
		return serialNumber;
	}

	public void setSerialNumber(String serialNumber) {
    
    
		this.serialNumber = serialNumber;
	}

	public int getBaudRate() {
    
    
		return baudRate;
	}

	public void setBaudRate(int baudRate) {
    
    
		this.baudRate = baudRate;
	}

	public int getCheckoutBit() {
    
    
		return checkoutBit;
	}

	public void setCheckoutBit(int checkoutBit) {
    
    
		this.checkoutBit = checkoutBit;
	}

	public int getDataBit() {
    
    
		return dataBit;
	}

	public void setDataBit(int dataBit) {
    
    
		this.dataBit = dataBit;
	}

	public int getStopBit() {
    
    
		return stopBit;
	}

	public void setStopBit(int stopBit) {
    
    
		this.stopBit = stopBit;
	}


}

3.3.4 GPSRMCMessage.java

package bean;

public class GPSRMCMessage 
{
    
    
	private String RMCID; // $GPRMC,语句 ID,表明该语句为 Recommended Minimum (RMC)推荐最小定位信息
	private double UTCTime; // UTC 时间,hhmmss.sss 格式
	private String state; // 状态,A=定位,V=未定位
	private double lat; // 纬度 ddmm.mmmm,度分格式(前导位数不足则补 0)
	private String LatDirection; // 纬度 N(北纬)或 S(南纬)
	private double lon; // 经度 dddmm.mmmm,度分格式(前导位数不足则补 0)
	private String LonDirection; // 经度 E(东经)或 W(西经)
	private double speed; // 速度,节,Knots
	private double α; // 方位角,度
	private int UTCDate; // UTC 日期,DDMMYY 格式
	private double δ; // 磁偏角,(000 - 180)度(前导位数不足则补 0)
	private double δDirection; // 磁偏角方向,E=东 W=西
	private String verification_value; // 校验值
	//$GNRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
	public GPSRMCMessage() 
	{
    
    
		this.RMCID = ""; 
		this.UTCTime = 0;
		this.state = "";
		this.lat = 0;
		this.LatDirection = "";
		this.lon = 0;
		this.LonDirection = "";
		this.speed = 0;
		this.α = 0;
		this.UTCDate = 0;
		this.δ  =0;
		this.δDirection = 0; 
		this.verification_value = "";
	}

	public static GPSRMCMessage parse(String data) 
	{
    
    
		GPSRMCMessage msg = new GPSRMCMessage();
		String[] s = data.split(",");
		msg.RMCID = s[0]; 
		msg.UTCTime = Double.valueOf(s[1]);
		msg.state = "";
		Double temp = Double.valueOf(s[3]);
		msg.lat =  temp/100.0 - (temp%100.0)/100.0 + (temp%100.0)/60.0;
		msg.LatDirection = "";
		temp = Double.valueOf(s[5]);
		msg.lon = temp/100.0 - (temp%100.0)/100.0 + (temp%100.0)/60.0;
		msg.LonDirection = "";
		msg.speed = Double.valueOf(s[7]);
		msg.α = Double.valueOf(s[8]);
		msg.UTCDate = Integer.valueOf(s[9]);;
		msg.δ  =0;
		msg.δDirection = 0; 
		msg.verification_value =s[12];
		return msg;
	}

	public String toMyString()
	{
    
    
		return 	"推荐最小定位信息:"	+this.RMCID
		+ "UTC:" +this.UTCTime
		+ "状态:"+this.state
		+ "纬度:"+this.lat
		+ "纬度方向:"+this.LatDirection
		+ "经度:"+this.lon
		+ "经度方向:"+this.LonDirection
		+ "速度:"+this.speed
		+ "方位角:"+this.α
		+ "UTC日期:"+this.UTCDate
		+ "磁偏角:"+this.δ
		+ "磁偏角方向:"+this.δDirection
		+ "校验值:"+this.verification_value;
	}
}

3.3.5 Operate.java (the class where the main function is located)

package test;

import serialport.CostomException;
import serialport.ParamConfig;
import serialport.SerialPortUtils;

public class Operate 
{
    
    
	public static void Execute() throws CostomException
	{
    
    
		// 实例化串口操作类对象
        SerialPortUtils serialPort = new SerialPortUtils();
        // 创建串口必要参数接收类并赋值,赋值串口号,波特率,校验位,数据位,停止位
        ParamConfig paramConfig = new ParamConfig("COM3", 9600, 0, 8, 1);
        // 初始化设置,打开串口,开始监听读取串口数据,并打印数据
        serialPort.init(paramConfig);
	}

	public static void main(String[] args) throws Exception 
	{
    
    
        Operate.Execute();
    }
}

3.3.6 hellodouble.java

package test;

public class hellodouble 
{
    
    
	public static void main(String[] args) 
	{
    
    
		double a =11421.1059 ,b=3031.7611;
		double temp =a;
		System.out.println(temp/100.0 - (temp%100.0)/100.0 + (temp%100.0)/60.0);
	}
}

3.4 Add serial communication dependency package

        After the java code is written,If you run Operate.java directly, it will prompt that there is no rxtxSerial link in the java library path, so add dependencies related to serial port communication in the COMM project.
insert image description here
        The jar package (RXTXcomm.jar) and dll (rxtxParallel.dll and rxtxSerial.dll) that the serial communication project depends on are shown in the figure below. Copy the two dll files and a jar package to the Java project COMM, and add the jar package to Go to the Java Build Path running path of the project COMM, and run Operate.java again to run successfully and receive data.

Configure Java Build Path
Copy dependencies

3.5 Running results

        As shown in the figure below, the received GNRMC data is output in the console $GNRMC,023724.000,A,3031.7606,N,11421.0989,E,0.40,356.63,100521,,,A*7F, and the data is also analyzed to obtain the following推荐最小定位信息:$GNRMCUTC:23724.0状态:纬度:30.529343333333333纬度方向:经度:114.35164833333334经度方向:速度:0.4方位角:356.63UTC日期:100521磁偏角:0.0磁偏角方向:0.0校验值:A*7F
insert image description here

4. C# implements GPS module serial port communication (using SerialPort)

4.1 Required environment (VS 2015 +C#)

4.2 Create a new C# Windows form project SerailCOMMWindows

        Use Visual Studio to create a new Windows form application under C#, change the form name of Form1 to serial port debugging assistant, and use the toolbox on the left to drag the following controls into the form: 4 GroupBoxes, 7 Buttons Button, 8 Label tags, 5 ComBox drop-down boxes, 2 RadioButton radio button boxes, 4 TextBox text boxes, 1 SerialPort serial port, 1 StatusStrip status bar, the specific description is as follows :

groupBox1 为串口设置组合框
groupBox2 为数据接收组合框
groupBox3 为数据发送组合框
groupBox4 为文件操作组合框
button2 为打开串口按钮
button3 为关闭串口按钮
button4 为清空数据按钮
button5 为发送数据按钮
button6 为打开文件按钮
button7 为保存文件按钮
label1 为串口号标签
label2 为波特率标签
label3 为停止位标签
label4 为奇偶校验标签
label5 为数据位标签
label6 为间隔标签
label8 为文件路径标签
comboBox1 为串口号对应下拉框
comboBox2 为波特率对应下拉框
comboBox3 为停止位对应下拉框
comboBox4 为奇偶校验对应下拉框
comboBox5 为数据位对应下拉框
radioButton1 为字符显示单选框
radioButton2 为hex显示单选框
textBox1 为数据接收下侧文本框
textBox2 为间隔右侧文本框
textBox3 为文件路径右侧文本框
textBox4 为数据发送下侧文本框

        The designed Windows form layout is shown in the figure below
insert image description here

4.3 C# project code

4.3.1 Form designer code Form1.Designer.cs (just compare)

namespace SerialCOMMWindows
{
    
    
    partial class Form1
    {
    
    
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
    
    
            if (disposing && (components != null))
            {
    
    
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
    
    
            this.components = new System.ComponentModel.Container();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.button3 = new System.Windows.Forms.Button();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.label7 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.radioButton2 = new System.Windows.Forms.RadioButton();
            this.radioButton1 = new System.Windows.Forms.RadioButton();
            this.button2 = new System.Windows.Forms.Button();
            this.comboBox5 = new System.Windows.Forms.ComboBox();
            this.comboBox4 = new System.Windows.Forms.ComboBox();
            this.label5 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.comboBox3 = new System.Windows.Forms.ComboBox();
            this.comboBox2 = new System.Windows.Forms.ComboBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.groupBox3 = new System.Windows.Forms.GroupBox();
            this.textBox4 = new System.Windows.Forms.TextBox();
            this.button5 = new System.Windows.Forms.Button();
            this.button4 = new System.Windows.Forms.Button();
            this.groupBox4 = new System.Windows.Forms.GroupBox();
            this.label8 = new System.Windows.Forms.Label();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.button7 = new System.Windows.Forms.Button();
            this.button6 = new System.Windows.Forms.Button();
            this.statusStrip1 = new System.Windows.Forms.StatusStrip();
            this.serialPort1 = new System.IO.Ports.SerialPort(this.components);
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.groupBox3.SuspendLayout();
            this.groupBox4.SuspendLayout();
            this.SuspendLayout();
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.button3);
            this.groupBox1.Controls.Add(this.textBox2);
            this.groupBox1.Controls.Add(this.label7);
            this.groupBox1.Controls.Add(this.label6);
            this.groupBox1.Controls.Add(this.radioButton2);
            this.groupBox1.Controls.Add(this.radioButton1);
            this.groupBox1.Controls.Add(this.button2);
            this.groupBox1.Controls.Add(this.comboBox5);
            this.groupBox1.Controls.Add(this.comboBox4);
            this.groupBox1.Controls.Add(this.label5);
            this.groupBox1.Controls.Add(this.label4);
            this.groupBox1.Controls.Add(this.comboBox3);
            this.groupBox1.Controls.Add(this.comboBox2);
            this.groupBox1.Controls.Add(this.label3);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.comboBox1);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Location = new System.Drawing.Point(44, 32);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(538, 135);
            this.groupBox1.TabIndex = 0;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "串口设置";
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(442, 49);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(75, 23);
            this.button3.TabIndex = 17;
            this.button3.Text = "关闭串口";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // textBox2
            // 
            this.textBox2.Location = new System.Drawing.Point(388, 85);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(63, 21);
            this.textBox2.TabIndex = 16;
            this.textBox2.Text = "1000";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(457, 88);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(17, 12);
            this.label7.TabIndex = 15;
            this.label7.Text = "ms";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(353, 88);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(29, 12);
            this.label6.TabIndex = 14;
            this.label6.Text = "间隔";
            // 
            // radioButton2
            // 
            this.radioButton2.AutoSize = true;
            this.radioButton2.Location = new System.Drawing.Point(223, 85);
            this.radioButton2.Name = "radioButton2";
            this.radioButton2.Size = new System.Drawing.Size(65, 16);
            this.radioButton2.TabIndex = 13;
            this.radioButton2.TabStop = true;
            this.radioButton2.Text = "hex显示";
            this.radioButton2.UseVisualStyleBackColor = true;
            // 
            // radioButton1
            // 
            this.radioButton1.AutoSize = true;
            this.radioButton1.Location = new System.Drawing.Point(146, 85);
            this.radioButton1.Name = "radioButton1";
            this.radioButton1.Size = new System.Drawing.Size(71, 16);
            this.radioButton1.TabIndex = 12;
            this.radioButton1.TabStop = true;
            this.radioButton1.Text = "字符显示";
            this.radioButton1.UseVisualStyleBackColor = true;
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(352, 49);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(75, 23);
            this.button2.TabIndex = 11;
            this.button2.Text = "打开串口";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // comboBox5
            // 
            this.comboBox5.FormattingEnabled = true;
            this.comboBox5.Items.AddRange(new object[] {
    
    
            "8",
            "7",
            "5",
            "6"});
            this.comboBox5.Location = new System.Drawing.Point(205, 51);
            this.comboBox5.Name = "comboBox5";
            this.comboBox5.Size = new System.Drawing.Size(56, 20);
            this.comboBox5.TabIndex = 9;
            // 
            // comboBox4
            // 
            this.comboBox4.FormattingEnabled = true;
            this.comboBox4.Items.AddRange(new object[] {
    
    
            "无校验",
            "奇校验",
            "偶校验"});
            this.comboBox4.Location = new System.Drawing.Point(207, 23);
            this.comboBox4.Name = "comboBox4";
            this.comboBox4.Size = new System.Drawing.Size(54, 20);
            this.comboBox4.TabIndex = 8;
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(146, 54);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(53, 12);
            this.label5.TabIndex = 7;
            this.label5.Text = "数据位:";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(146, 26);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(65, 12);
            this.label4.TabIndex = 6;
            this.label4.Text = "奇偶校验:";
            // 
            // comboBox3
            // 
            this.comboBox3.FormattingEnabled = true;
            this.comboBox3.Items.AddRange(new object[] {
    
    
            "1",
            "1.5",
            "2"});
            this.comboBox3.Location = new System.Drawing.Point(66, 82);
            this.comboBox3.Name = "comboBox3";
            this.comboBox3.Size = new System.Drawing.Size(74, 20);
            this.comboBox3.TabIndex = 5;
            // 
            // comboBox2
            // 
            this.comboBox2.FormattingEnabled = true;
            this.comboBox2.Items.AddRange(new object[] {
    
    
            "9600",
            "4800"});
            this.comboBox2.Location = new System.Drawing.Point(65, 51);
            this.comboBox2.Name = "comboBox2";
            this.comboBox2.Size = new System.Drawing.Size(74, 20);
            this.comboBox2.TabIndex = 4;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(7, 85);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(53, 12);
            this.label3.TabIndex = 3;
            this.label3.Text = "停止位:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(6, 54);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(53, 12);
            this.label2.TabIndex = 2;
            this.label2.Text = "波特率:";
            // 
            // comboBox1
            // 
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(66, 23);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(74, 20);
            this.comboBox1.TabIndex = 1;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(7, 26);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(53, 12);
            this.label1.TabIndex = 0;
            this.label1.Text = "串口号:";
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.textBox1);
            this.groupBox2.Location = new System.Drawing.Point(44, 181);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(544, 136);
            this.groupBox2.TabIndex = 1;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "数据接收";
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(6, 11);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBox1.Size = new System.Drawing.Size(532, 119);
            this.textBox1.TabIndex = 0;
            // 
            // groupBox3
            // 
            this.groupBox3.Controls.Add(this.textBox4);
            this.groupBox3.Controls.Add(this.button5);
            this.groupBox3.Controls.Add(this.button4);
            this.groupBox3.Location = new System.Drawing.Point(44, 337);
            this.groupBox3.Name = "groupBox3";
            this.groupBox3.Size = new System.Drawing.Size(538, 68);
            this.groupBox3.TabIndex = 2;
            this.groupBox3.TabStop = false;
            this.groupBox3.Text = "数据发送";
            // 
            // textBox4
            // 
            this.textBox4.Location = new System.Drawing.Point(6, 11);
            this.textBox4.Multiline = true;
            this.textBox4.Name = "textBox4";
            this.textBox4.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBox4.Size = new System.Drawing.Size(445, 51);
            this.textBox4.TabIndex = 2;
            // 
            // button5
            // 
            this.button5.Location = new System.Drawing.Point(457, 39);
            this.button5.Name = "button5";
            this.button5.Size = new System.Drawing.Size(75, 23);
            this.button5.TabIndex = 1;
            this.button5.Text = "发送数据";
            this.button5.UseVisualStyleBackColor = true;
            this.button5.Click += new System.EventHandler(this.button5_Click);
            // 
            // button4
            // 
            this.button4.Location = new System.Drawing.Point(457, 9);
            this.button4.Name = "button4";
            this.button4.Size = new System.Drawing.Size(75, 23);
            this.button4.TabIndex = 0;
            this.button4.Text = "清空数据";
            this.button4.UseVisualStyleBackColor = true;
            this.button4.Click += new System.EventHandler(this.button4_Click);
            // 
            // groupBox4
            // 
            this.groupBox4.Controls.Add(this.label8);
            this.groupBox4.Controls.Add(this.textBox3);
            this.groupBox4.Controls.Add(this.button7);
            this.groupBox4.Controls.Add(this.button6);
            this.groupBox4.Location = new System.Drawing.Point(44, 424);
            this.groupBox4.Name = "groupBox4";
            this.groupBox4.Size = new System.Drawing.Size(410, 69);
            this.groupBox4.TabIndex = 3;
            this.groupBox4.TabStop = false;
            this.groupBox4.Text = "文件操作";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Location = new System.Drawing.Point(9, 30);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(53, 12);
            this.label8.TabIndex = 3;
            this.label8.Text = "文件路径";
            // 
            // textBox3
            // 
            this.textBox3.Location = new System.Drawing.Point(64, 26);
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(244, 21);
            this.textBox3.TabIndex = 2;
            // 
            // button7
            // 
            this.button7.Location = new System.Drawing.Point(319, 40);
            this.button7.Name = "button7";
            this.button7.Size = new System.Drawing.Size(75, 23);
            this.button7.TabIndex = 1;
            this.button7.Text = "保存文件";
            this.button7.UseVisualStyleBackColor = true;
            // 
            // button6
            // 
            this.button6.Location = new System.Drawing.Point(319, 15);
            this.button6.Name = "button6";
            this.button6.Size = new System.Drawing.Size(75, 23);
            this.button6.TabIndex = 0;
            this.button6.Text = "打开文件";
            this.button6.UseVisualStyleBackColor = true;
            // 
            // statusStrip1
            // 
            this.statusStrip1.Location = new System.Drawing.Point(0, 500);
            this.statusStrip1.Name = "statusStrip1";
            this.statusStrip1.Size = new System.Drawing.Size(650, 22);
            this.statusStrip1.TabIndex = 4;
            this.statusStrip1.Text = "statusStrip1";
            // 
            // serialPort1
            // 
            this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(650, 522);
            this.Controls.Add(this.statusStrip1);
            this.Controls.Add(this.groupBox4);
            this.Controls.Add(this.groupBox3);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Name = "Form1";
            this.Text = "串口调试助手";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.groupBox3.ResumeLayout(false);
            this.groupBox3.PerformLayout();
            this.groupBox4.ResumeLayout(false);
            this.groupBox4.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Label label7;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.RadioButton radioButton2;
        private System.Windows.Forms.RadioButton radioButton1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.ComboBox comboBox5;
        private System.Windows.Forms.ComboBox comboBox4;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.ComboBox comboBox3;
        private System.Windows.Forms.ComboBox comboBox2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.ComboBox comboBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.GroupBox groupBox3;
        private System.Windows.Forms.Button button5;
        private System.Windows.Forms.Button button4;
        private System.Windows.Forms.GroupBox groupBox4;
        private System.Windows.Forms.Label label8;
        private System.Windows.Forms.TextBox textBox3;
        private System.Windows.Forms.Button button7;
        private System.Windows.Forms.Button button6;
        private System.Windows.Forms.TextBox textBox4;
        private System.Windows.Forms.StatusStrip statusStrip1;
        private System.IO.Ports.SerialPort serialPort1;
    }
}

4.3.2 Form code Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SerialCOMMWindows
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
        }
        private void CheckPort()//检查串口是否可用
        {
    
    
            this.comboBox1.Items.Clear();//清除控件中的当前值
            bool havePort = false;
            string[] names = SerialPort.GetPortNames();
            if (names != null)
            {
    
    

                for (int i = 0; i < names.Length; i++)
                {
    
    
                    bool use = false;
                    try
                    {
    
    
                        SerialPort t = new SerialPort(names[i]);
                        t.Open();
                        t.Close();
                        use = true;
                    }
                    catch
                    {
    
    
                    }
                    if (use)
                    {
    
    
                        this.comboBox1.Items.Add(names[i]);
                        havePort = true;
                    }
                }
            }
            if (havePort)
            {
    
    
                this.comboBox1.SelectedIndex = 0;
            }
            else
            {
    
    
                MessageBox.Show("无可用串口.", "错误");
            }
        }
        private void SetPort()//设置串口
        {
    
    
            try
            {
    
    
                serialPort1.PortName = this.comboBox1.Text.Trim();//串口名给了串口类
                serialPort1.BaudRate = Convert.ToInt32(this.comboBox2.Text.Trim());//Trim除去前后空格,讲文本转换为32位字符给予串口类
                if (this.comboBox4.Text.Trim() == "奇校验")
                {
    
    
                    serialPort1.Parity = Parity.Odd;//将奇校验位给了serialPort1的协议
                }
                else if (this.comboBox4.Text.Trim() == "偶校验")
                {
    
    
                    serialPort1.Parity = Parity.Even;
                }
                else
                {
    
    
                    serialPort1.Parity = Parity.None;
                }
                if (this.comboBox3.Text.Trim() == "1.5")
                {
    
    
                    serialPort1.StopBits = StopBits.OnePointFive;//设置停止位有几位
                }
                else if (this.comboBox3.Text.Trim() == "2")
                {
    
    
                    serialPort1.StopBits = StopBits.Two;
                }
                else
                {
    
    
                    serialPort1.StopBits = StopBits.One;
                }
                serialPort1.DataBits = Convert.ToInt16(this.comboBox5.Text.ToString().Trim());//数据位
                serialPort1.Encoding = Encoding.UTF8;//串口通信的编码格式
                serialPort1.Open();
            }
            catch {
    
     }

        }
        private string HexToASCII(string str)
        {
    
    
            try
            {
    
    
                string[] mystr1 = str.Trim().Split(' ');
                byte[] t = new byte[mystr1.Length];
                for (int i = 0; i < t.Length; i++)
                {
    
    
                    t[i] = Convert.ToByte(mystr1[i], 16);
                }
                return Encoding.UTF8.GetString(t);

            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show("转换失败!" + ex.Message, "错误提示");
                return str;
            }
        }
        private string ASCIIToHex(string my2)
        {
    
    
            try
            {
    
    
                byte[] a = Encoding.UTF8.GetBytes(my2.Trim());
                string mystr1 = "";
                for (int i = 0; i < a.Length; i++)
                {
    
    
                    mystr1 += a[i].ToString("X2") + " ";
                }
                return mystr1;
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show("转换失败!" + ex.Message, "错误提示");
                return my2;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
    
    
            this.comboBox1.Items.Clear();
            CheckPort();
            this.comboBox1.SelectedIndex = 0;
            this.comboBox2.SelectedIndex = 0;
            this.comboBox3.SelectedIndex = 0;
            this.comboBox4.SelectedIndex = 0;
            this.comboBox5.SelectedIndex = 0;
            this.statusStrip1.Text = "";
            this.radioButton1.Checked = true;
        }

        private void button5_Click(object sender, EventArgs e)
        {
    
    
            try
            {
    
    

                Byte[] a = Encoding.UTF8.GetBytes(this.textBox4.Text);
                this.serialPort1.Write(a, 0, a.Length);//写入serialPort1
                this.statusStrip1.Text = "发送成功!";
            }
            catch
            {
    
    
                this.statusStrip1.Text = "发送失败";
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
    
    
            SetPort();
            if (serialPort1.IsOpen)
            {
    
    
                this.statusStrip1.Text = "串口" + this.comboBox1.Text + "已打开!";
            }
            else
            {
    
    
                try
                {
    
    
                    serialPort1.Open();
                    this.statusStrip1.Text = "串口" + this.comboBox1.Text + "打开成功!";
                }
                catch (Exception ex)
                {
    
    
                    MessageBox.Show("串口" + this.comboBox1.Text + "打开失败,失败原因:" + ex.Message, "错误提示");
                    this.statusStrip1.Text = "串口" + this.comboBox1.Text + "打开失败,失败原因:" + ex.Message;
                }
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
    
    
            Thread.Sleep(500);//等待

            this.Invoke((EventHandler)(delegate //异步委托一个线程
            {
    
    
                try
                {
    
    
                    Byte[] a = new Byte[serialPort1.BytesToRead];//读出缓冲区串口通信的字节
                    this.serialPort1.Read(a, 0, a.Length);//写入serialPort1
                    string my2 = Encoding.UTF8.GetString(a);
                    string b = "";
                    if (this.radioButton2.Checked)
                    {
    
    
                        b = ASCIIToHex(my2);
                        this.textBox1.Text += b + "\r\n";
                        this.textBox1.Focus();//获取焦点
                        this.textBox1.Select(this.textBox1.TextLength, 0);//光标定位到文本最后
                        this.textBox1.ScrollToCaret();//滚动到光标处
                        this.statusStrip1.Text = "正在接收数据!";
                    }
                    else
                    {
    
    
                        b = my2;
                        this.textBox1.Text += b + "\r\n";
                        String[] lonandlat = b.Split(',');
                        double temp = Convert.ToDouble(lonandlat[3]);
                        temp = temp / 100.0 - (temp % 100.0) / 100.0 + (temp % 100.0) / 60.0;
                        this.textBox1.Text += "纬度:" + temp;
                        temp = Convert.ToDouble(lonandlat[5]);
                        temp = temp / 100.0 - (temp % 100.0) / 100.0 + (temp % 100.0) / 60.0;
                        this.textBox1.Text += " 经度:" + temp + "\r\n";
                        this.textBox1.Focus();//获取焦点
                        this.textBox1.Select(this.textBox1.TextLength, 0);//光标定位到文本最后
                        this.textBox1.ScrollToCaret();//滚动到光标处
                        this.statusStrip1.Text = "正在接收数据!";
                    }
                }
                catch
                {
    
    
                    this.statusStrip1.Text = "接收失败!";
                }
                this.serialPort1.DiscardInBuffer();
            }));
        }

        private void button4_Click(object sender, EventArgs e)
        {
    
    
            this.textBox1.Text = "";
            this.textBox4.Text = "";
        }

        private void button3_Click(object sender, EventArgs e)
        {
    
    
            try
            {
    
    
                this.serialPort1.Close(); //关闭串口
                this.statusStrip1.Text = "串口" + this.comboBox1.Text + "关闭成功!";
            }
            catch (Exception ex)
            {
    
    
                MessageBox.Show("串口" + this.comboBox1.Text + "关闭失败,错误提示:" + ex.Message, "错误提示");
                this.statusStrip1.Text = "串口" + this.comboBox1.Text + "关闭失败,错误提示:" + ex.Message;
            }
        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {
    
    

        }
    }
}

4.3.3 Program main function code Program.cs (no need to write, automatically generated)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SerialCOMMWindows
{
    
    
    static class Program
    {
    
    
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
    
    
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

4.4 Running results

insert image description here

        After the startup program is running, select the serial port number COM3 in the serial port debugging assistant window, click to open the serial port, and you will see the received GPS data displayed in the text box below the data reception, and the received data will be displayed as sixteen if you select hex display Hexadecimal, the selected character display will display as normal ASCII characters , click to close the serial port to stop receiving data.

insert image description here
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/jing_zhong/article/details/116501779