c#通过串口及CAN模块实现上位及下位机通讯

目录

前言

一、串口、CAN总线

二、使用步骤

1.RS232串口通讯(指令下发与接收)

2.CAN总线通讯

总结


 

前言

 学习及工作中我们经常会遇到上位机与下位机通讯等工作,结合场景使用不同的通讯方式实时通讯,以下为工作中遇到的上位机与下位机进行实时通讯,采用RS232串口和CAN总线形式进行网络通讯。


一、串口、CAN总线

串行接口简称串口,也称串行通讯接口或串行通讯接口(通常指设备的COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通讯简单,只要一对传输线,通过设备设置传输线端口等参数就可以实现双向通信,从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。

CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。上位机与与下位机制定好通用协议通过CAN模块将数据进行16进制转换实时通讯。

二、使用步骤

1.RS232串口通讯(指令下发与接收)

代码如下(示例):

//命名空间引入
using System.IO.Ports;
public SerialPort serialPort;//定义串口对象类public
//定义连接方法
public void Connect()
{

       serialPort  = new SerialPort();

       serialPort.BaudRate = 1200;//波特率
       serialPort.PortName = "COM1";
       serialPort.Parity = Parity.None;//校验法:无
       serialPort.DataBits = 8;//数据位:8
       serialPort.StopBits = StopBits.One;//停止位:1
            try
             {
                serialPort.Open();//打开串口
                serialPort.DtrEnable = true;//设置DTR为高电平
                serialPort.RtsEnable = true;//设置RTS位高电平
                serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);//DataReceived事件委托
                byte[] WriteBuffer = Encoding.ASCII.GetBytes("下发指令");
                //下发
                serialPort.Write(WriteBuffer, 0, WriteBuffer.Length);
            }
            catch (Exception ex)
            {
                //打开串口出错,显示错误信息
                Console.WriteLine("串口打开失败");
            }
        }

2.CAN总线通讯

代码如下(示例):

//首先与CAN模块进行连接

        public TcpClient mTcp = new TcpClient();
        private const int READ_BUFFER_SIZE = 1000;
        private byte[] readBuffer = new byte[READ_BUFFER_SIZE + 1];
        public delegate void DoReadEventHandle(object sender, string e);
        public event DoReadEventHandle ReadedEvent;
        public event DoReadEventHandle LogEvent;

        public string recStr { get; set; }
        public string HandString { get; set; }
        public bool Connect()
        {
            //Can模块ip
            string mIPAddress = "192.168.1.1";
            IPAddress hostIPAddress = IPAddress.Parse(mIPAddress);
            //端口
            int mPort = 8080;
            IPEndPoint endIP = new IPEndPoint(hostIPAddress, mPort);
            try
            {
                mTcp = new TcpClient(mIPAddress, mPort);
                DateTime Savetime = DateTime.Now;
                TimeSpan n = new TimeSpan();
                while (true)
                {
                    n = DateTime.Now - Savetime;
                    if (n.TotalMilliseconds > 1000 || mTcp.Client.Connected) break;
                }
                if (!mTcp.Client.Connected) return false;
                mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }
        private void DoRead(IAsyncResult ar)
        {
            try
            {
                int BytesRead = mTcp.GetStream().EndRead(ar);
                if (BytesRead > 0)
                {
                    string s = "";
                    for (int i = 0; i <= BytesRead - 1; i++)
                    {
                        s = s + string.Format("{0:x2}", readBuffer[i]) + " ";
                    }
                    Console.WriteLine(s);
                    var t = s.Split(new string[] { "aa 00 ff 00 00 00 00 00 00 00 00 00 55" },            StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(ex => ex != " ");
                    if (!string.IsNullOrEmpty(t))
                    {
                        recStr += t + "\r\n";
                        if (HandString == recStr && LogEvent != null)
                        {
                            HandString = null;
                            LogEvent(this, "握手成功!");
                        }
                    } mTcp.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, DoRead, null);
                }
            }
            catch (Exception e)
            {
                mTcp.Client.Close();
            }
        }

//数据发送

 public void sendCan(string temperature, bool check)
        {
            HandString = "0xC0 0x02 0x02 0x00 0x00";
            string[] tmp = temperature.Split(' ');
            var buf = new byte[22];

            for (int i = 0; i < buf.Length; i++)
            {
                buf[i] = 0;
            }
            for (int i = 0; i < tmp.Length; i++)
            {
                try
                {
                    buf[i] = Convert.ToByte(tmp[i], 16);
                }
                catch (Exception e)
                {
                    buf[i] = 0;
                }
            }
            SendData(buf, 0, 13, check);
        }

        public bool SendData(byte[] sendBytes, int mStart, int mLen, bool check = true)
        {
            if (!check) return false;
            try
            {
                lock (mTcp.GetStream())
                {
                    mTcp.GetStream().Write(sendBytes, mStart, mLen);
                }
                return true;
            }
            catch (Exception x)
            {
                return false;
            }
        }


总结

1、RS232串口通讯

      接口的信号电平值较高,易损坏接口电路的芯片,传输速率较低,传输距离有限。

2、CAN模块通讯

      具有实时性强、传输距离较远、抗电磁干扰能力强、成本低等优点;可根据报文的内容决定接收或屏蔽该报文;通讯过程信道容易阻塞。

猜你喜欢

转载自blog.csdn.net/weixin_43292039/article/details/108215111
今日推荐