C 程序未在 Arduino Mega 上打开串行
C Program not opening Serial on Arduino Mega
我有一个 C 程序 (win32 api),它通过串口 (USB) 与我的 Arduino Mega 通信。
我可以通过 IDE 的串行监视器与 Arduino 通信。
如果我插我的Arduino和运行 C程序,端口似乎没有正常打开,没有通信。
在这种情况下,如果我从 Arduino 的 IDE(或另一个串行程序)打开串行监视器,然后再次关闭它,C 程序就可以正常工作。
这是我来自 C 程序的端口代码(在这个例子中它传递了 5,因为这是 Arduino 正在使用的端口):
CSerialPort.h:
#pragma once
#include <Windows.h>
#define CP_BAUD_RATE_1200 CBR_1200
#define CP_BAUD_RATE_9600 CBR_9600
#define CP_BAUD_RATE_1155 CBR_1155
#define CP_BAUD_RATE_4800 CBR_4800
#define CP_BAUD_RATE_19200 CBR_19200
#define CP_DATA_BITS_5 5
#define CP_DATA_BITS_6 6
#define CP_DATA_BITS_7 7
#define CP_DATA_BITS_8 8
#define CP_STOP_BITS_ONE ONESTOPBIT
#define CP_STOP_BITS_TWO TWOSTOPBITS
#define CP_STOP_BITS_ONE_AND_HALF ONE5STOPBITS
#define CP_PARITY_NOPARITY NOPARITY
#define CP_PARITY_ODD ODDPARITY
#define CP_PARITY_EVEN EVENPARITY
#define CP_PARITY_MARK MARKPARITY
#define CP_PARITY_SPACE SPACEPARITY
typedef HANDLE PORT;
PORT OpenPort(int idx);
void ClosePort(PORT com_port);
int SetPortBaudRate(PORT com_port, int rate);
int SetPortDataBits(PORT com_port, int databits);
int SetPortStopBits(PORT com_port, int stopbits);
int SetPortParity(PORT com_port, int parity);
int GetPortBaudRate(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 * databuffer,int bufferlen);
CSerialPort.c
#include "CSerialPort.h"
#include <time.h>
PORT OpenPort(int idx)
{
HANDLE hComm;
TCHAR comname[100];
wsprintf(comname, TEXT("\\.\COM%d"), idx);
hComm = CreateFile(comname, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
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;
return hComm;
}
void ClosePort(PORT com_port)
{
CloseHandle(com_port);
}
int SetPortBaudRate(PORT com_port, int rate)
{
DCB dcbSerialParams = { 0 };
BOOL Status;
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(com_port, &dcbSerialParams);
if (Status == FALSE)
printf("FALSE BAUD STATE");
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)
printf("FALSE DATABITS STATE");
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)
printf("FALSE STOP STATE");
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)
printf("FALSE PARITY STATE");
return FALSE;
dcbSerialParams.Parity = parity;
Status = SetCommState(com_port, &dcbSerialParams);
return Status;
}
int GetPortBaudRate(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;
}
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;
return dNoOfBytesWritten;
}
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;
}
return TRUE;
}
测试代码:
#include "CSerialPort.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
bool sendComms(char * msgSndPtr, int portNum)
{
auto p1 = OpenPort(portNum);
SetPortBaudRate(p1, CP_BAUD_RATE_9600);
SetPortDataBits(p1, CP_DATA_BITS_8);
SetPortStopBits(p1, CP_STOP_BITS_ONE);
SetPortParity(p1, CP_PARITY_NOPARITY);
SendData(p1, msgSndPtr);
ClosePort(p1);
printf("%s sent.\n", msgSndPtr); //debug
//strcpy(msgSndPtr,"");
return 1;
}
bool receiveComms(char * msgRecPtr, int portNum)
{
bool status = 0;
strcpy(msgRecPtr,"");
SetPortBaudRate(portNum, CP_BAUD_RATE_9600);
SetPortDataBits(portNum, CP_DATA_BITS_8);
SetPortStopBits(portNum, CP_STOP_BITS_ONE);
SetPortParity(portNum, CP_PARITY_NOPARITY);
auto p1 = OpenPort(portNum);
status = ReciveData(p1, msgRecPtr, 50);
ClosePort(p1);
if (!status) //if nothing is received, cancel out and show error
{
return 0;
}
else
{
printf("%s received.\n", msgRecPtr); //debug
return 1;
}
}
void main()
{
char msgRec[50];
char * msgRecPtr = msgRec;
char msgSnd[50];
char * msgSndPtr = msgSnd;
while (!(strcmp("end",msgRecPtr)))
{
sendComms(msgSndPtr, 5);
receiveComms(msgRecPtr, 5);
printf("sent: %s\n, msgSndPtr);
printf("received: %s\n, msgRecPtr);
}
}
arduino代码:
int i = 0;
void setup()
{
// Initiate Serial
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect. Needed for native USB
Serial.println("serial ready");
}
void loop()
{
Serial.println("testing comms");
i++
delay (150);
if (i == 10) {
Serial.println("end");
}
}
如果有人在使用 win32 时遇到过这个问题或知道串行监视器如何打开它的端口,那将非常有帮助。
编辑:澄清一下,一旦成功打开端口(除了我的 C 程序之外的任何程序),我的 C 程序就可以正常工作并且可以 open/close 成功打开端口,直到下一次通电循环.
谢谢
我已经修复了你的代码!
主要错误是:
Incorrect use of COM port number where a handle was required
Closing the port after sending data and before receiving response which flush input buffer
Almost no error check which prohibed to know what was wrong
在测试代码中,主循环不正确。没有发送数据,在收到“end”时中断循环是错误的。
我在打开端口后移动了一次 COM 端口参数化(也可能在 OpenPort 内部)。
您处理接收的方式与您定义的通信协议有关。我没有触及那部分。如果它是我的软件,我会将协议设计为 面向行的协议 即发送和接收的每条消息都将采用以 CRLF 对终止的行的形式。然后可以循环接收,累积所有字符直到找到行尾。
这里是固定源代码之后。还有很多romm需要改进。
测试代码:
#include "CSerialPort.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
bool SetComParameters(PORT comPort, int rate, int dataBits, int stopBits, int parity)
{
if (!SetPortBaudRate(comPort, CP_BAUD_RATE_9600)) {
fprintf(stderr, "Unable to set baudrate\n");
return 0;
}
if (!SetPortDataBits(comPort, CP_DATA_BITS_8)) {
fprintf(stderr, "Unable to set data bits\n");
return 0;
}
if (!SetPortStopBits(comPort, CP_STOP_BITS_ONE)) {
fprintf(stderr, "Unable to set stop bits\n");
return 0;
}
if (!SetPortParity(comPort, CP_PARITY_NOPARITY)) {
fprintf(stderr, "Unable to set parity\n");
return 0;
}
return 1;
}
bool sendComms(char* msgSndPtr, PORT comPort)
{
SendData(comPort, msgSndPtr);
return 1;
}
bool receiveComms(char* msgRecPtr, PORT comPort)
{
bool status = 0;
strcpy(msgRecPtr, "");
status = ReceiveData(comPort, msgRecPtr, 50);
return status;
}
void main()
{
char msgRec[50];
char* msgRecPtr = msgRec;
char msgSnd[50];
char* msgSndPtr = msgSnd;
int portNum = 1;
PORT com_port = OpenPort(portNum);
if (com_port == NULL) {
fprintf(stderr, "Unable to open COM%d\n", portNum);
return;
}
if (!SetComParameters(com_port, CP_BAUD_RATE_9600, CP_DATA_BITS_8, CP_STOP_BITS_ONE, CP_PARITY_NOPARITY)) {
fprintf(stderr, "Error setting parameters\n");
return;
}
do { // FPiette use of do/while instead of while loop
strcpy(msgSnd, "Hello\r\n");
if (!sendComms(msgSndPtr, com_port)) {
fprintf(stderr, "sendComs failed\n");
break;
}
printf("sent: %s\n", msgSndPtr);
if (!receiveComms(msgRecPtr, com_port)) {
fprintf(stderr, "receiveComms failed\n");
break;
}
printf("received: %s\n", msgRecPtr);
} while (strcmp("end", msgRecPtr));
ClosePort(&com_port);
printf("Done.\n");
}
CSerialPort.c:
#include <stdio.h>
#include "CSerialPort.h"
#include <time.h>
PORT OpenPort(int idx)
{
HANDLE hComm;
TCHAR comname[100];
wsprintf(comname, TEXT("\\.\COM%d"), idx);
hComm = CreateFile(comname, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
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;
return hComm;
}
void ClosePort(PORT* com_port)
{
if (com_port && *com_port) {
CloseHandle(*com_port);
*com_port = NULL;
}
}
int SetPortBaudRate(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;
}
int GetPortBaudRate(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;
}
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;
return dNoOfBytesWritten;
}
int ReceiveData(PORT com_port, char* data, int len)
{
DWORD dwEventMask = 0;
DWORD NoBytesRead = 0;
BOOL Status = WaitCommEvent(com_port, &dwEventMask, NULL);
if (Status == FALSE)
return FALSE;
Status = ReadFile(com_port, data, len, &NoBytesRead, NULL);
if (Status == FALSE)
return FALSE;
data[NoBytesRead] = 0;
return TRUE;
}
CSerialPort.h:
#pragma once
#include <Windows.h>
#define CP_BAUD_RATE_1200 CBR_1200
#define CP_BAUD_RATE_9600 CBR_9600
#define CP_BAUD_RATE_1155 CBR_1155
#define CP_BAUD_RATE_4800 CBR_4800
#define CP_BAUD_RATE_19200 CBR_19200
#define CP_DATA_BITS_5 5
#define CP_DATA_BITS_6 6
#define CP_DATA_BITS_7 7
#define CP_DATA_BITS_8 8
#define CP_STOP_BITS_ONE ONESTOPBIT
#define CP_STOP_BITS_TWO TWOSTOPBITS
#define CP_STOP_BITS_ONE_AND_HALF ONE5STOPBITS
#define CP_PARITY_NOPARITY NOPARITY
#define CP_PARITY_ODD ODDPARITY
#define CP_PARITY_EVEN EVENPARITY
#define CP_PARITY_MARK MARKPARITY
#define CP_PARITY_SPACE SPACEPARITY
#define bool BOOL
typedef HANDLE PORT;
PORT OpenPort(int idx);
void ClosePort(PORT* com_port);
int SetPortBaudRate(PORT com_port, int rate);
int SetPortDataBits(PORT com_port, int databits);
int SetPortStopBits(PORT com_port, int stopbits);
int SetPortParity(PORT com_port, int parity);
int GetPortBaudRate(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 ReceiveData(PORT com_port, char* databuffer, int bufferlen);
我有一个 C 程序 (win32 api),它通过串口 (USB) 与我的 Arduino Mega 通信。
我可以通过 IDE 的串行监视器与 Arduino 通信。
如果我插我的Arduino和运行 C程序,端口似乎没有正常打开,没有通信。 在这种情况下,如果我从 Arduino 的 IDE(或另一个串行程序)打开串行监视器,然后再次关闭它,C 程序就可以正常工作。
这是我来自 C 程序的端口代码(在这个例子中它传递了 5,因为这是 Arduino 正在使用的端口):
CSerialPort.h:
#pragma once
#include <Windows.h>
#define CP_BAUD_RATE_1200 CBR_1200
#define CP_BAUD_RATE_9600 CBR_9600
#define CP_BAUD_RATE_1155 CBR_1155
#define CP_BAUD_RATE_4800 CBR_4800
#define CP_BAUD_RATE_19200 CBR_19200
#define CP_DATA_BITS_5 5
#define CP_DATA_BITS_6 6
#define CP_DATA_BITS_7 7
#define CP_DATA_BITS_8 8
#define CP_STOP_BITS_ONE ONESTOPBIT
#define CP_STOP_BITS_TWO TWOSTOPBITS
#define CP_STOP_BITS_ONE_AND_HALF ONE5STOPBITS
#define CP_PARITY_NOPARITY NOPARITY
#define CP_PARITY_ODD ODDPARITY
#define CP_PARITY_EVEN EVENPARITY
#define CP_PARITY_MARK MARKPARITY
#define CP_PARITY_SPACE SPACEPARITY
typedef HANDLE PORT;
PORT OpenPort(int idx);
void ClosePort(PORT com_port);
int SetPortBaudRate(PORT com_port, int rate);
int SetPortDataBits(PORT com_port, int databits);
int SetPortStopBits(PORT com_port, int stopbits);
int SetPortParity(PORT com_port, int parity);
int GetPortBaudRate(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 * databuffer,int bufferlen);
CSerialPort.c
#include "CSerialPort.h"
#include <time.h>
PORT OpenPort(int idx)
{
HANDLE hComm;
TCHAR comname[100];
wsprintf(comname, TEXT("\\.\COM%d"), idx);
hComm = CreateFile(comname, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
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;
return hComm;
}
void ClosePort(PORT com_port)
{
CloseHandle(com_port);
}
int SetPortBaudRate(PORT com_port, int rate)
{
DCB dcbSerialParams = { 0 };
BOOL Status;
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(com_port, &dcbSerialParams);
if (Status == FALSE)
printf("FALSE BAUD STATE");
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)
printf("FALSE DATABITS STATE");
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)
printf("FALSE STOP STATE");
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)
printf("FALSE PARITY STATE");
return FALSE;
dcbSerialParams.Parity = parity;
Status = SetCommState(com_port, &dcbSerialParams);
return Status;
}
int GetPortBaudRate(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;
}
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;
return dNoOfBytesWritten;
}
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;
}
return TRUE;
}
测试代码:
#include "CSerialPort.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
bool sendComms(char * msgSndPtr, int portNum)
{
auto p1 = OpenPort(portNum);
SetPortBaudRate(p1, CP_BAUD_RATE_9600);
SetPortDataBits(p1, CP_DATA_BITS_8);
SetPortStopBits(p1, CP_STOP_BITS_ONE);
SetPortParity(p1, CP_PARITY_NOPARITY);
SendData(p1, msgSndPtr);
ClosePort(p1);
printf("%s sent.\n", msgSndPtr); //debug
//strcpy(msgSndPtr,"");
return 1;
}
bool receiveComms(char * msgRecPtr, int portNum)
{
bool status = 0;
strcpy(msgRecPtr,"");
SetPortBaudRate(portNum, CP_BAUD_RATE_9600);
SetPortDataBits(portNum, CP_DATA_BITS_8);
SetPortStopBits(portNum, CP_STOP_BITS_ONE);
SetPortParity(portNum, CP_PARITY_NOPARITY);
auto p1 = OpenPort(portNum);
status = ReciveData(p1, msgRecPtr, 50);
ClosePort(p1);
if (!status) //if nothing is received, cancel out and show error
{
return 0;
}
else
{
printf("%s received.\n", msgRecPtr); //debug
return 1;
}
}
void main()
{
char msgRec[50];
char * msgRecPtr = msgRec;
char msgSnd[50];
char * msgSndPtr = msgSnd;
while (!(strcmp("end",msgRecPtr)))
{
sendComms(msgSndPtr, 5);
receiveComms(msgRecPtr, 5);
printf("sent: %s\n, msgSndPtr);
printf("received: %s\n, msgRecPtr);
}
}
arduino代码:
int i = 0;
void setup()
{
// Initiate Serial
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect. Needed for native USB
Serial.println("serial ready");
}
void loop()
{
Serial.println("testing comms");
i++
delay (150);
if (i == 10) {
Serial.println("end");
}
}
如果有人在使用 win32 时遇到过这个问题或知道串行监视器如何打开它的端口,那将非常有帮助。
编辑:澄清一下,一旦成功打开端口(除了我的 C 程序之外的任何程序),我的 C 程序就可以正常工作并且可以 open/close 成功打开端口,直到下一次通电循环.
谢谢
我已经修复了你的代码!
主要错误是:
Incorrect use of COM port number where a handle was required
Closing the port after sending data and before receiving response which flush input buffer
Almost no error check which prohibed to know what was wrong
在测试代码中,主循环不正确。没有发送数据,在收到“end”时中断循环是错误的。
我在打开端口后移动了一次 COM 端口参数化(也可能在 OpenPort 内部)。
您处理接收的方式与您定义的通信协议有关。我没有触及那部分。如果它是我的软件,我会将协议设计为 面向行的协议 即发送和接收的每条消息都将采用以 CRLF 对终止的行的形式。然后可以循环接收,累积所有字符直到找到行尾。
这里是固定源代码之后。还有很多romm需要改进。
测试代码:
#include "CSerialPort.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
bool SetComParameters(PORT comPort, int rate, int dataBits, int stopBits, int parity)
{
if (!SetPortBaudRate(comPort, CP_BAUD_RATE_9600)) {
fprintf(stderr, "Unable to set baudrate\n");
return 0;
}
if (!SetPortDataBits(comPort, CP_DATA_BITS_8)) {
fprintf(stderr, "Unable to set data bits\n");
return 0;
}
if (!SetPortStopBits(comPort, CP_STOP_BITS_ONE)) {
fprintf(stderr, "Unable to set stop bits\n");
return 0;
}
if (!SetPortParity(comPort, CP_PARITY_NOPARITY)) {
fprintf(stderr, "Unable to set parity\n");
return 0;
}
return 1;
}
bool sendComms(char* msgSndPtr, PORT comPort)
{
SendData(comPort, msgSndPtr);
return 1;
}
bool receiveComms(char* msgRecPtr, PORT comPort)
{
bool status = 0;
strcpy(msgRecPtr, "");
status = ReceiveData(comPort, msgRecPtr, 50);
return status;
}
void main()
{
char msgRec[50];
char* msgRecPtr = msgRec;
char msgSnd[50];
char* msgSndPtr = msgSnd;
int portNum = 1;
PORT com_port = OpenPort(portNum);
if (com_port == NULL) {
fprintf(stderr, "Unable to open COM%d\n", portNum);
return;
}
if (!SetComParameters(com_port, CP_BAUD_RATE_9600, CP_DATA_BITS_8, CP_STOP_BITS_ONE, CP_PARITY_NOPARITY)) {
fprintf(stderr, "Error setting parameters\n");
return;
}
do { // FPiette use of do/while instead of while loop
strcpy(msgSnd, "Hello\r\n");
if (!sendComms(msgSndPtr, com_port)) {
fprintf(stderr, "sendComs failed\n");
break;
}
printf("sent: %s\n", msgSndPtr);
if (!receiveComms(msgRecPtr, com_port)) {
fprintf(stderr, "receiveComms failed\n");
break;
}
printf("received: %s\n", msgRecPtr);
} while (strcmp("end", msgRecPtr));
ClosePort(&com_port);
printf("Done.\n");
}
CSerialPort.c:
#include <stdio.h>
#include "CSerialPort.h"
#include <time.h>
PORT OpenPort(int idx)
{
HANDLE hComm;
TCHAR comname[100];
wsprintf(comname, TEXT("\\.\COM%d"), idx);
hComm = CreateFile(comname, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
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;
return hComm;
}
void ClosePort(PORT* com_port)
{
if (com_port && *com_port) {
CloseHandle(*com_port);
*com_port = NULL;
}
}
int SetPortBaudRate(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;
}
int GetPortBaudRate(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;
}
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;
return dNoOfBytesWritten;
}
int ReceiveData(PORT com_port, char* data, int len)
{
DWORD dwEventMask = 0;
DWORD NoBytesRead = 0;
BOOL Status = WaitCommEvent(com_port, &dwEventMask, NULL);
if (Status == FALSE)
return FALSE;
Status = ReadFile(com_port, data, len, &NoBytesRead, NULL);
if (Status == FALSE)
return FALSE;
data[NoBytesRead] = 0;
return TRUE;
}
CSerialPort.h:
#pragma once
#include <Windows.h>
#define CP_BAUD_RATE_1200 CBR_1200
#define CP_BAUD_RATE_9600 CBR_9600
#define CP_BAUD_RATE_1155 CBR_1155
#define CP_BAUD_RATE_4800 CBR_4800
#define CP_BAUD_RATE_19200 CBR_19200
#define CP_DATA_BITS_5 5
#define CP_DATA_BITS_6 6
#define CP_DATA_BITS_7 7
#define CP_DATA_BITS_8 8
#define CP_STOP_BITS_ONE ONESTOPBIT
#define CP_STOP_BITS_TWO TWOSTOPBITS
#define CP_STOP_BITS_ONE_AND_HALF ONE5STOPBITS
#define CP_PARITY_NOPARITY NOPARITY
#define CP_PARITY_ODD ODDPARITY
#define CP_PARITY_EVEN EVENPARITY
#define CP_PARITY_MARK MARKPARITY
#define CP_PARITY_SPACE SPACEPARITY
#define bool BOOL
typedef HANDLE PORT;
PORT OpenPort(int idx);
void ClosePort(PORT* com_port);
int SetPortBaudRate(PORT com_port, int rate);
int SetPortDataBits(PORT com_port, int databits);
int SetPortStopBits(PORT com_port, int stopbits);
int SetPortParity(PORT com_port, int parity);
int GetPortBaudRate(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 ReceiveData(PORT com_port, char* databuffer, int bufferlen);