zoukankan      html  css  js  c++  java
  • 使用线程接收串口接收数据,DLT645 2007 智能电表抄表代码

    用线程是一种方式,也可以用自带的组件是异步的,如果不用组件用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("奇偶校验错误!
    ");
                            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("
    ");
                        }
                        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("
    ");
                        }                    
                        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("
    ");
                    }                
                    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;            
            }
    
        }
    }

  • 相关阅读:
    python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类
    python中将函数赋值给变量时需要注意的一些问题
    python获得命令行输入的参数
    Python实现语音识别和语音合成
    pymysql
    Matplotlib
    级联,映射
    处理丢失数据
    Numpy,Pandas,Matplotlib
    crawlSpider,分布式爬虫,增量式爬虫
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317559.html
Copyright © 2011-2022 走看看