用线程是一种方式,也可以用自带的组件是异步的,如果不用组件用API写串口,应该启用两个线程,用作读写。
以下代码是可以用来学习的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1 mainform;
public Form2 f;
private bool show_or_not = true; //是否显示接收和发送
private byte[] send = new byte[50]; //要发送的字节
private byte[] receive = new byte[50]; //要接收的字节
private byte sendnum; //需要发送的数据个数
private byte receivenum; //需要返回的数据个数
Thread trd; //开一个线程
private delegate void DelegateFunciton();
public Form1()
{
InitializeComponent();
}
private void CreateHeadersAndFillListview()
{
listView1.Columns.Add("数据大小", 77, HorizontalAlignment.Left);
listView1.Columns.Add("数据项名称",140, HorizontalAlignment.Left);
listView1.Columns.Add("标识编码", 75, HorizontalAlignment.Right);
}
private void PaintListView()
{
listView1.BeginUpdate();
listView1.Items.Add("0", "00001234", 0);
listView1.Items[0].SubItems.Add("正向有功功率");
listView1.Items[0].SubItems.Add("0x9010");
listView1.Items.Add("1", "00001234", 0);
listView1.Items[1].SubItems.Add("费率1正向有功功率");
listView1.Items[1].SubItems.Add("0x9011");
listView1.Items.Add("2", "00001234", 0);
listView1.Items[2].SubItems.Add("费率2正向有功功率");
listView1.Items[2].SubItems.Add("0x9012");
listView1.Items.Add("3", "00001234", 0);
listView1.Items[3].SubItems.Add("费率3正向有功功率");
listView1.Items[3].SubItems.Add("0x9013");
listView1.Items.Add("4", "00001234", 0);
listView1.Items[4].SubItems.Add("费率4正向有功功率");
listView1.Items[4].SubItems.Add("0x9014");
listView1.Items.Add("5", "00001234", 0);
listView1.Items[5].SubItems.Add("反向有功功率");
listView1.Items[5].SubItems.Add("0x9020");
listView1.Items.Add("6", "00001234", 0);
listView1.Items[6].SubItems.Add("费率1反向有功功率");
listView1.Items[6].SubItems.Add("0x9021");
listView1.Items.Add("7", "00001234", 0);
listView1.Items[7].SubItems.Add("费率2反向有功功率");
listView1.Items[7].SubItems.Add("0x9022");
listView1.Items.Add("8", "00001234", 0);
listView1.Items[8].SubItems.Add("费率3反向有功功率");
listView1.Items[8].SubItems.Add("0x9023");
listView1.Items.Add("9", "00001234", 0);
listView1.Items[9].SubItems.Add("费率4反向有功功率");
listView1.Items[9].SubItems.Add("0x9024");
listView1.Items.Add("10", "00001234", 0);
listView1.Items[10].SubItems.Add("反向无功功率");
listView1.Items[10].SubItems.Add("0x9120");
listView1.Items.Add("11", "00001234", 0);
listView1.Items[11].SubItems.Add("费率1反向无功功率");
listView1.Items[11].SubItems.Add("0x9121");
listView1.Items.Add("12", "00001234", 0);
listView1.Items[12].SubItems.Add("费率2反向无功功率");
listView1.Items[12].SubItems.Add("0x9122");
listView1.Items.Add("13", "00001234", 0);
listView1.Items[13].SubItems.Add("费率3反向无功功率");
listView1.Items[13].SubItems.Add("0x9123");
listView1.Items.Add("14", "00001234", 0);
listView1.Items[14].SubItems.Add("费率4反向无功功率");
listView1.Items[14].SubItems.Add("0x9124");
listView1.Items.Add("15", "00001234", 0);
listView1.Items[15].SubItems.Add("瞬时有功功率");
listView1.Items[15].SubItems.Add("0xB630");
listView1.Items.Add("16", "00001234", 0);
listView1.Items[16].SubItems.Add("A相有功功率");
listView1.Items[16].SubItems.Add("0xB631");
listView1.Items.Add("17", "00001234", 0);
listView1.Items[17].SubItems.Add("B相有功功率");
listView1.Items[17].SubItems.Add("0xB632");
listView1.Items.Add("18", "00001234", 0);
listView1.Items[18].SubItems.Add("C相有功功率");
listView1.Items[18].SubItems.Add("0xB633");
listView1.Items.Add("19", "00001234", 0);
listView1.Items[19].SubItems.Add("瞬时无功功率");
listView1.Items[19].SubItems.Add("0xB640");
listView1.Items.Add("20", "00001234", 0);
listView1.Items[20].SubItems.Add("A相无功功率");
listView1.Items[20].SubItems.Add("0xB641");
listView1.Items.Add("21", "00001234", 0);
listView1.Items[21].SubItems.Add("B相无功功率");
listView1.Items[21].SubItems.Add("0xB642");
listView1.Items.Add("22", "00001234", 0);
listView1.Items[22].SubItems.Add("C相无功功率");
listView1.Items[22].SubItems.Add("0xB643");
listView1.Items.Add("23", "1234", 0);
listView1.Items[23].SubItems.Add("A相电压");
listView1.Items[23].SubItems.Add("0xB611");
listView1.Items.Add("24", "1234", 0);
listView1.Items[24].SubItems.Add("B相电压");
listView1.Items[24].SubItems.Add("0xB612");
listView1.Items.Add("25", "1234", 0);
listView1.Items[25].SubItems.Add("C相电压");
listView1.Items[25].SubItems.Add("0xB613");
listView1.Items.Add("26", "1234", 0);
listView1.Items[26].SubItems.Add("A相电流");
listView1.Items[26].SubItems.Add("0xB621");
listView1.Items.Add("27", "1234", 0);
listView1.Items[27].SubItems.Add("B相电流");
listView1.Items[27].SubItems.Add("0xB622");
listView1.Items.Add("28", "1234", 0);
listView1.Items[28].SubItems.Add("C相电流");
listView1.Items[28].SubItems.Add("0xB623");
listView1.EndUpdate();
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "关闭串口") //关闭串口
{
button1.Text = "打开串口";
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
trd.Abort();
serialPort1.Close();//关闭串口
}
else if (button1.Text == "打开串口") //打开串口
{
serialPort1.PortName = comboBox1.SelectedItem.ToString();
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);
if (comboBox3.SelectedIndex == 0)
serialPort1.Parity = System.IO.Ports.Parity.Even; //偶校验
else if (comboBox3.SelectedIndex == 1)
serialPort1.Parity = System.IO.Ports.Parity.Odd; //奇校验
else serialPort1.Parity = System.IO.Ports.Parity.None; //无校验
serialPort1.Open();
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
button1.Text = "关闭串口";
trd = new Thread(new ThreadStart(this.ThreadTask));
trd.IsBackground = true;
trd.Start(); //打开线程
}
}
public byte Calculate_Parity(byte[] data, byte num1, byte num2) //num1是FE数量,num2是数组大小,奇偶校验
{
byte i;
byte sum=0;
for (i = num1; i < num2; i++)
sum += data[i];
return sum;
}
public Int32 Get_Item_Index(Int16 DI1_0) //由标识编码得到listview中的item的编号
{
Int16 i;
for (i = 0; (i < listView1.Items.Count) && (Convert.ToInt16(listView1.Items[i].SubItems[2].Text, 16) != DI1_0); i++) ;
if ((i == listView1.Items.Count) && (Convert.ToInt16(listView1.Items[i-1].SubItems[2].Text, 16) != DI1_0))
{
return 10000;//错误
}
else
return i;
}
private void ThreadFunction()
{
richTextBox1.Focus();
}
private void ThreadTask() //独立线程
{
byte i,FE_num,err;
UInt16 temp;
Int32 temp1;
Int16 DL745_DI; //DL645标识编码
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
richTextBox1.BackColor = Color.Black;
while (true)
{
DelegateFunciton df = new DelegateFunciton(ThreadFunction);
while (serialPort1.BytesToRead == 0)
{
//richTextBox1.Focus();
//comboBox6.Focus();
//comboBox6.SelectedIndex = 2;
this.Invoke(df);
Thread.Sleep(50); //延时50ms
}
Thread.Sleep(50); //延时50ms
FE_num = 0;
i = 0;
receivenum = (byte)serialPort1.BytesToRead;
serialPort1.Read(receive, 0, serialPort1.BytesToRead);
while (receive[i] == 0xFE)
FE_num++;
err = Calculate_Parity(receive, FE_num, (byte)(receivenum - 2));
if (err != receive[receivenum - 2]) //奇偶校验错误
{
if (show_or_not == true) //是否显示
{
richTextBox1.SelectionColor = Color.LawnGreen;
richTextBox1.AppendText("奇偶校验错误!\r\n");
richTextBox1.SelectionColor = Color.White;
richTextBox1.AppendText("接收: ");
for (i = 0; i < receivenum; i++)
{
if (receive[i] < 16)
richTextBox1.AppendText("0" + receive[i].ToString("X") + " "); //按16进制显示
else
richTextBox1.AppendText(receive[i].ToString("X") + " "); //按16进制显示
}
richTextBox1.AppendText("\r\n");
}
temp = Convert.ToUInt16(label5.Text, 10);
temp++;
label5.Text = temp.ToString(); //接收加1
serialPort1.DiscardOutBuffer(); //窗口清零
serialPort1.DiscardInBuffer();
}
else//奇偶校验正确
{
if (show_or_not == true) //是否显示
{
richTextBox1.SelectionColor = Color.White;
richTextBox1.AppendText("接收: ");
for (i = 0; i < receivenum; i++)
{
if(receive[i]<16)
richTextBox1.AppendText("0"+receive[i].ToString("X") + " "); //按16进制显示
else
richTextBox1.AppendText(receive[i].ToString("X") + " "); //按16进制显示
}
richTextBox1.AppendText("\r\n");
}
temp = Convert.ToUInt16(label5.Text, 10);
temp++;
label5.Text = temp.ToString(); //接收加1
DL745_DI = (Int16)receive[11 + FE_num];
DL745_DI -= 0x33;
DL745_DI <<= 8;
DL745_DI += receive[10 + FE_num];
DL745_DI -= 0x33; //解析得到的DL645标识编码
temp1 = Get_Item_Index(DL745_DI); //得到其在listview中对应的位置index
if (temp1 != 10000)
{
send[0] = send[1] = 0xFE; //发两字节的0xFE
for (i = FE_num; i < FE_num + 12; i++)
send[i - FE_num + 2] = receive[i]; //发送的相同字节
send[10] = 0x81;
if (temp1 < 23) //index在23之前的都是4字节
{
send[11] += 4;
send[14] = Convert.ToByte(listView1.Items[temp1].Text.Substring(6, 2), 16);
send[15] = Convert.ToByte(listView1.Items[temp1].Text.Substring(4, 2), 16);
send[16] = Convert.ToByte(listView1.Items[temp1].Text.Substring(2, 2), 16);
send[17] = Convert.ToByte(listView1.Items[temp1].Text.Substring(0, 2), 16);
send[14] += 0x33;
send[15] += 0x33;
send[16] += 0x33;
send[17] += 0x33;
send[18] = Calculate_Parity(send, 2, 18);
send[19] = 0x16;
sendnum = 20;
}
else //2字节
{
send[11] += 2;
send[14] = Convert.ToByte(listView1.Items[temp1].Text.Substring(2, 2), 16);
send[15] = Convert.ToByte(listView1.Items[temp1].Text.Substring(0, 2), 16);
send[14] += 0x33;
send[15] += 0x33;
send[16] = Calculate_Parity(send, 2, 16);
send[17] = 0x16;
sendnum = 18;
}
serialPortSend();//发送
}
richTextBox1.Focus();
}
// richTextBox1.Select(richTextBox1.TextLength, 0);
// richTextBox1.ScrollToCaret(); //richtextbox显示最后一行
}
}
private void listView1_ItemActivate(object sender, EventArgs e)
{
int i =new int();
Form2 f = new Form2();
f.ShowDialog();
if (f.DialogResult == DialogResult.OK)//f2窗口点击OK是要警醒处理的结果
{
i = listView1.SelectedItems[0].Index;
if (i < 23) //index在23之前的都是4字节
{
if (f.datasource.Length > 8)
f.datasource = f.datasource.Substring(0, 8);
listView1.Items[i].Text = f.datasource.ToString().PadLeft(8, '0');//固定长度一个数值,左边补齐0,直到满8个长
}
else
{
if (f.datasource.Length > 4)
f.datasource = f.datasource.Substring(0, 4);
listView1.Items[i].Text = f.datasource.ToString().PadLeft(4, '0');
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = System.IO.Ports.SerialPort.GetPortNames();
byte i = 0;
foreach (string port in ports)
{
comboBox1.Items.Add(port);
i++;
}
if (i > 0)
{
comboBox1.SelectedIndex = 0;
comboBox2.SelectedIndex = 1;
comboBox3.SelectedIndex = 0;
button1.Text = "打开串口";
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
serialPort1.PortName = comboBox1.SelectedItem.ToString();
//label6.Text = "没有打开串口!";
}
comboBox6.SelectedIndex = 0;
CheckForIllegalCrossThreadCalls = false; //线程间调用
trd = new Thread(new ThreadStart(this.ThreadTask));
trd.IsBackground = true;
CreateHeadersAndFillListview();
PaintListView();
}
private void button3_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
label5.Text = "0";
label6.Text = "0";
}
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "停止显示")
{
show_or_not = false;
button2.Text = "继续显示";
}
else
{
show_or_not = true;
button2.Text = "停止显示";
richTextBox1.Focus();
}
}
private void serialPortSend() //串口发送函数
{
byte i;
UInt16 temp;
try
{
serialPort1.Write(send, 0, sendnum); // 要发送的数据个数
if (show_or_not == true) //是否显示
{
richTextBox1.SelectionColor = Color.Yellow;
richTextBox1.AppendText("发送: ");
for (i = 0; i < sendnum; i++)
{
if (send[i] < 16)
richTextBox1.AppendText("0"+send[i].ToString("X") + " "); //16进制显示
else
richTextBox1.AppendText(send[i].ToString("X") + " "); //16进制显示
}
richTextBox1.AppendText("\r\n");
}
temp = Convert.ToUInt16(label6.Text, 10);
temp++;
label6.Text = temp.ToString();
}
catch (System.InvalidOperationException e)
{
MessageBox.Show("通信接口未打开!", "注意!");
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
trd.Abort(); //关掉线程
serialPort1.Close();
}
}
private void button7_Click(object sender, EventArgs e) //串口清零
{
if (serialPort1.IsOpen)
{
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
richTextBox1.Focus(); //让其获得焦点,一直显示最后一行
// comboBox6.Focus();
}
private void comboBox1_Click(object sender, EventArgs e)
{
//Cursor cr = Cursor.Current;
//Cursor.Current = Cursors.WaitCursor;
}
}
}
使用线程接收串口接收数据,DLT645 2007 智能电表抄表代码
转载下一篇:彻底弄懂js循环中的闭包问题
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
C-DLT645电表数据 转IEC61850项目案例
使用VFBOX网关实现DLT645电表数据到IEC61850协议的转换,支持多种协议转换,简化设备间数据交换,节省时间成本,网关稳定可靠,满足工业应用需求。
网关 协议转换 DLT645 IEC61850 VFBOX -
DLT645协议介绍
参考 DLT645协议解析(二) 07
数据帧 读取数据 字节数 -
DLT645电表数据 转 IEC61850项目案例
DLT645电表数据 转 IEC61850项目案例
物联网 网络协议 网络 数据 逻辑设备 -
DLT645电表数据 转IEC104项目案例
DLT645电表数据 转IEC104项目案例
网络协议 物联网 网络 数据 IP