转载请注明出处
作者:小马
自己写的一个的串口操作类
一 打开串口
打开串口用CreateFile, 关健是几个参数该怎么填. CreateFile有7个参数.
LPCTSTR lpFileName 这个填串口号, 比如你用com1, 传进来”com1”就可以了.这里有一点要注意,如果你的串口号是com1到com9, 按上面说的传参没有问题, 如果 com9以上,比如com10, 就要用下面这样的形式,” ////.//COM10 ” DWORD dwDesiredAccess 访问方式, 读,写或可读可写, 一般我们用串口,既要发送数据又会接收据, 可以设置为 GENERIC_READ | GENERIC_WRITE. DWORD dwShareMode 共享模式, 在串口操作中,这个值一般设置为0, 表示不能共享,独占. 这个道理很容易明白,串口是硬件的I/O操作,读写时肯定要独占. LPSECURITY_ATTRIBUTES lpSecurityAttributes 这个值在串口应用中,一般不必关心,直接置为null. DWORD dwCreationDisposition 这个表示如果文件存在或不存在时,createfile的动作, 很明显,在串口应用中,OPEN_EXISTING,表示打开已存在的串口. 如果串口不存在,不可能去创建一个吧. DWORD dwFlagsAndAttributes 文件的属性和标志位, 在串口应用中, 有两种操作模式, 同步(Nonoverlapped)和异步(overlapped), 同步该值为0, 异步模式, 该值可设置为FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED或FILE_FLAG_OVERLAPPED. HANDLE hTemplateFile 这个值直接置为null.
下面解释一下同步和异步的概念.
拿发送数据举个例子, 同步模式下,发送函数返回(可能成功或失败), 操作才完成,否则当前发送线程会阻塞,直到发送完成. 而异步模式通过事件通知来避免阻塞,你可以在发送数据的同时,做其它事情,然后检测事件来判断操作是否完成. 关于同步和异步,在进发送和接收数据时,还有更详细的描述.
该函数如果成功,返回一个有效的串口句柄,否则返回INVALID_HANDLE_VALUE, 注意不是FALSE.
二 串口参数设置
波特率,停止位,字节大小,奇偶校验
这几个参数都存在于一个叫DCB的结构体内, 我们只需给这几个变量赋值, 然后调用SetCommState就可以了. 这里有一点要注意, 因为DCB结构体中还有其它成员变量, 对于我们不需要改变的,要知道它们原来的值,以免调用SetCommState之后出错. 所以,一般是用如下的方式设置这几个成员.
DCB dcb; FillMemory(&dcb, sizeof(dcb), 0);//初始化为空 if (!GetCommState(hComm, &dcb)) // 取当前dcb设置 // Error in GetCommState return FALSE; // 更新自己要设置的值 dcb.BaudRate = CBR_9600 ;//波特率,9600 dcb.Parity = NOPARITY; //无奇偶校验
通过上面方法,就可以避免更改其它的成员.
超时时间包括写超时和读超时,都在COMMTIMEOUTS这个结构体中的成员中。
WriteTotalTimeoutMultiplier和WriteTotalTimeoutConstant是和写操作有关的超时时间.
一次写操作的超时时间为WriteTotalTimeoutMultiplier*(字符数)+WriteTotalTimeoutConstant.
比如要发送10个字节,
WriteTotalTimeoutMultiplier = 100,
WriteTotalTimeoutConstant = 2000.
那么写操作超超时间为100*10+2000 = 3000ms.
在同步模式下, 如果3000ms内没有发送完数据,WriteFile函数会超时返回,可通过函数返回的实际发送的字节数来判断发送是否完成.
在异步模式下, 情况比较复杂一点, 下面讲到发送数据的时候再详述.
如果WriteTotalTimeoutMultiplier和WriteTotalTimeoutConstant的值都为0,表示写操作无超时时间.
ReadIntervalTimeout, ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant三个变量是和读操作有关的超时时间. 后面两个变量用法与写操作类似. 第一个变量, 表示读数据时,两个字节之间的间隔时间,如果该值为0,表示间隔超时不使用.
如果是下面这样的设置:
CommTimeOuts.ReadIntervalTimeout = MAXWORD; CommTimeOuts.ReadTotalTimeoutMultiplier = 0; CommTimeOuts.ReadTotalTimeoutConstant = 0;
读一次缓冲区操作立即返回, 不管读到的是什么,读到多少个字节. 这样的设置还是比较常用的.
超时时间的设置比较灵活, 具体如何设置要根据实际应用, 比如有些应用中,用户在上层自己控制读和写的超时时间, 这种情况下,上面的设置意义就不大.