粗略的对windows下串口的编程写了常用的封装函数(包含打开 关闭 初始化 读写),测试过的
HANDLE CUART::uart_open(const char *uart_str) {
HANDLE hCom1 = CreateFile(uart_str,
GENERIC_READ | GENERIC_WRITE, //允许读和写
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING, //打开而不是创建
0,
NULL);
if (hCom1 == INVALID_HANDLE_VALUE) {
printf("打开COM失败!\n");
return 0;
}
//FILE_SHARE_READ| FILE_SHARE_WRITE
printf("COM打开成功!\n");
SetupComm(hCom1, 4096, 4096); //输入缓冲区和输出缓冲区的大小都是4096
return hCom1;
}
int CUART::uart_init(HANDLE uart_fd, DWORD BAUD, BYTE DATABITS, BYTE PARITY, BYTE STOPBIT) {
COMMTIMEOUTS TimeOuts;
//设定读超时 间隔超时是指读取两个字符之间的延时,总超时是指读写操作总共花费的时间。写操作只支持总超时,读操作两种超时都支持
// 单位为ms
TimeOuts.ReadIntervalTimeout = 0; //读间隔超时
TimeOuts.ReadTotalTimeoutMultiplier = 10; //读时间系数
TimeOuts.ReadTotalTimeoutConstant = 5000; //读时间常量
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier = 10; //写时间系数
TimeOuts.WriteTotalTimeoutConstant = 5000; //写时间常量
SetCommTimeouts(uart_fd, &TimeOuts); //设置超时
DCB dcb;
GetCommState(uart_fd, &dcb);
dcb.BaudRate = BAUD; //波特率
dcb.ByteSize = DATABITS; //数据位
dcb.Parity = PARITY; //奇偶校验
dcb.StopBits = STOPBIT; // 停止位
SetCommState(uart_fd, &dcb);
return 0;
// ReadIntervalTimeout:两相邻字符之间最大的延时。当读串口数据时,一旦两个字符传输的时间间隔超过该时间,读函数将返回现有的数据。设置为0表示该参数不起作用。
// ReadTotalTimeoutMultiplier:读操作总的超时事件的系数。
// 这个变量是不能单独使用的。必须和ReadTotalTimeoutConstant一起使用才有效果。
// ReadTotalTimeoutConstant:读操作总的超时时间的修正常量。
// 这个变量也是不能单独使用的,必须和ReadTotalTimeoutMultiplier一起使用才有效果。
// WriteTotalTimeoutMultiplier:写操作总的超时事件的系数。
// 这个变量是不能单独使用的,必须和WriteTotalTimeoutConstant一起使用才有效果。
// WriteTotalTimeoutConstant:写操作总的超时时间的修正常量。
// 这个变量也是不能单独使用的。必须和WriteTotalTimeoutMultiplier一起使用才有效果。
// 在整个串口的读写操作中,存在着两种超时设置。一种是间隔超时,一种是总超时。这两种超时是独立存在,互不影响的。
// 间隔超时,只在读操作中存在,就是ReadIntervalTimeout。
// 当读操作中,前后两个字符之间的时间间隔超过时,读操作就结束了。
// 举例来说,你一次读取8个字符,但是在你读取了第一个字符之后,在读取第二个字符时,间隔超时了,那么读操作就结束了,这样整个操作就只读取了1个字节。
// 即使,你的总时间没有超时。
// 另一种超时,就是总超时。
// 这里有一个公式。
// 总的读 / 写超时时间 = Read(Write) TotalTimeoutMultiplier x 要读/写的字节数
// + Read(Write) TotalTimeoutConstant.
// 这里要说明的一点,要读/写的字节数是从哪里来的。 这个是从ReadFile
// 或者WriteFile函数中定义的。 在读操作时,
// 若当前所花读取时间已经超过了总的超时设置,则读操作就结束了。
// 即使,每两个字符之间的间隔没有超时。
// 举例来说,若总共读取8个字节。
// 间隔设置为8ms,总超时系数为3ms,总超时常数为3ms。
// 则总的超时时间为3 * 8 + 3 =27ms。
// 若每个字符读取的间隔为7ms,则这次操作总共能读取4个字符,就结束了。
// 因为读取第5个字符时,已经需要35ms,超过总超时时间了。
return 0;
}
void CUART::uart_close(HANDLE uart_fd) {
CloseHandle(uart_fd); //关闭文件描述符
return;
}
int CUART::uart_recv(HANDLE uart_fd, BYTE *recv_buf, unsigned int recv_len,DWORD* act_recv_len) {
//返回值只是表示此次执行的结果
struct _COMSTAT comstat;
ClearCommError(uart_fd,NULL,&comstat);
if(comstat.cbInQue < recv_len)
{
recv_len = comstat.cbInQue;
}
return ReadFile(uart_fd,recv_buf,recv_len,act_recv_len,NULL);
}
int CUART::uart_send(HANDLE uart_fd, BYTE *send_buf, unsigned int send_len,DWORD* act_send_len) {
//返回值只是表示此次执行的结果
DWORD comerr = 0;
struct _COMSTAT comstat;
ClearCommError(uart_fd,&comerr,&comstat);
if(comerr != 0)
{
perror("uart_send err");
return -1;
}
return WriteFile(uart_fd,send_buf,send_len,act_send_len,NULL);
}