qq_28684017
背过手!
采纳率60%
2016-08-05 02:47 阅读 2.0k

C#串口通信问题,两个串口间互发信息

10

一个串口com1向另一个串口com2发信息 比如发1-10之间的任意一个数,com2接收到后就会回复a ,11-20之间的数,com2就会回复b 以此类推 ,如果没回复,则com1继续向com2重复发。请大神们给个思路,或者最好是参考代码,谢谢

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

2条回答 默认 最新

  • songhtao 我不懂电脑 2016-08-05 03:05

    C#非常的强大而且友好,串口的通信可以通过编程环境(这里我用的是Visual Studio 2010),如果有需要的话可以给我信息,我有完整版的安装包。如下图,简单的调用和选择就完成了串口的基本配置。

    下面主要就是编程的问题了,在窗体Load的进程中可以完成串口的启动

    复制代码
    1 private void Form1_Load(object sender, EventArgs e)
    2 {
    3 serialPort1.PortName = "COM4";
    4 serialPort1.BaudRate = 9600;
    5 serialPort1.Open();
    6 this.textBox1.Clear();
    7 thread = new Thread(CrossThreadFlush);
    8 thread.IsBackground = true;
    9 thread.Start();
    10 }
    复制代码
    而后就是读取数据的操作,这时候用到事件

    1 private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

    在这个事件里面编程就可以了,但是在对窗体内文本进行操作的时候会发现出现了线程的冲突和错误。网上给出的一种解决方法是采用代理的方式具体的程序如下

    复制代码
    1 public partial class Form1 : Form
    2 {
    3 private delegate void FlushClient(); //代理
    4 Thread thread = null;
    5 uint DateTemp;
    6 uint Datefalg = 0;
    7 uint counter = 0;
    8 uint DateTemp1 = 0;
    9 uint TMP1;
    10 uint RH1;
    11 uint PRESS1;
    12 double TMP;
    13 double RH;
    14 double PRESS;
    15
    16 public Form1()
    17 {
    18 InitializeComponent();
    19 }
    20
    21
    22 private void Form1_Load(object sender, EventArgs e)
    23 {
    24 serialPort1.PortName = "COM4";
    25 serialPort1.BaudRate = 9600;
    26 serialPort1.Open();
    27 this.textBox1.Clear();
    28 thread = new Thread(CrossThreadFlush);
    29 thread.IsBackground = true;
    30 thread.Start();
    31 }
    32
    33

    34 private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    35 {
    36 counter=counter+1;
    37 DateTemp = (uint)this.serialPort1.ReadByte();
    38 if (DateTemp == 0xF1)
    39 {
    40 Datefalg = 1;
    41 DateTemp1 = 0;
    42 DateTemp = 0;
    43 counter=0;
    44 }
    45 if (DateTemp == 0xF2)
    46 {
    47 Datefalg = 2;
    48 DateTemp1 = 0;
    49 DateTemp = 0;
    50 counter=0;
    51 }
    52 if (DateTemp == 0xF3)
    53 {
    54 Datefalg = 3;
    55 DateTemp1 = 0;
    56 DateTemp = 0;
    57 counter=0;
    58 }
    59 if (Datefalg == 1 && DateTemp != 0xF1)
    60 { if(counter==1)
    61 DateTemp1 = DateTemp;
    62 if (counter == 2)
    63 {
    64 TMP1 = DateTemp1 * 256 + DateTemp;
    65 TMP = (0.01 * TMP1) - 40;
    66 }
    67

    68 }
    69 if (Datefalg == 2 && DateTemp != 0xF2)
    70 {
    71 if (counter == 1)
    72 DateTemp1 = DateTemp;
    73 if (counter == 2)
    74 {
    75 RH1 = DateTemp1 * 256 + DateTemp;
    76 RH = (0.0405 * RH1) - 4-0.0000028*RH1*RH1;
    77 }
    78
    79 }
    80 if (Datefalg == 3 && DateTemp != 0xF3)
    81 {
    82 if (counter == 1)
    83 DateTemp1 = DateTemp;
    84 if (counter == 2)
    85 {
    86 PRESS1 = DateTemp1 * 256 + DateTemp;
    87 PRESS = (PRESS1-16384)*90/16384 + 30;
    88 }
    89 }
    90 }
    91
    92 private void CrossThreadFlush()
    93 {
    94 while (true)
    95 {
    96 //将sleep和无限循环放在等待异步的外面
    97 Thread.Sleep(500);
    98 ThreadFunction();
    99 }
    100 }
    101

    102 private void ThreadFunction()
    103 {
    104 if (this.textBox1.InvokeRequired)//等待异步
    105 {
    106 FlushClient fc = new FlushClient(ThreadFunction);
    107 this.Invoke(fc); //通过代理调用刷新方法
    108

    109 }
    110 else
    111 textBox1.Text = TMP.ToString("0.00");
    112 if (this.textBox2.InvokeRequired)//等待异步
    113 {
    114 FlushClient fc = new FlushClient(ThreadFunction);
    115 this.Invoke(fc); //通过代理调用刷新方法
    116
    117 }
    118 else
    119 textBox2.Text = RH.ToString("0.00");
    120 if (this.textBox3.InvokeRequired)//等待异步
    121 {
    122 FlushClient fc = new FlushClient(ThreadFunction);
    123 this.Invoke(fc); //通过代理调用刷新方法
    124
    125 }
    126 else
    127 textBox3.Text = PRESS.ToString("0.00");
    128

    129 }
    130

    131

    132 }
    复制代码
    通过这样的一番调试之后才得以程序正确的运行,由于工科程序员和计算机程序员的编程思想还是有差别的,所以写的不好的地方请轻喷。

    点赞 评论 复制链接分享
  • feng1790291543 鱼弦 2016-08-05 03:36

    多线程处理串口的倒是没有,DEMO代码倒是有,你搜下 ThreadPool.QueueUserWorkItem 这个东西吧
    var doEvents = new ManualResetEvent[threadCount];
    for (var i = 0; i < threadCount; i++)
    {
    doEvents[i] = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(new WaitCallback(DealData), new object[] { i, doEvents[i] });
    }
    WaitHandle.WaitAll(doEvents);
    public void DealData(object eventParams) {

    var threadId = (int)(((object[])eventParams)[0]); //当前线程ID

    var doEvent = (ManualResetEvent)(((object[])eventParams)[1]);

    var perThreadCount = dataTable.Rows.Count / threadCount; //平均每个线程处理数据
    for (int i = 0; i < dataTable.Rows.Count; i++) {

          if (i < (threadId) * perThreadCount) continue;
    if ((i >= (threadId + 1) * perThreadCount) && threadId != (threadCount - 1)) break;
    ImportData(dataTable.Rows[i]);

    }

    doEvent.Set();

    }

    2 、

    SerialPort类 的介绍
    http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(v=vs.80).aspx

    这个例子网上有,哎....我一直以为 serailport 不是一个控件呢!
    我现在疑问?_难道 所有的再c#可以引用的类,都对应一个控件吗?

    还有c#的添加监听器的方法,该如何添加呢?
    如果是控件的话,直接双击控件就可以添加上监听器,但是对于一般的对象的话就得
    用+=这个方法添加....还没怎么看c#,慢慢来

    关于这个程序是有bug的,而且我也没有修正,因为串口对象的 readline是个阻塞方法,所以当你运行到这个语句的时候,如果读不到数据的话就会导致整个程序假死,只能强制终止 这个程序了

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;//新调用的类所在的命名空间

    namespace 串口控制
    {
    public partial class Form1 : Form
    {
    //我用了控件,所以不用初始化对象了!!
    //SerialPort sPort;//声明一个串口类对象,该对象的初始化我放到了

        public Form1() 
        { 
            InitializeComponent(); 
    
    
        } 
    
        //发送按钮的响应时间 
        private void button1_Click(object sender, EventArgs e) 
        { 
    
            //对于中文的话,要先对其进行编码,将其转换成 _Base64String ,否则你得不到中文字符串的 
            byte[] data = Encoding.Unicode.GetBytes(textBox1.Text); 
            string str = Convert.ToBase64String(data); 
            sPort.WriteLine(str); 
            MessageBox.Show("数据发送成功","系统提示"); 
    
        } 
    
        private void button2_Click(object sender, EventArgs e) 
        { 
    
            //解码然后将字符串赋值给 文本框的 文本区 
            byte[] data = Convert.FromBase64String(sPort.ReadLine()); 
            textBox2.Text = Encoding.Unicode.GetString(data); 
    
        } 
    
        private void Form1_Load(object sender, EventArgs e) 
        { 
    
            sPort.PortName = "com3";//串口的portname 
            sPort.BaudRate = 9600;//串口的波特率 
            sPort.Open(); 
        } 
    
        private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
        { 
           //关闭串口 
            sPort.Close(); 
        } 
    
    
    } 
    

    }

    
    
    点赞 评论 复制链接分享

相关推荐