C#编程简单模拟与下位机的串口通信

在学校里的团队里,遇到需要与下位机实现串口通信的项目,假期里查了很多资料,在此发一篇加深一下印象

需要:
电脑,vs软件(visual studio 2010)
Serial Port Tester(串口调试工具)
友善串口调试助手(选择添加COM1和COM2)

Serial Port Tester串口调试助手
第一步
打开文件,新建,项目
在这里插入图片描述
选择Windows窗体应用程序,随意命名
在这里插入图片描述点击视图,选择工具箱(找到button,和serialport,拖动到窗体上)
在这里插入图片描述
鼠标右键点击serialport,查看属性,默认值不改变(可以自己更改,选择可用串口);再双击button1进入
在这里插入图片描述
在button1点击事件中写简单代码,调试运行,再打开串口助手选择asc2接收(注意,虚拟串口成对出现,这里是COM1和COM2,且目前只能发送一次,多点会出错,后面用try catch 解决)

serialport1.Open();
string str ="easy";
serialport1.write(str);

在这里插入图片描述第二步
退出运行后,继续添加控件,并在属性栏中修改控件名称和控件显示的文本(如将button1改为buttonOpen)
在这里插入图片描述
再修改代码,使可以关闭串口,和将文本框的字符发送的功能
在这里插入图片描述
第三步
添加接收文本框,修改名称后将属性设置为多行,垂直滚动
在这里插入图片描述
双击进入serialport属性里的datareceive事件
在这里插入图片描述
在datareceived事件里编写代码,遇到跨线程错误后,在Form1里加入一句代码,使不进行跨线程检查

string str =serialport1.ReadExisisting();
textBoxReceive.AppendText(str);

在这里插入图片描述
在form1里添加代码后,用串口助手发送asc2数据,接收文本框显示接收到的数据(还不能发汉字)

 public Form1()
        {
            InitializeComponent();
           //防止跨线程错误
			System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;     
        }

在这里插入图片描述
到现在的,基本的发送接收已经完成了,但是可能会出现很多问题,比如说:串口可能多次打开会出错,无法发送和接收文字,无法像助手一样选择发送接收模式…所以继续优化,问题慢慢解决
第四步
添加串口,波特率下拉框,并编辑内容
在这里插入图片描述
添加panel容器并往容器上加单选框,更改属性名称和文本
在这里插入图片描述
再在打开按钮上加上try catch 语句,避免运行过程中死机,在form1load再给控件初始化

private void Form1_Load(object sender, EventArgs e)
        {
            radioButtonReceiveHex.Checked = true;         //接收单选框默认值为Hex
            radioButtonSendHex.Checked = true;            //发送单选框默认值为Hex
            comboBox1.Text = "COM1";                      //默认值
            comboBox2.Text = "9600";
        }

再对发送和接收事件进行优化,可选择Asc2和Hex模式(代码在最后)
在这里插入图片描述
在这里插入图片描述
再在form1中改变串口接送的编码,实现汉字转化
在这里插入图片描述

   serialPort1.Encoding = Encoding.GetEncoding("GB2312");                         		

在这里插入图片描述
此时的程序与下位机匹配时,即可实现简单的数据通讯了
本次的完整代码如下
*Form1

 public Form1()
        {
            InitializeComponent();
             //串口接收编码   
            serialPort1.Encoding = Encoding.GetEncoding("GB2312");                         
			//防止跨线程错误
			System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;     
        }

Form1_Load

private void Form1_Load(object sender, EventArgs e)
        {
            radioButtonReceiveHex.Checked = true;         //默认值为Hex
            radioButtonSendHex.Checked = true;            //默认值为Hex
            comboBox1.Text = "COM1";                      //默认值
            comboBox2.Text = "9600";
        }

打开按钮事件

private void buttonOpen_Click(object sender, EventArgs e)
        {
            if (buttonOpen.Text == "打开串口")//判断文字
            {
                try                                                              //尝试以下代码,未能完全执行就执行catch 
                {
                    serialPort1.PortName = comboBox1.Text;                    //将串口文本框的COM值传给serialport
                    serialPort1.BaudRate = Convert.ToInt16(comboBox2.Text);   //j将波特率文本框的值转成数字给serialport
                    serialPort1.Close();                                        //关闭串口
                    serialPort1.Open();                                       //打开串口,若未打开,则不往下执行   
                    buttonOpen.Text = "关闭串口";                           //将按钮文本"打开串口"改为"关闭串口"
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.ToString(), "错误");//弹出消息提示
                }
            }
            else
            {
                serialPort1.Close();                         //关闭串口
                buttonOpen.Text = "打开串口";               //将按钮文本"关闭串口"改为"打开串口"
            }
        }

串口接收事件

 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            if (radioButtonReceiveAsc2.Checked)                             //如果接收模式为字符模式
            {
                string str = serialPort1.ReadExisting();                    //字符串方式读
                textBoxReceive.AppendText(str);                             //将接收文本添加到文本框中
            }
            else                                                            //如果接收模式为数值接收
            { 
                byte data;
                data = (byte)serialPort1.ReadByte();                      //此处需要强制类型转换,将(int)类型数据转换为(byte类型数据,不必考虑是否会丢失数据
                string str = Convert.ToString(data, 16).ToUpper();        //转换为大写十六进制字符串
                textBoxReceive.AppendText("0x" + (str.Length == 1 ? "0" + str : str) + " ");//空位补“0”   
                //上一句等同为:if(str.Length == 1)
                //                  str = "0" + str; 
                //              else 
                //                  str = str;
                //              textBox1.AppendText("0x" + str);
            }
        }  

发送按钮的事件

private void buttonSend_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                if (radioButtonSendAsc2.Checked)//如果发送模式是字符模式
                {
                    serialPort1.WriteLine(textBoxSend.Text);//写数据
                }
                else
                {
                    try
                    {
                        byte[] Data = new byte[1];                                            //用于缓存
                        for (int i = 0; i < (textBoxSend.Text.Length - textBoxSend.Text.Length % 2) / 2; i++)//取余3运算作用是防止用户输入的字符为奇数个
                            {
                            Data[0] = Convert.ToByte(textBoxSend.Text.Substring(i * 2, 2), 16);
                            serialPort1.Write(Data, 0, 1);                                  //循环发送(如果输入字符为0A0BB,则只发送0A,0B)
                        }
                        if (textBoxSend.Text.Length % 2 != 0)//剩下一位单独处理
                        {
                            Data[0] = Convert.ToByte(textBoxSend.Text.Substring(textBoxSend.Text.Length - 1, 1), 16);//单独发送B(0B)
                            serialPort1.Write(Data, 0, 1);                                      //发送
                        }
                    }
                    catch(Exception err)
                    {
                        MessageBox.Show(err.ToString(), "错误");//出错提示
                        serialPort1.Close();
                        buttonOpen.Text = "打开串口";               //将按钮文本"关闭串口"改为"打开串口"
                    }
                }
            }
		}

最后的话,自己定义一套通讯协议,与相应的下位机连接试试吧!

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值