릴레이의 직렬 포트 제어가 필요한 소규모 프로젝트에 참여했기 때문에 지난 이틀 동안 기본적인 직렬 포트 프로그래밍을 배웠습니다. 동료가 JAVA 직렬 통신 패키지를 가지고 있는데 인터넷에서 다운로드한 것인데 상당히 지저분하고 직렬 통신의 과정과 내용을 정확하게 파악하기 어렵습니다. 그래서 온라인 전문가들의 방법을 배우며 직접 C#을 활용한 기본적인 직렬통신 프로그래밍을 구현해보았습니다. 학습 결과는 아래와 같습니다. 모든 분들께 도움이 되기를 바랍니다.
1. 직렬 통신 소개
직렬 인터페이스(직렬 포트)는 CPU에서 받은 병렬 데이터 문자를 연속적인 직렬 데이터 스트림으로 변환하여 동시에 전송할 수 있는 유형입니다. , 수신된 직렬 데이터 스트림은 장치가 병렬 데이터 문자로 변환되어 CPU에 공급될 수 있습니다. 일반적으로 이 기능을 완성하는 회로를 직렬 인터페이스 회로라고 합니다.
직렬 통신의 개념은 매우 간단합니다. 직렬 포트는 비트 단위로 바이트를 보내고 받습니다. 바이트별 병렬 통신보다 속도는 느리지만 직렬 포트는 한 회선에서 데이터를 보내고 다른 회선에서 데이터를 수신할 수 있습니다. 직렬 통신의 가장 중요한 매개변수는 전송 속도, 데이터 비트, 정지 비트 및 패리티입니다. 두 포트가 통신하려면 이러한 매개변수가 일치해야 합니다.
1. 전송 속도(Baud rate): 기호 전송 속도를 측정하는 매개변수입니다. 신호가 변조된 후 단위 시간의 변화, 즉 단위 시간당 반송파 매개 변수 변경 수를 나타냅니다. 예를 들어 초당 960개의 문자가 전송되고 각 문자 형식에는 10비트(1개 시작 비트, 1개)가 포함됩니다. 정지 비트, 8 데이터 비트), 이때 전송 속도는 960Bd, 비트 속도는 10비트 * 960비트/초 = 9600bps입니다.
2. 데이터 비트: 통신 시 실제 데이터 비트를 측정하는 매개변수입니다. 컴퓨터가 정보 패킷을 보낼 때 실제 데이터는 8비트가 아닌 경우가 많습니다. 표준 값은 6, 7, 8비트입니다. 표준 ASCII 코드는 0~127(7비트)이고, 확장 ASCII 코드는 0~255(8비트)입니다.
3. 정지 비트: 단일 패킷의 마지막 몇 비트를 나타내는 데 사용됩니다. 일반적인 값은 1, 1.5, 2비트입니다. 데이터는 전송 라인에서 시간이 측정되고 각 장치에는 자체 시계가 있으므로 통신 중에 두 장치 간에 작은 비동기화가 발생할 수 있습니다. 따라서 정지 비트는 전송의 끝을 나타낼 뿐만 아니라 컴퓨터에 시계 동기화를 수정할 수 있는 기회도 제공합니다.
4. 체크 디지트 : 시리얼 통신에서의 간단한 에러 검출 방식. 오류 감지 모드에는 짝수, 홀수, 높음, 낮음의 네 가지가 있습니다. 물론 체크 숫자가 없을 수도 있습니다.
2. C# 직렬 포트 프로그래밍 클래스
.NET Framework 2.0부터 C#에서는 직렬 포트 제어를 위한 SerialPort 클래스를 제공합니다. 네임스페이스:System.IO.Ports. 자세한 회원 소개는 MSDN 문서를 참고하세요. 다음은 일반적으로 사용되는 필드, 메소드 및 이벤트를 소개합니다.
1. 공통 필드:
Name | Description |
PortName | 통신 포트 가져오기 또는 설정 |
BaudRate | 가져오기 또는 설정 string Line Baud Rate |
DataBits | 바이트당 표준 데이터 비트 길이 가져오기 또는 설정 |
Parity | 패리티 검사 프로토콜 가져오기 또는 설정 |
StopBits | 바이트당 표준 정지 비트 수를 가져오거나 설정합니다 |
2. 일반적으로 사용되는 방법:
Name | Description |
Close | 포트 연결을 닫고 IsOpen을 설정합니다. 속성 false에 대한 속성 및 내부 스트림 객체를 릴리스 |
getportNames | 현재 컴퓨터의 직렬 포트 이름 배열 가져옵니다. |
Read | Read from SerialPort | 입력 버퍼
Write | 직렬 포트 출력 버퍼 |
3. 일반 이벤트:
Name
Description
DataReceived | 데이터 수신 이벤트를 처리할 방법을 나타냅니다. SerialPort | 개체
1 using System; 2 using System.Windows.Forms; 3 using System.IO.Ports; 4 using System.Text; 5 6 namespace Traveller_SerialPortControl 7 { 8 public partial class Form1 : Form 9 { 10 //定义端口类 11 private SerialPort ComDevice = new SerialPort(); 12 public Form1() 13 { 14 InitializeComponent(); 15 InitralConfig(); 16 } 17 /// <summary> 18 /// 配置初始化 19 /// </summary> 20 private void InitralConfig() 21 { 22 //查询主机上存在的串口 23 comboBox_Port.Items.AddRange(SerialPort.GetPortNames()); 24 25 if (comboBox_Port.Items.Count > 0) 26 { 27 comboBox_Port.SelectedIndex = 0; 28 } 29 else 30 { 31 comboBox_Port.Text = "未检测到串口"; 32 } 33 comboBox_BaudRate.SelectedIndex = 5; 34 comboBox_DataBits.SelectedIndex = 0; 35 comboBox_StopBits.SelectedIndex = 0; 36 comboBox_CheckBits.SelectedIndex = 0; 37 pictureBox_Status.BackgroundImage = Properties.Resources.red; 38 39 //向ComDevice.DataReceived(是一个事件)注册一个方法Com_DataReceived,当端口类接收到信息时时会自动调用Com_DataReceived方法 40 ComDevice.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived); 41 } 42 43 /// <summary> 44 /// 一旦ComDevice.DataReceived事件发生,就将从串口接收到的数据显示到接收端对话框 45 /// </summary> 46 /// <param name="sender"></param> 47 /// <param name="e"></param> 48 private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e) 49 { 50 //开辟接收缓冲区 51 byte[] ReDatas = new byte[ComDevice.BytesToRead]; 52 //从串口读取数据 53 ComDevice.Read(ReDatas, 0, ReDatas.Length); 54 //实现数据的解码与显示 55 AddData(ReDatas); 56 } 57 58 /// <summary> 59 /// 解码过程 60 /// </summary> 61 /// <param name="data">串口通信的数据编码方式因串口而异,需要查询串口相关信息以获取</param> 62 public void AddData(byte[] data) 63 { 64 if (radioButton_Hex.Checked) 65 { 66 StringBuilder sb = new StringBuilder(); 67 for (int i = 0; i < data.Length; i++) 68 { 69 sb.AppendFormat("{0:x2}" + " ", data[i]); 70 } 71 AddContent(sb.ToString().ToUpper()); 72 } 73 else if (radioButton_ASCII.Checked) 74 { 75 AddContent(new ASCIIEncoding().GetString(data)); 76 } 77 else if (radioButton_UTF8.Checked) 78 { 79 AddContent(new UTF8Encoding().GetString(data)); 80 } 81 else if (radioButton_Unicode.Checked) 82 { 83 AddContent(new UnicodeEncoding().GetString(data)); 84 } 85 else 86 { 87 StringBuilder sb = new StringBuilder(); 88 for (int i = 0; i < data.Length; i++) 89 { 90 sb.AppendFormat("{0:x2}" + " ", data[i]); 91 } 92 AddContent(sb.ToString().ToUpper()); 93 } 94 } 95 96 /// <summary> 97 /// 接收端对话框显示消息 98 /// </summary> 99 /// <param name="content"></param>100 private void AddContent(string content)101 {102 BeginInvoke(new MethodInvoker(delegate103 { 104 textBox_Receive.AppendText(content); 105 }));106 }107 108 /// <summary>109 /// 串口开关110 /// </summary>111 /// <param name="sender"></param>112 /// <param name="e"></param>113 private void button_Switch_Click(object sender, EventArgs e)114 {115 if (comboBox_Port.Items.Count <= 0)116 {117 MessageBox.Show("未发现可用串口,请检查硬件设备");118 return;119 }120 121 if (ComDevice.IsOpen == false)122 {123 //设置串口相关属性124 ComDevice.PortName = comboBox_Port.SelectedItem.ToString();125 ComDevice.BaudRate = Convert.ToInt32(comboBox_BaudRate.SelectedItem.ToString());126 ComDevice.Parity = (Parity)Convert.ToInt32(comboBox_CheckBits.SelectedIndex.ToString());127 ComDevice.DataBits = Convert.ToInt32(comboBox_DataBits.SelectedItem.ToString());128 ComDevice.StopBits = (StopBits)Convert.ToInt32(comboBox_StopBits.SelectedItem.ToString());129 try130 {131 //开启串口132 ComDevice.Open();133 button_Send.Enabled = true;134 }135 catch (Exception ex)136 {137 MessageBox.Show(ex.Message, "未能成功开启串口", MessageBoxButtons.OK, MessageBoxIcon.Error);138 return;139 }140 button_Switch.Text = "关闭";141 pictureBox_Status.BackgroundImage = Properties.Resources.green;142 }143 else144 {145 try146 {147 //关闭串口148 ComDevice.Close();149 button_Send.Enabled = false;150 }151 catch (Exception ex)152 {153 MessageBox.Show(ex.Message, "串口关闭错误", MessageBoxButtons.OK, MessageBoxIcon.Error);154 }155 button_Switch.Text = "开启";156 pictureBox_Status.BackgroundImage = Properties.Resources.red;157 }158 159 comboBox_Port.Enabled = !ComDevice.IsOpen;160 comboBox_BaudRate.Enabled = !ComDevice.IsOpen;161 comboBox_DataBits.Enabled = !ComDevice.IsOpen;162 comboBox_StopBits.Enabled = !ComDevice.IsOpen;163 comboBox_CheckBits.Enabled = !ComDevice.IsOpen;164 }165 166 167 /// <summary>168 /// 将消息编码并发送169 /// </summary>170 /// <param name="sender"></param>171 /// <param name="e"></param>172 private void button_Send_Click(object sender, EventArgs e)173 {174 if (textBox_Receive.Text.Length > 0)175 {176 textBox_Receive.AppendText("\n");177 }178 179 byte[] sendData = null;180 181 if (radioButton_Hex.Checked)182 {183 sendData = strToHexByte(textBox_Send.Text.Trim());184 }185 else if (radioButton_ASCII.Checked)186 {187 sendData = Encoding.ASCII.GetBytes(textBox_Send.Text.Trim());188 }189 else if (radioButton_UTF8.Checked)190 {191 sendData = Encoding.UTF8.GetBytes(textBox_Send.Text.Trim());192 }193 else if (radioButton_Unicode.Checked)194 {195 sendData = Encoding.Unicode.GetBytes(textBox_Send.Text.Trim());196 }197 else198 {199 sendData = strToHexByte(textBox_Send.Text.Trim());200 }201 202 SendData(sendData);203 }204 205 /// <summary>206 /// 此函数将编码后的消息传递给串口207 /// </summary>208 /// <param name="data"></param>209 /// <returns></returns>210 public bool SendData(byte[] data)211 {212 if (ComDevice.IsOpen)213 {214 try215 {216 //将消息传递给串口217 ComDevice.Write(data, 0, data.Length);218 return true;219 }220 catch (Exception ex)221 {222 MessageBox.Show(ex.Message, "发送失败", MessageBoxButtons.OK, MessageBoxIcon.Error);223 }224 }225 else226 {227 MessageBox.Show("串口未开启", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);228 }229 return false;230 }231 232 /// <summary>233 /// 16进制编码234 /// </summary>235 /// <param name="hexString"></param>236 /// <returns></returns>237 private byte[] strToHexByte(string hexString)238 {239 hexString = hexString.Replace(" ", "");240 if ((hexString.Length % 2) != 0) hexString += " ";241 byte[] returnBytes = new byte[hexString.Length / 2];242 for (int i = 0; i < returnBytes.Length; i++)243 returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 16);244 return returnBytes;245 }246 247 //以下两个指令是结合一款继电器而设计的248 private void button_On_Click(object sender, EventArgs e)249 {250 textBox_Send.Text = "005A540001010000B0";251 }252 253 private void button_Off_Click(object sender, EventArgs e)254 {255 textBox_Send.Text = "005A540002010000B1";256 }257 }258 }
소프트웨어는 기본 인터페이스를 구현합니다
위 내용은 C# 직렬 통신 예제 튜토리얼의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!