**
如何读取一个串口
**
网上有很多关于上位机的介绍,但是很少有关于具体如何读取一个串口的介绍,在经过反复查找后。将关于如何读取一个串口的零零碎碎知识整理为一个简单的流程。
首先,串口在电脑中被定义为一个文件,这个文件被windows系统管理,我们的程序无法直接进入系统对串口进行操作,但是我们可以借助API函数访问。
API为application programing interface,即应用程序接口。程序将需求用API函数告诉windows系统,windows系统通过API函数将程序所需求的信息送回程序。
API返回信息时,为了通用性,通常会返回一个叫做句柄的编码。句柄即编码,用来辨识串口。它简单,通用性广。
所以打开一个串口的第一步:
定义一个句柄
HANDLE hCom1;
第二步:调用API函数将句柄指向串口
hCom1 = CreateFile(_T("COM8"),//COM1口
GENERIC_READ | GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
NULL);
if (hCom1 == (HANDLE)-1)
{
printf("打开COM失败!\n");
return FALSE;
}
else
{
printf("COM打开成功!\n");
}
其中定义了对串口的权限,打开串口的方式等。
第三步:设置串口的参数:
这时我们用一个DCB的结构体为串口建模,将串口的所有信息存入其中,这样在交给windows操作系统时,可以把DCB交给windows。
其中我们需要设定
1、波特率
2、奇偶校验位
3、停止位//用于时钟同步的纠正
4、每个字节有多少位
……
DCB dcb1;//一个串口结构体
GetCommState(hCom1, &dcb1);
dcb1.BaudRate = 115200;//波特率为9600
dcb1.ByteSize = 8;//每个字节有8位
dcb1.Parity = NOPARITY;//无奇偶校验位
dcb1.StopBits = TWOSTOPBITS;//两个停止位
//dcb1.fParity = FALSE;
//dcb1.fNull = FALSE;
SetCommState(hCom1, &dcb1);
第四步:我们还需要设定超时
我们在读取数据时,有可能在读入两个字节后第三个字节迟迟不到达,这是我们设定的超时就会起作用,一旦到了超时时间就会强制结束,不再读入。而读取下一个数据串。
COMMTIMEOUTS TimeOuts;
//设定读超时,最长的等待时间
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.ReadTotalTimeoutConstant = 5000;
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom1, &TimeOuts);//设置超时
第五步:我们还需要设定缓存区
SetupComm(hCom1, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是1024
第六步:清空缓存区:
PurgeComm(hCom1, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区
第七步:读写数据
跟文件读取类似
while (1)//不断读取数据
{
unsigned char str[8];
if (!ReadFile(hCom1, str, wCount, &wCount, NULL))//类似于读文件,句柄,读取后存放的地址,要读取的字节数,实际读取的字节数
{
printf("读串口失败!");
return FALSE;
}
FILE* fp1;
fp1 = fopen("串口发送的数.txt", "a+");//新建一个文本,将数据保存在其中
int i = 0;
for (i = 0; i < wCount; i++)
{
printf("读串口成功!读取数据为: %02X \n", str[i]);
fprintf(fp1, "%02X ", str[i]);
}
fclose(fp1);
}
最后关闭串口:
CloseHandle(hCom1);
至此一个读取串口的操作就完全完成了!