实现串口的控制
简介
串口,也称串行通信接口(通常指COM接口或UART (Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART包含TTL电平的串口和RS232电平的串口。TTL电平是3.3V的(单片机),而RS232是负逻辑电平,它定义+5~+12V为低电平,而-12~-5V为高电平,通常PC机串口与单片机串口通信需要电平转换芯片如MAX232。
RS-232也是目前最常用的一种串行通讯接口。它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。
传统的RS-232-C接口标准有22根线,采用标准25芯D型插头座。自BMPC/AT开始使用简化了的9芯D型插座。至今25芯插头座现代应用中已经很少采用。RS-232最大传输距离为15米,最高通信速率为20kb/s。
基本参数
- 串行端口的通信方式是将字节拆分后按位传输,接到此电位信号的一方再将此一个一个的位组合成原来的字节,所以,应在通信端口的初始化时设置几个通信参数。
1)波特率,通俗的讲就是传送数据的速度,不过这里的“数据”是数据位数。波特率的意思就是在一秒中可以传输的数据位数,单位是bps。常用波特率在编程中定义如下:
#define BAUD_075 ((DWORD)0x1)
#define BAUD_110 ((DWORD)0x2)
#define BAUD_134_5 ((DWORD)0x4)
#define BAUD_150 ((DWORD)0x8)
#define BAUD_300 ((DWORD)0x10)
#define BAUD_600 ((DWORD)0x20)
#define BAUD_1200 ((DWORD)0x40)
#define BAUD_1800 ((DWORD)0x80)
#define BAUD_2400 ((DWORD)0x100)
#define BAUD_4800 ((DWORD)0x200)
#define BAUD_7200 ((DWORD)0x400)
#define BAUD_9600 ((DWORD)0x800)
#define BAUD_14400 ((DWORD)0x1000)
#define BAUD_19200 ((DWORD)0x2000)
#define BAUD_38400 ((DWORD)0x4000)
#define BAUD_56K ((DWORD)0x8000)
#define BAUD_128K ((DWORD)0x10000)
#define BAUD_115200 ((DWORD)0x20000)
#define BAUD_57600 ((DWORD)0x40000)
#define BAUD_USER ((DWORD)0x10000000)
2)数据位,当接收设备收到起始位后,紧接着就会收到数据位,数据位的个数可以是5、6、7或者8位。在字符数据传输的过程中,数据位从最低有效位开始传输。定义如下:
#define DATABITS_5 ((WORD)0x1)
#define DATABITS_6 ((WORD)0x2)
#define DATABITS_7 ((WORD)0x4)
#define DATABITS_8 ((WORD)0x8)
3)起始位,在串口线上,没有数据传输时处于逻辑“1”状态,当发送设备要发送一个字符数据时,首先发出一个逻辑“0”信号,这个逻辑低电平就是起始位。起始位通过通信线传像接收设备,当接收设备检测到这个逻辑低电平后,就开始准备接收数据位,因此起始位所起的作用就是告诉接收方字符传输的开始。
4)停止位,在奇偶校验位或者数据位(无奇偶校验位时)就是停止位,它可以是1位、1.5位或者2位,停止位是一个字符数据的结束标志。定义如下
#define ONESTOPBIT 0
#define ONE5STOPBITS 1
#define TWOSTOPBITS 2
5)奇偶校验位,数据位发送完之后,就可以发送奇偶校验位。奇偶校验用于有限差错校验,定义如下:
#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define MARKPARITY 3
#define SPACEPARITY 4
初始化
串口初始化主要完成选定传开的DCB配置、参数、超时处理方式初始化等
-
DCB的定义和初始化
typedef struct _DCB {
DWORD DCBlength;
DWORD BaudRate;
DWORD fBinary: 1;
DWORD fParity: 1;
DWORD fOutxCtsFlow:1;
DWORD fOutxDsrFlow:1;
DWORD fDtrControl:2;
DWORD fDsrSensitivity:1;
DWORD fTXContinueOnXoff: 1;
DWORD fOutX: 1;
DWORD fInX: 1;
DWORD fErrorChar: 1;
DWORD fNull: 1;
DWORD fRtsControl:2;
DWORD fAbortOnError:1;
DWORD fDummy2:17;
WORD wReserved;
WORD XonLim;
WORD XoffLim;
BYTE ByteSize;
BYTE Parity;
BYTE StopBits;
char XonChar;
char XoffChar;
char ErrorChar;
char EofChar;
char EvtChar;
WORD wReserved1;
} DCB -
创建串口,获取句柄
这主要由:
FCommHandle = CreateFile(… …);函数完成 -
串口参数初始化
完成波特率、数据位、停止位、校验位等参数设置。 -
超时参数配置
-
初始化缓冲区
-
串口读写线程的创建。
相关代码如下:
COMMTIMEOUTS CommTimeOut;
DCB dcb;
char com[64] = {0};
sprintf(com, "%s%s", "\\\\.\\", "com7");
FCommHandle = CreateFile(TEXT(com), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (FCommHandle == INVALID_HANDLE_VALUE) {
printf("Open Comm failed. [%ld] \r\n", GetLastError());
exit(0);
}
else {
printf("Open Comm success. \r\n");
}
//Set Commport File InQueue/OutQueue Buffer Size
SetupComm(FCommHandle, 8*1024, 8*1024);
//Set TimeOut Info 配置超时处理
GetCommTimeouts( FCommHandle, &CommTimeOut);
CommTimeOut.ReadIntervalTimeout = 1000;
CommTimeOut.ReadTotalTimeoutMultiplier = 1000;
CommTimeOut.ReadTotalTimeoutConstant = 1000;
CommTimeOut.WriteTotalTimeoutMultiplier = 1000;
CommTimeOut.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts( FCommHandle, &CommTimeOut);
//Set DCB Info 定义串口参数
GetCommState(FCommHandle, &dcb);
dcb.DCBlength = sizeof(DCB);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = DATABITS_8 ;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE;
SetCommState(FCommHandle, &dcb);
PurgeComm(FCommHandle, (PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR)); //清空缓冲区
//create thread to recv and send via Uart Device.
HANDLE hdr_Uartsync = CreateThread(NULL, 0, Thread_UartSync, NULL, 0, NULL);
发送
int Comm_Send(unsigned char *buf,int num)
{
BOOL bRet = FALSE;
DWORD iRet=0,iLen=0;
if(SendFrameReady==0)
return 0;
iLen=num;
bRet = WriteFile(FCommHandle, buf, num, &iRet, NULL);
if (bRet)
{
printf("WriteFile [%ld] bytes. [%s], real is [%ld] Bytes. \r\n", iLen, buf, iRet);
}
SendFrameReady=0;
return 1;
}
接收
BOOL bRet = FALSE;
DWORD iStart, iSpan;
DWORD dwLength, dwFixLen, dwErrorFlags, iRet=0;
COMSTAT comStatus;
char Buf[Max_BUFSIZ];
int i;
if (dwLength > 0) {
memset(Buf, 0, sizeof(Buf));
dwFixLen = sizeof(Buf);
bRet = ReadFile(FCommHandle, Buf, min(dwFixLen, dwLength), &iRet, 0);
if ((bRet)&& (iRet > 0)) {
//打印输出接收到的信息
printf("receive data is:");
for(i=0;i<dwLength;i++)printf("0x%x,",Buf[i]&0xff);
printf("\n");
}
}
return iRet;
用完关闭
int Comm_Close(void)
{
CloseHandle(FCommHandle);
FCommHandle = INVALID_HANDLE_VALUE;
printf("Quit Comm success. \r\n");
return 0;
}