《RS485/RS232不同平台的测试程序 Windows和Linux》之二

随祥 2016-10-14 11:05:16
Windows平台
现在我在写一下利用VC++的API函数编写的串口通讯程序,生成运行在Windows平台下的.exe可执行文件
打开编写软件



实现串口通讯的API函数
函数名 作用
CreateFile 打开串口
GetCommState 检测串口设置
SetCommState 设置串口

BuilderCommDCB 用字符串中的值来填充设备控制块
GetCommTimeouts 检测通信超时设置

SetCommTimeouts 设置通信超时参数

SetCommMask 设定被监控事件
WaitCommEvent 等待被监控事件发生

WaitForMultipleObjects 等待多个被监测对象的结果
WriteFile 发送数据
ReadFile 接收数据
GetOverlappedResult 返回最后重叠(异步)操作结果
PurgeComm 清空串口缓冲区,退出所有相关操作
ClearCommError 更新串口状态结构体,并清除所有串口硬件错误
CloseHandle 关闭串行口

用Windows API 编写串口程序本身是有巨大优点的,控制能力会更强,效率高,运用灵活;
API编写串口,过程:
1、 创建串口句柄,用CreateFile;
2、 对串口的参数进行设置,波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);
3、 对串口进行相应的读写操作,ReadFile和WriteFile函数;
4、 读写结束后,关闭串口句柄,用CloseFile。

因为我不是专门在Windows平台下开发软件的所以一些具体的函数参数理解有限,所以我在这里只把源码献上,如若要详细了解各个函数的功能还是要另行网上查询的 O(∩_∩)O~

串口句柄打开串口
/************************************************************************/
/*打开COM口文件
/* nPort : 串口号
/*BOOL:返回 TRUE 成功
/************************************************************************/
BOOL CSerial::Open(int nPort)
{
char szPort[15];
wsprintf(szPort,"COM%d:",nPort);
//cout << ">>opened------>:" << szPort << endl;
m_hComDev = CreateFile(szPort,GENERIC_READ | GENERIC_WRITE,\
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);//打开串口文件
if(m_hComDev == INVALID_HANDLE_VALUE)
{
cout << " no open:" << GetLastError() << endl;
return (FALSE);
}

memset(&m_OverlappedRead, 0, sizeof( OVERLAPPED));
memset(&m_OverlappedWrite, 0, sizeof( OVERLAPPED));
m_OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

if(!SetupComm(m_hComDev,1024,1024))
{ ////输入缓冲区和输出缓冲区的大小都是1024
cout << "erroe SetupComm 读写缓冲区" << endl;
return (FALSE);
}
return TRUE;
}//Open

设置串口
/************************************************************************/
/* nBaud : 波特率, 比如 9600
/* nByteSize : 数据位, 比如 8
/* nParity : 奇偶校验位, NOPARITY 表示 No parity, EVENPARITY表示Even; MARKPARITY表示Mark;ODDPARITY表示Odd; SPACEPARITY表示Space
/* nStopBits : 停止位, ONESTOPBIT 表示 1 stop bit;ONE5STOPBITS 表示 1.5 stop bits; TWOSTOPBITS 表示 2 stop bits ;
/*RetValue : 成功返回TRUE, 失败返回FALSE
/************************************************************************/
//配置串口属性
BOOL CSerial::Setconfig(int nBaud,BYTE nByteSize,BYTE nParity,BYTE nStopBits)
{
memset(&dcb,0,sizeof(dcb));//在一段内存块中填充某个给定的值,是对较大的结构//体或数组进行清零操作的一种最快方法
if(!GetCommState(m_hComDev,&dcb))//获取当前DCB配置
{
cout << "Error GetCommState" << endl;
return FALSE;
}
// set DCB to configure the serial port
dcb.DCBlength = sizeof(dcb);
/* ---------- Serial Port Config ------- */
dcb.BaudRate = nBaud;
dcb.ByteSize = nByteSize;
dcb.Parity = nParity;// uParity
dcb.StopBits = nStopBits;
dcb.fParity = TRUE;
dcb.fOutxCtsFlow = 0;//CTS线上的硬件握手
dcb.fOutxDsrFlow = 0;//DSR线上的硬件握手
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;// DSR sensitivity
dcb.fRtsControl = RTS_CONTROL_DISABLE;// RTS_CONTROL_ENABLE
dcb.fOutX = 0;
dcb.fInX = 0;
dcb.fTXContinueOnXoff = TRUE;
/* ----------------- misc parameters ----- */
dcb.fErrorChar = 0;
dcb.fBinary = 1;
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
dcb.XonLim = 2;//transmit XON threshold 指定在XON字符发送这前接收缓冲区中可允许的最小字节数
dcb.XoffLim = 4;//transmit XOFF threshold 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数
dcb.XonChar = 0x11;//0x13
dcb.XoffChar = 0x13;// 0x19
dcb.EvtChar = 0;

// set DCB
if (!SetCommState( m_hComDev, &dcb ) || m_OverlappedRead.hEvent==NULL || m_OverlappedWrite.hEvent==NULL)
{
DWORD dwError = GetLastError();
fprintf(stdout, "\nerror at connect.\n");
printf("dwError = %d \n", dwError);
return FALSE;
}
else
return true;
}//Setconfig
这里可以详细说一下DCB这个结构体我是一一配置的 其实还有个函数直接配置的就用不到这么麻烦的,一开始我认为RS485的流控制要配置以下这几个参数的,不知道为什么其实这样也可以实现RS485的通讯的,我在下面会有一些函数专门是设置RTS为的拉高和拉低的;
dcb.fOutxCtsFlow = 0;//CTS线上的硬件握手
dcb.fOutxDsrFlow = 0;//DSR线上的硬件握手
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;// DSR sensitivity
dcb.fRtsControl = RTS_CONTROL_DISABLE;// RTS_CONTROL_ENABLE
这里请路过的大神能留步给我讲解一下呀O(∩_∩)O~这几个参数在何时要设置呢,我之前了解过如果只有一个主机和多个从机之间的轮询通讯时这几个参数是需要设置的
dcb.fOutxCtsFlow = 1;//CTS线上的硬件握手
dcb.fOutxDsrFlow = 0;//DSR线上的硬件握手
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 1;// DSR sensitivity
dcb.fRtsControl = RTS_CONTROL_ENABLE;// RTS_CONTROL_ENABLE


这样给你们复制一下网上的对DCB结构体参数的详细介绍:
typedef struct _DCB { // dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate 指定当前的波特率
DWORD fBinary: 1; // binary mode, no EOF check 指定是否允许二进制模式,WINDOWS 95中必须为TRUE
DWORD fParity: 1; // enable parity checking 指定奇偶校验是否允许

DWORD fOutxCtsFlow:1; // CTS output flow control 指定CTS是否用于检测发送控制.当为TRUE是CTS为OFF,发送将被挂起
DWORD fOutxDsrFlow:1; // DSR output flow control 指定DSR是否用于检测发送控制.当为TRUE是DSR为OFF,发送将被挂起
DWORD fDtrControl:2; // DTR flow control type DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手",
DWORD fDsrSensitivity:1; // DSR sensitivity 当该值为TRUE时DSR为OFF时接收的字节被忽略
DWORD fTXContinueOnXoff:1; // XOFF continues Tx 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送是否停止.TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送出XoffChar字符中止接收字节之后,发送继续进行。FALSE时,在接收缓冲区接收到代表缓冲区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。
DWORD fOutX: 1; // XON/XOFF out flow control TRUE时,接收到XoffChar之后便停止发送.接收到XonChar之后将重新开始
DWORD fInX: 1; // XON/XOFF in fv control TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出去.接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去
DWORD fErrorChar: 1; // enable error replacement 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字符
DWORD fNull: 1; // enable null stripping TRUE时,接收时去掉空(0值)字节
DWORD fRtsControl:2; // 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
DWORD fAbortOnError:1; // abort reads/writes on error TRUE时,有错误发生时中止读和写操作
DWORD fDummy2:17; // reserved 未使用
WORD wReserved; // not currently used 未使用,必须为0
WORD XonLim; // transmit XON threshold 指定在XON字符发送这前接收缓冲区中可允许的最小字节数
WORD XoffLim; // transmit XOFF threshold 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数
BYTE ByteSize; // number of bits/byte, 4-8 指定端口当前使用的数据位
BYTE Parity; // 0-4=no,odd,even,mark,space 指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY
BYTE StopBits; // 0,1,2 = 1, 1.5, 2 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS
char XonChar; // Tx and Rx XON character 指定用于发送和接收字符XON的值

char XoffChar; // Tx and Rx XOFF character 指定用于发送和接收字符XOFF值
char ErrorChar; // error replacement character 本字符用来代替接收到的奇偶校验发生错误时的值
char EofChar; // end of input character 当没有使用二进制模式时,本字符可用来指示数据的结束
char EvtChar; // received event character 当接收到此字符时,会产生一个事件
WORD wReserved1; // reserved; do not use 未使用
  } //DCB;
...全文
261 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧