关于串口编程的(一)

所谓串口,也叫串行接口,即COM口,采用串行通讯方式(即数据一位一位的传送)的接口。也就是电脑后面D形9针插口。
最近做了两个都和串口编程有关的功能,一个是不间断电源,一个是RS232型串口打印机。因为是串口所以主要的用法都不难,难点是对设备的相应命令的理解和使用上。因为不同类型的、不同厂家的设备命令是不同的,因为也没法总一个总结。那就对于串口的简单用法做一些总结吧。
主要用到的类是SerialPort,在System.IO.Ports下。传设备的基本使用步骤如下:
1、设置串口的参数。因为不同的设备对串口的参数要求是不同的,最常见就是波特率,一般好像都是9600。
2、打开串口。也就是SerialPort的Open()方法。
3、想串口写命令或写文本内容。一般情况下,如果是数字类型的命令都是十六进制的,当然也有十进制的,不过如果有十六进制和十进制两种,我觉得最好用十六进制的,因为十六进制好转换为byte数组。
向串口写命令的方法是SerialPort的Write(byte[] buffer, int offset, int count)。比如一个命令,十六进制下:00 FF,十进制下:00 255;那么这段命令最终转为byte[]时,00和FF分别转换,但是对于00和255显然就不怎么方便了。看一下后面的一个例子就明白了。
4,接收返回值。向串口发送命令,有的是指示执行操作的,有的是查询状态的,因此需要读取返回值。
下面对于某一个串口设备的控制,写一个简单的例子。
1、字符操作类,因为串口写入的须要是byte数组型,读出又要将byte数组转为string,一般命令也是十六进制的。所以转换的方法需要用到。
[csharp]  view plain  copy
 print ?
  1. /// <summary>  
  2.    /// 串口字符类  
  3.    /// </summary>  
  4.    public class CharOperated  
  5.    {  
  6.        public static string ByteArrayToHexString(byte[] byteData)  
  7.        {  
  8.            StringBuilder result = new StringBuilder(byteData.Length * 3);  
  9.   
  10.   
  11.            foreach (byte b in byteData)  
  12.            {  
  13.                result.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));  
  14.            }  
  15.   
  16.   
  17.            return result.ToString().ToUpper();  
  18.        }  
  19.   
  20.   
  21.        /// <summary>  
  22.        /// 十六进制的字符串转成byte数组  
  23.        /// </summary>  
  24.        /// <returns></returns>  
  25.        public static byte[] HexStringToByteArray(string content)  
  26.        {  
  27.            content = content.Replace(" """);  
  28.   
  29.   
  30.            byte[] buffer = new byte[content.Length / 2];  
  31.   
  32.   
  33.            for (int i = 0; i < content.Length; i += 2)//因为十六进制命令一般都是两位十六进制一起。  
  34.            {  
  35.                buffer[i / 2] = (byte)Convert.ToByte(content.Substring(i, 2), 16);  
  36.            }  
  37.            return buffer;  
  38.        }  
  39.   
  40.   
  41.        /// <summary>  
  42.        /// 16进制编码的字串解析成 ascii码  
  43.        /// </summary>  
  44.        /// <param name="statusCode"></param>  
  45.        /// <returns></returns>  
  46.        public static string DecodeHexToAsc(string statusCode)  
  47.        {  
  48.            string rtn = "";  
  49.   
  50.   
  51.            statusCode = statusCode.Replace(" """);  
  52.   
  53.   
  54.            for (int i = 0; i < (statusCode.Length / 2); i++)  
  55.            {  
  56.                string key = statusCode.Substring(2 * i, 2);  
  57.   
  58.   
  59.                int asii = Convert.ToInt32(key, 16);//将16进制字符串转换成其ASCII码(实际是Unicode码)  
  60.   
  61.   
  62.                rtn += Chr(asii);  
  63.            }  
  64.   
  65.   
  66.            return rtn;  
  67.        }  
  68.   
  69.   
  70.        /// <summary>  
  71.        /// ascii码转字符  
  72.        /// </summary>  
  73.        /// <param name="asciiCode"></param>  
  74.        /// <returns></returns>  
  75.        public static string Chr(int asciiCode)  
  76.        {  
  77.            if (asciiCode >= 0 && asciiCode <= 255)  
  78.            {  
  79.                System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();  
  80.   
  81.   
  82.                byte[] byteArray = new byte[] { (byte)asciiCode };  
  83.   
  84.   
  85.                string strCharacter = asciiEncoding.GetString(byteArray);  
  86.   
  87.   
  88.                return (strCharacter);  
  89.            }  
  90.   
  91.   
  92.            return string.Empty;  
  93.        }  
  94.    }  
2、对串口的打开,发送命令,关闭等的类。
[csharp]  view plain  copy
 print ?
  1. public class ComManager  
  2.    {  
  3.        private SerialPort comm = null;  
  4.   
  5.   
  6.        private static string currentPortName = string.Empty;  
  7.   
  8.   
  9.        private static object sendCommandLock = new object();  
  10.   
  11.   
  12.        public ComManager(SerialPort comm)  
  13.        {  
  14.            if (this.comm == null)  
  15.            {  
  16.                this.comm = comm;  
  17.            }  
  18.        }  
  19.   
  20.   
  21.        /// <summary>  
  22.        /// 串口参数设定  
  23.        /// </summary>  
  24.        private void SetSerialPort()  
  25.        {  
  26.            //根据设备要求设置参数,比如某一设备要求参数如下:  
  27.            comm.BaudRate = 9600;  
  28.   
  29.   
  30.            comm.Encoding = System.Text.Encoding.GetEncoding("GB2312");  
  31.   
  32.   
  33.            comm.RtsEnable = true;  
  34.        }  
  35.   
  36.   
  37.        /// <summary>  
  38.        /// 打开串口设备  
  39.        /// </summary>  
  40.        private void SerialPortOpen()  
  41.        {  
  42.            try  
  43.            {  
  44.                if (comm.IsOpen)  
  45.                {  
  46.                    comm.Close();  
  47.                }  
  48.   
  49.   
  50.                currentPortName = "COM1";//此处可指定串口,也可以实时读取设备到底连接在那个串口,实际情况根据设备情况而定。  
  51.   
  52.   
  53.                //currentPortName = DoGetUPSPortName();以某一设备为例遍历所有串口,找到连接该设备的串口  
  54.   
  55.   
  56.                SetSerialPort();  
  57.   
  58.   
  59.                if (string.IsNullOrEmpty(currentPortName))  
  60.                {  
  61.                    return;  
  62.                }  
  63.   
  64.   
  65.                comm.PortName = currentPortName;  
  66.   
  67.   
  68.                comm.Open();  
  69.            }  
  70.            catch  
  71.            {  
  72.            }  
  73.        }  
  74.   
  75.   
  76.        /// <summary>  
  77.        /// 向串口发送命令  
  78.        /// </summary>  
  79.        /// <param name="sendstring"></param>  
  80.        public void SendDatastring(string sendstring)  
  81.        {  
  82.            lock (sendCommandLock)  
  83.            {  
  84.                //16进制转二进制  
  85.                byte[] data = CharOperated.HexStringToByteArray(sendstring);  
  86.   
  87.   
  88.                //打开口串口设备  
  89.                SerialPortOpen();  
  90.                //发送命令到串口设备  
  91.                if (comm.IsOpen)  
  92.                {  
  93.                    comm.DiscardInBuffer();  
  94.   
  95.   
  96.                    comm.Write(data, 0, data.Length);  
  97.                }  
  98.            }  
  99.        }  
  100.   
  101.   
  102.        /// <summary>  
  103.        /// 向串口写字符串  
  104.        /// </summary>  
  105.        /// <param name="sendstring"></param>  
  106.        public void WriteLingContent(string content)  
  107.        {  
  108.            lock (sendCommandLock)  
  109.            {  
  110.                //打开口串口设备  
  111.                SerialPortOpen();  
  112.                //发送报文到串口设备  
  113.                if (comm.IsOpen)  
  114.                {  
  115.                    comm.WriteLine(content);  
  116.   
  117.   
  118.                    comm.DiscardInBuffer();  
  119.                }  
  120.            }  
  121.        }  
  122.   
  123.   
  124.        /// <summary>  
  125.        /// 读取端口返回值  
  126.        /// </summary>  
  127.        /// <returns></returns>  
  128.        private string DoReadPortResult()  
  129.        {  
  130.            string resultString = string.Empty;  
  131.            try  
  132.            {  
  133.                int bytes = comm.BytesToRead;  
  134.   
  135.   
  136.                byte[] buffer = new byte[bytes];  
  137.   
  138.   
  139.                comm.Read(buffer, 0, bytes);  
  140.   
  141.   
  142.                string rtnStrPort = CharOperated.ByteArrayToHexString(buffer);  
  143.   
  144.   
  145.                resultString = CharOperated.DecodeHexToAsc(rtnStrPort);  
  146.   
  147.   
  148.                if (comm.IsOpen)  
  149.                {  
  150.                    comm.DiscardInBuffer();  
  151.                }  
  152.            }  
  153.            catch  
  154.            {  
  155.            }  
  156.            return resultString;  
  157.        }  
  158.   
  159.   
  160.        /// <summary>  
  161.        /// 获取某一设备的端口号  
  162.        /// </summary>  
  163.        /// <returns></returns>  
  164.        private string DoGetUPSPortName()  
  165.        {  
  166.            string commName = string.Empty;  
  167.   
  168.   
  169.            try  
  170.            {  
  171.                Computer localComputer = new Computer();  
  172.   
  173.   
  174.                foreach (string portItem in localComputer.Ports.SerialPortNames)  
  175.                {  
  176.                    try  
  177.                    {  
  178.                        if (string.IsNullOrEmpty(portItem))  
  179.                        {  
  180.                            continue;  
  181.                        }  
  182.   
  183.   
  184.                        commName = portItem;  
  185.   
  186.   
  187.                        byte[] data = CharOperated.HexStringToByteArray("发送的命令");  
  188.   
  189.   
  190.                        comm.Close();  
  191.   
  192.   
  193.                        SetSerialPort();  
  194.   
  195.   
  196.                        comm.PortName = portItem;  
  197.   
  198.   
  199.                        comm.Open();  
  200.   
  201.   
  202.                        //发送报文到串口设备  
  203.                        if (comm.IsOpen)  
  204.                        {  
  205.                            comm.DiscardInBuffer();  
  206.   
  207.   
  208.                            comm.Write(data, 0, data.Length);  
  209.                        }  
  210.   
  211.   
  212.                        Thread.Sleep(500);  
  213.   
  214.   
  215.                        //if (条件)  
  216.                        //{  
  217.   
  218.   
  219.                        //}  
  220.                        //else  
  221.                        //{  
  222.                        //    commName = string.Empty;  
  223.                        //}  
  224.                    }  
  225.                    catch  
  226.                    {  
  227.                    }  
  228.                    finally  
  229.                    {  
  230.                        if (comm.IsOpen)  
  231.                        {  
  232.                            comm.Close();  
  233.                        }  
  234.                    }  
  235.                }  
  236.            }  
  237.            catch  
  238.            {  
  239.            }  
  240.            finally  
  241.            {  
  242.                if (comm.IsOpen)  
  243.                {  
  244.                    comm.Close();  
  245.                }  
  246.            }  
  247.   
  248.   
  249.            return commName;  
  250.        }  
  251.    }  
使用
[csharp]  view plain  copy
 print ?
  1. class Program  
  2.     {  
  3.         private static SerialPort serialPortCom = new SerialPort();//串口定义 。  
  4.   
  5.   
  6.         private static string receiveResult = string.Empty; //接收数据。  
  7.   
  8.   
  9.         static void Main(string[] args)  
  10.         {  
  11.             ComManager cm = new ComManager(serialPortCom);  
  12.   
  13.   
  14.             cm.SendDatastring("00FF");//命令  
  15.   
  16.   
  17.             cm.WriteLingContent("内容");  
  18.   
  19.   
  20.             Thread.Sleep(200);//停几百毫秒,然后读取  
  21.   
  22.   
  23.             string result = SerialPortComDataReceived();  
  24.         }  
  25.   
  26.   
  27.         private static string SerialPortComDataReceived()  
  28.         {  
  29.             if (serialPortCom == null || !serialPortCom.IsOpen)  
  30.             {  
  31.                 return string.Empty;  
  32.             }  
  33.   
  34.   
  35.             int bytes = serialPortCom.BytesToRead;  
  36.   
  37.   
  38.             byte[] buffer = new byte[bytes];  
  39.   
  40.   
  41.             serialPortCom.Read(buffer, 0, bytes);  
  42.   
  43.   
  44.             receiveResult = string.Empty;  
  45.   
  46.   
  47.             receiveResult = CharOperated.ByteArrayToHexString(buffer);  
  48.   
  49.   
  50.             receiveResult = receiveResult.Trim();  
  51.   
  52.   
  53.             return receiveResult;  
  54.         }  
  55.     }  
详细代码下载: http://download.csdn.net/detail/yysyangyangyangshan/5516631

你可能感兴趣的:(C++,通讯,串口编程)