Windows C下的 “serial”
上文中我们已经介绍了基于python的serial库,而针对法老王——C,自然也有自己的串口库:
- 实验环境:Win10 x64 C
- gcc 版本:8.1.0
1. 串口配置
针对以下串口配置有:
其中:serial.h
,
#ifndef __SERIAL_H #define __SERIAL_H #include <windows.h> typedef HANDLE PORT;
PORT OpenPort(int idx); void ClosePort(PORT com_port); int SetPortBoudRate(PORT com_port, int rate); int SetPortDataBits(PORT com_port, int bits); int SetPortStopBits(PORT com_port, int bits); int SetPortParity(PORT com_port, int parity); int GetPortBoudRate(PORT com_port); int GetPortDataBits(PORT com_port); int GetPortStopBits(PORT com_port); int GetPortParity(PORT com_port); int SendData(PORT com_port, const char * data); int ReciveData(PORT com_port, char * data,int len); PORT serial_init(int idx, int rate, int databits, int stopbits, int parity); int Serial_SendData(PORT com_port, const char *data, int len); int Serial_ReciveData(PORT com_port, char *data, int len);
#endif
|
1.1 打开和关闭串口
打开串口:
PORT OpenPort(int idx) { HANDLE hComm; TCHAR comname[100];
wsprintf(comname, TEXT("\\\\.\\COM%d"), idx); hComm = CreateFile(comname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hComm == INVALID_HANDLE_VALUE) return NULL; COMMTIMEOUTS timeouts = { 0 }; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE) return NULL;
if (SetCommMask(hComm, EV_RXCHAR) == FALSE) return NULL;
printf("open%d ok\n",idx);
return hComm; }
|
关闭串口:
void ClosePort(PORT com_port) { CloseHandle(com_port); }
|
1.2 串口参数配置
- 对于串口常规需要设置的有:端口号、波特率、数据位、停止位、校验位
1.2.1 设置参数
int SetPortBoudRate(PORT com_port, int rate) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return FALSE; dcbSerialParams.BaudRate = rate; Status = SetCommState(com_port, &dcbSerialParams); return Status; }
|
int SetPortDataBits(PORT com_port, int bits) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return FALSE; dcbSerialParams.ByteSize = bits; Status = SetCommState(com_port, &dcbSerialParams); return Status; }
|
int SetPortStopBits(PORT com_port, int bits) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return FALSE; dcbSerialParams.StopBits = bits; Status = SetCommState(com_port, &dcbSerialParams); return Status; }
|
int SetPortParity(PORT com_port, int parity) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return FALSE; dcbSerialParams.Parity = parity; Status = SetCommState(com_port, &dcbSerialParams); return Status; }
|
1.2.2 获取参数
对应有获取当前设备串口数据信息:
int GetPortBoudRate(PORT com_port) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return -1; return dcbSerialParams.BaudRate; }
|
int GetPortDataBits(PORT com_port) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return -1; return dcbSerialParams.ByteSize; }
|
int GetPortStopBits(PORT com_port) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return -1; return dcbSerialParams.StopBits; }
|
int GetPortParity(PORT com_port) { DCB dcbSerialParams = { 0 }; BOOL Status; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); Status = GetCommState(com_port, &dcbSerialParams); if (Status == FALSE) return -1; return dcbSerialParams.Parity; }
|
1.3 读写操作
int SendData(PORT com_port, const char * data) { DWORD dNoOFBytestoWrite = strlen(data); DWORD dNoOfBytesWritten; BOOL Status = WriteFile(com_port, data, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL); if (Status == FALSE) { return -1; } else { printf("%s\n",data); } return dNoOfBytesWritten; }
int Serial_SendData(PORT com_port, const char *data, int len) { DWORD dNoOfBytesWritten; BOOL Status = WriteFile(com_port, data, len, &dNoOfBytesWritten, NULL);
if (Status == FALSE) return -1; else printf("send ok\n");
return 0; }
|
int ReciveData(PORT com_port, char * data,int len) { DWORD dwEventMask; DWORD NoBytesRead;
BOOL Status = WaitCommEvent(com_port, &dwEventMask, NULL); if (Status == FALSE) { return FALSE; } Status = ReadFile(com_port, data, len, &NoBytesRead, NULL); data[NoBytesRead] = 0;
if (Status == FALSE) { return FALSE; } else { printf("%s\n",data); } return TRUE; }
int Serial_ReciveData(PORT com_port, char * data, int len) { DWORD dwEventMask; DWORD NoBytesRead;
BOOL Status = WaitCommEvent(com_port, &dwEventMask, NULL); if (Status == FALSE) { return -1; } Status = ReadFile(com_port, data, len, &NoBytesRead, NULL); data[NoBytesRead] = 0;
if (Status == FALSE) return -1; else printf("rcv ok\n");
return NoBytesRead; }
|
1. 4串口初始化
# 形参分别为:端口、波特率、数据位、停止位、校验位 PORT serial_init(int idx, int rate, int databits, int stopbits, int parity) { int ret = 0; PORT com_port; com_port = OpenPort(idx); if (com_port == INVALID_HANDLE_VALUE) { printf("open COM%d fail\n", idx); return NULL; } ret = SetPortBoudRate(com_port, rate); if(ret == FALSE) { printf("set COM%d band fail\n", idx); return NULL; } ret = SetPortDataBits(com_port, databits); if(ret == FALSE) { printf("set COM%d databits fail\n", idx); return NULL; } stopbits = ONESTOPBIT; printf("stopbits %d\n",stopbits); ret = SetPortStopBits(com_port, stopbits); if(ret == FALSE) { printf("set COM%d stopbits fail\n", idx); return NULL; } ret = SetPortParity(com_port, parity); if(ret == FALSE) { printf("set COM%d parity fail\n", idx); return NULL; } return com_port; }
|
2. 使用
- 因为serial函数太多可以放于另一个文件中,称为源文件。
- 在主程序中使用
include "serial.c"
,进行调用。
- 还值得一提的是,当接受数据时,必然要建立缓冲池,有两种方式,
char [1024]
或者 `memset(buff, 0, 1024)。
#include <stdio.h> #include <stdint.h> #include <windows.h> #include "serial.h" #include "serial.c"
int serial_test() { PORT COM1; char buff[1024] = {0};
printf("open com1\n"); COM1 = serial_init(1, 115200, 8, 1, 0);
Serial_SendData(COM1, "hello guoguo\n", 13); memset(buff, 0, 1024); Sleep(1); }
int main() { serial_test(); return 0; }
|
可以使用**==VSPD==**虚拟串口进行仿真。
版权声明: 此文章版权归lancit所有,如有转载,请注明来自原作者。