手持嵌入式wince6.0串口通信调试

嵌入式wince 专栏收录该内容
1 篇文章 0 订阅

 前几天在手持的wince设备上进行调试串口通信,着实让人挠头啊,串口能打开也能关闭,但就是收发数据不行,搞了好长时间,才发现,是硬件连接有问题。

 

我用的是vs2008+C#,系统跑的是wince6.0,用C#开发串口通信其实最简单的就是直接拖控件,很方便,但欠缺灵活性,这里就不说了,我用代码实现的串口程序如下:

已经跑通,可以直接用的。

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace SmartDeviceProject1
{
    class wincecom
    {
        #region 变量、函数声明定义部分
        //设备控制块结构体类型
        [StructLayout(LayoutKind.Sequential)]
        public struct DCB
        {
            //taken from c struct in platform sdk
            public int DCBlength;           // sizeof(DCB)
            public int BaudRate;            // 指定当前波特率 current baud rate
            // these are the c struct bit fields, bit twiddle flag to set
            /*
            public int fBinary;          // 指定是否允许二进制模式,在windows95中必须主TRUE binary mode, no EOF check
            public int fParity;          // 指定是否允许奇偶校验 enable parity checking
            public int fOutxCtsFlow;      // 指定CTS是否用于检测发送控制,当为TRUE是CTS为OFF,发送将被挂起。 CTS output flow control
            public int fOutxDsrFlow;      // 指定CTS是否用于检测发送控制 DSR output flow control
            public int fDtrControl;       // DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手" DTR flow control type
            public int fDsrSensitivity;   // 当该值为TRUE时DSR为OFF时接收的字节被忽略 DSR sensitivity
            public int fTXContinueOnXoff; // 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止。TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。 FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。XOFF continues Tx
            public int fOutX;          // TRUE时,接收到XoffChar之后便停止发送接收到XonChar之后将重新开始 XON/XOFF out flow control
            public int fInX;           // TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去 XON/XOFF in flow control
            public int fErrorChar;     // 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符 enable error replacement
            public int fNull;          // eTRUE时,接收时去掉空(0值)字节 enable null stripping
            public int fRtsControl;     // RTS flow control
            *//*RTS_CONTROL_DISABLE时,RTS置为OFF
                     RTS_CONTROL_ENABLE时, RTS置为ON
                     RTS_CONTROL_HANDSHAKE时,
                     当接收缓冲区小于半满时RTS为ON
                      当接收缓冲区超过四分之三满时RTS为OFF
                     RTS_CONTROL_TOGGLE时,
                     当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF*/

            //public int fAbortOnError;   // TRUE时,有错误发生时中止读和写操作 abort on error
            //public int fDummy2;        // 未使用 reserved

            public uint flags;
            public ushort wReserved;          // 未使用,必须为0 not currently used
            public ushort XonLim;             // 指定在XON字符发送这前接收缓冲区中可允许的最小字节数 transmit XON threshold
            public ushort XoffLim;            // 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数 transmit XOFF threshold
            public byte ByteSize;           // 指定端口当前使用的数据位 number of bits/byte, 4-8
            public byte Parity;             // 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY  0-4=no,odd,even,mark,space
            public byte StopBits;           // 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS  0,1,2 = 1, 1.5, 2
            public byte XonChar;            // 指定用于发送和接收字符XON的值 Tx and Rx XON character
            public byte XoffChar;           // 指定用于发送和接收字符XOFF值 Tx and Rx XOFF character
            public byte ErrorChar;          // 本字符用来代替接收到的奇偶校验发生错误时的值 error replacement character
            public byte EofChar;            // 当没有使用二进制模式时,本字符可用来指示数据的结束 end of input character
            public byte EvtChar;            // 当接收到此字符时,会产生一个事件 received event character
            public ushort wReserved1;         // 未使用 reserved; do not use
        }

        //串口超时时间结构体类型 ,以毫秒为单位
        [StructLayout(LayoutKind.Sequential)]
        public struct COMMTIMEOUTS
        {
            public int ReadIntervalTimeout;           //读间隔超时
            public int ReadTotalTimeoutMultiplier;    //读时间系数
            public int ReadTotalTimeoutConstant;      //读时间常量
            public int WriteTotalTimeoutMultiplier;   //写时间系数
            public int WriteTotalTimeoutConstant;     //写时间常量
        }

        //溢出缓冲区结构体类型
        [StructLayout(LayoutKind.Sequential)]
        public struct OVERLAPPED
        {
            public int Internal;
            public int InternalHigh;
            public int Offset;
            public int OffsetHigh;
            public int hEvent;
        }
       
        [DllImport("coredll.dll")]
        public static extern int CreateFile(
            string lpFileName,                         // 要打开的串口名称
            uint dwDesiredAccess,                      // 指定串口的访问方式,一般设置为可读可写方式
            int dwShareMode,                           // 指定串口的共享模式,串口不能共享,所以设置为0
            int lpSecurityAttributes,                  // 设置串口的安全属性,WIN9X下不支持,应设为NULL
            int dwCreationDisposition,                 // 对于串口通信,创建方式只能为OPEN_EXISTING
            int dwFlagsAndAttributes,                  // 指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信
            int hTemplateFile                          // 对于串口通信必须设置为NULL
            );
        [DllImport("coredll.dll")]
        public static extern bool ReadFile(
            int hFile,                                 // 通信设备句柄 handle to file
            byte[] lpBuffer,                           // 数据缓冲区 data buffer
            int nNumberOfBytesToRead,                  // 多少字节等待读取 number of bytes to read
            ref int lpNumberOfBytesRead,               // 读取多少字节 number of bytes read
            ref OVERLAPPED lpOverlapped                // 溢出缓冲区 overlapped buffer
            //int r
            );
        [DllImport("coredll.dll")]
        public static extern bool WriteFile(
            int hFile,                                 // 通信设备句柄 handle to file
            byte[] lpBuffer,                           // 数据缓冲区 data buffer
            int nNumberOfBytesToWrite,                 // 多少字节等待写入 number of bytes to write
            ref int lpNumberOfBytesWritten,            // 已经写入多少字节 number of bytes written
            ref OVERLAPPED lpOverlapped                // 溢出缓冲区 overlapped buffer
            //int s
            );
        [DllImport("coredll.dll")]
        public static extern bool CloseHandle(
            int hObject                                // handle to object
            );
        [DllImport("coredll.dll")]
        public static extern bool GetCommState(
            int hFile,                                 //通信设备句柄
            ref DCB lpDCB                              // 设备控制块DCB
            );
        [DllImport("coredll.dll")]
        public static extern bool SetCommState(
            int hFile,                                 // 通信设备句柄
            ref DCB lpDCB                              // 设备控制块
            );
        [DllImport("coredll.dll")]
        public static extern bool GetCommTimeouts(
            int hFile,                                 // 通信设备句柄 handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts            // 超时时间 time-out values
            );
        [DllImport("coredll.dll")]
        public static extern bool SetCommTimeouts(
            int hFile,                                 // 通信设备句柄 handle to comm device
            ref COMMTIMEOUTS lpCommTimeouts            // 超时时间 time-out values
            );
        //清空读写缓冲区
        [DllImport("coredll.dll")]
        public static extern bool PurgeComm(
            int hFile,
            uint dwFlags
            );
        //设置读写缓冲区
        [DllImport("coredll.dll")]
        public static extern bool SetupComm(
            int hFile,                    // 通信设备句柄 handle to file
            int dwInQueue,                //输入缓冲区的大小
            int dwOutQueue                //输出缓冲区的大小
            );

        //得到串口最后一次返回的错误
        [DllImport("coredll.dll")]
        private static extern uint GetLastError();

        //设置DCB标志位
        internal void SetDcbFlag(int whichFlag, int setting, DCB dcb)
        {
            uint num;
            setting = setting << whichFlag;
            if ((whichFlag == 4) || (whichFlag == 12))
            {
                num = 3;
            }
            else if (whichFlag == 15)
            {
                num = 0x1ffff;
            }
            else
            {
                num = 1;
            }
            dcb.flags &= ~(num << whichFlag);
            dcb.flags |= (uint)setting;
        }

        //comm port win32 file handle
        static int hComm = -1;       
        //win32 api constants
        const uint GENERIC_READ = 0x80000000;// WINAPI常量,写标志
        const uint GENERIC_WRITE = 0x40000000;// WINAPI常量,读标志
        const int OPEN_EXISTING = 3;   // WINAPI常量,打开已存在  
        //清空读写缓冲区
        const int PURGE_REABORT = 0x2;
        const int PURGE_REACLEAR = 0x8;
        const int PURGE_TXABORT = 0x1;
        const int PURGE_TXACLEAR = 0x4;
        int ReadTimeout = 1000;  //超时长
        string comPort = "COM4:";//端口名称(COM1,COM2...COM4...)
        //string PortNum="4";//端口号
        //string comPort = string.Format("COM{0}:", PortNum);//将端口号格式化
        DCB dcbCommPort = new DCB();
        COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
        //OVERLAPPED ovlCommPort = new OVERLAPPED();//溢出缓冲区
        #endregion

        // 打开串口 OPEN THE COMM PORT.
        public int OpenCom()
        {
            hComm = CreateFile(comPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
            if (!SetupComm(hComm, 1024, 1024))//输入输出缓冲区大小都是1024个字节
                return -1;
            // 设置通信超时时间 SET THE COMM TIMEOUTS.
            if (!GetCommTimeouts(hComm, ref ctoCommPort))
                return -2;
            ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
            ctoCommPort.ReadTotalTimeoutMultiplier = 0;
            ctoCommPort.WriteTotalTimeoutMultiplier = 0;
            ctoCommPort.WriteTotalTimeoutConstant = 0;
            if (!SetCommTimeouts(hComm, ref ctoCommPort))
                return -3;

            // 设置串口 SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
            if (!GetCommState(hComm, ref dcbCommPort))
                return -4;
            dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
            dcbCommPort.BaudRate = 115200;
            dcbCommPort.flags = 0;
            dcbCommPort.ByteSize = (byte)8;
            dcbCommPort.Parity = (byte)0;
            dcbCommPort.StopBits = 0;
            //if (dcbCommPort.Parity > 0)
            //{
            //    dcbCommPort.fParity = 1;
            //dcbCommPort.flags |= 2;
            //}
            //dcbCommPort.flags |= 1;
            //dcbCommPort.wReserved = 0;
          //------------------------------
/*            SetDcbFlag(0, 1, dcbCommPort);            //二进制方式
            SetDcbFlag(1, (dcbCommPort.Parity == 0) ? 0 : 1, dcbCommPort);
            SetDcbFlag(2, 0, dcbCommPort);            //不用CTS检测发送流控制
            SetDcbFlag(3, 0, dcbCommPort);            //不用DSR检测发送流控制
            SetDcbFlag(4, 0, dcbCommPort);            //禁止DTR流量控制
            SetDcbFlag(6, 0, dcbCommPort);            //对DTR信号线不敏感
            SetDcbFlag(9, 1, dcbCommPort);            //检测接收缓冲区
            SetDcbFlag(8, 0, dcbCommPort);            //不做发送字符控制
            SetDcbFlag(10, 0, dcbCommPort);           //是否用指定字符替换校验错的字符
            SetDcbFlag(11, 0, dcbCommPort);           //保留NULL字符
            SetDcbFlag(12, 0, dcbCommPort);           //允许RTS流量控制
            SetDcbFlag(14, 0, dcbCommPort);           //发送错误后,继续进行下面的读写操作

            //------------------------------
            dcbCommPort.wReserved = 0;                       //没有使用,必须为0 
            dcbCommPort.XonLim = 0;                          //指定在XOFF字符发送之前接收到缓冲区中可允许的最小字节数
            dcbCommPort.XoffLim = 0;                         //指定在XOFF字符发送之前缓冲区中可允许的最小可用字节数
            dcbCommPort.XonChar = 0;                         //发送和接收的XON字符
            dcbCommPort.XoffChar = 0;                        //发送和接收的XOFF字符
            dcbCommPort.ErrorChar = 0;                       //代替接收到奇偶校验错误的字符
            dcbCommPort.EofChar = 0;                         //用来表示数据的结束 
            dcbCommPort.EvtChar = 0;                         //事件字符,接收到此字符时,会产生一个事件 
            dcbCommPort.wReserved1 = 0;                      //没有使用
*/
            if(!SetCommState(hComm, ref dcbCommPort))
                return -5;
            return hComm;
        }

        //串口发送函数
        public int SendCom(byte[] BufWrite, int SendNum)
        {
            if (hComm != -1)
            {
                int intRealWrite = 0;
                OVERLAPPED ovlCommPort = new OVERLAPPED();
                //PurgeComm(hComm, PURGE_REABORT | PURGE_REACLEAR | PURGE_TXABORT | PURGE_TXACLEAR );
                //向串口发送数据
                bool a = WriteFile(hComm, BufWrite, SendNum, ref intRealWrite, ref ovlCommPort);
                return intRealWrite;
            }
            return -6;
        }


        // 清除接收缓冲区
        public void ClearReceiveBuf()
        {
            if (hComm != -1)
            {
                PurgeComm(hComm, PURGE_REABORT | PURGE_REACLEAR);
            }
        }

        // 清除发送缓冲区
        public void ClearSendBuf()
        {
            if (hComm != -1)
            {
                PurgeComm(hComm, PURGE_TXABORT | PURGE_TXACLEAR);
            }
        }

        //从串口读取数据
        public int ReadCom(ref byte[] BufRead, int NumBytes)
        {
            if (hComm != -1)
            {
                //byte[] BufRead = new byte[NumBytes];//接收数据的缓冲区
                int intBytesRead = 0;//实际接收的多少字节
                OVERLAPPED ovlCommPort = new OVERLAPPED();
                //PurgeComm(hComm, PURGE_REABORT | PURGE_REACLEAR | PURGE_TXABORT | PURGE_TXACLEAR | PURGE_TXACLEAR);
                //接收从串口返回来的数据
                bool b = ReadFile(hComm, BufRead, NumBytes, ref intBytesRead, ref ovlCommPort);
                return intBytesRead;
            }
            return -1;
        }

        //关闭串口
        public bool CloseCom()
        {
            bool c = CloseHandle(hComm);
            return c;
        }


        // 发送命令
        public int SendCommand(byte[] SendData, ref  byte[] ReceiveData, int Overtime)
        {
            if (hComm != -1)
            {
                COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
                // 设置通信超时时间
                GetCommTimeouts(hComm, ref ctoCommPort);
                ctoCommPort.ReadTotalTimeoutConstant = Overtime;
                ctoCommPort.ReadTotalTimeoutMultiplier = 0;
                ctoCommPort.WriteTotalTimeoutMultiplier = 0;
                ctoCommPort.WriteTotalTimeoutConstant = 200; 
                SetCommTimeouts(hComm, ref ctoCommPort);

                ClearSendBuf();
                ClearReceiveBuf();

                int a = SendCom(SendData, SendData.Length);
                //return a;
                return ReadCom(ref ReceiveData, ReceiveData.Length);
            }
            return -1;
        }
    }
}

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值