【发布时间】:2021-10-07 23:16:33
【问题描述】:
我正在尝试通过我 PC 上的 COM 端口从 nRF52832 芯片读取 2048 个样本。我已经使用 UART 转 USB 电缆将 nRF 芯片的 UART 引脚连接到计算机。之前我已经能够以 921600 的波特率从中获取 printf 和 NRF_LOG_INFO。现在我想对数据进行实时处理,我需要自己读取它。但是当我运行附加代码(见下文)时,读取这些示例需要 15 秒以上,而这应该在大约 1 秒内完成。
关于如何使这段代码运行得更快的任何想法?
(实时方面稍后会添加,现在我的目标是让程序读取速度足够快)
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdint.h>
#include <time.h>
#define SUCCESS 0
#define BUF_SIZE 2048
char* hComm_init_error_modes[7] = {"", //NOT INTENDED FOR USE
"", //NOT INTENDED FOR USE
"ERROR OPENING SERIAL PORT\n",
"ERROR RETRIEVING COMM STATE\n",
"ERROR CONFIGURING COMM STATE\n",
"ERROR RETRIEVING COMM TIMEOUTS\n",
"ERROR CONFIGURING COMM TIMEOUTS\n",};
HANDLE hComm;
uint8_t m_buf[BUF_SIZE];
uint8_t single_val_buf[1];
//int m_buf_full = 0;
int hComm_init(char* port){
hComm = CreateFileA(port, //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 2;
}
DCB commStateConfig;
if (!GetCommState(hComm, &commStateConfig)){
return 3;
}
commStateConfig.BaudRate = 921600;
commStateConfig.ByteSize = 8;
if (!SetCommState(hComm, &commStateConfig)){
return 4;
}
COMMTIMEOUTS comm_timeouts;
if (!GetCommTimeouts(hComm, &comm_timeouts)){
return 5;
}
comm_timeouts.ReadIntervalTimeout = 0;
comm_timeouts.ReadTotalTimeoutMultiplier = 0;
comm_timeouts.ReadTotalTimeoutConstant = 1;
comm_timeouts.WriteTotalTimeoutMultiplier = 0;
comm_timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(hComm, &comm_timeouts)){
return 6;
}
return 0;
}
int main(int argc, char* argv[]){
if (argc != 2){
printf("\nWrong number of inputs! Please provide the com port number and nothing else.\n");
return 1;
}
char portname[11+strlen(argv[1])];
strcpy(portname, "\\\\.\\COM");
strcat(portname, argv[1]);
int err = hComm_init(portname);
if (err != SUCCESS){
printf("%s", hComm_init_error_modes[err]);
goto RUNTIME_ERROR;
}
printf("OPENED AND CONFIGURED SERIAL PORT SUCCESSFULLY\n");
if (!SetCommMask(hComm, EV_RXCHAR | EV_ERR)){
printf("SetCommMask failed with error code: %ld\n", GetLastError());
goto RUNTIME_ERROR;
}
DWORD dwEvtMask;
DWORD read;
int readcount = 0;
while (1){
read = 0;
dwEvtMask = 0;
if(kbhit()) //Check for key press
{
if(27 == getch()) // ESC pressed
{
printf("Key ESC pressed, exiting...\n");
goto CLEAN_EXIT;
}
}
if (WaitCommEvent(hComm, &dwEvtMask, NULL))
{
if (dwEvtMask & EV_ERR)
{
printf("Wait failed with error %ld.\n", GetLastError());
goto RUNTIME_ERROR;
}
if (dwEvtMask & EV_RXCHAR)
{
if(!ReadFile(hComm, single_val_buf, 1, &read, NULL)){
printf("\n\nERROR when reading\n\n");
}
m_buf[readcount] = *single_val_buf;
readcount++;
}
if (readcount == BUF_SIZE){
double diff_ms = (clock()-start) * 1000. / CLOCKS_PER_SEC;
print_m_buf(); //for testing only, remove later
printf("Time spent reading: %f ms\n", diff_ms);
goto CLEAN_EXIT;
}
} else {
DWORD dwRet = GetLastError();
if( ERROR_IO_PENDING == dwRet)
{
printf("I/O is pending...\n");
// To do.
}
else
printf("Wait failed with error %ld.\n", GetLastError());
}
}
CLEAN_EXIT:
CloseHandle(hComm);
return 0;
RUNTIME_ERROR:
printf("Runtime error, program exited.\n");
CloseHandle(hComm);
return -1;
}
【问题讨论】:
-
您正在为每个字节读取(一次一个字节)进行操作系统调用并检查键输入。这是一个很大的自重。您可以读取尽可能多的字符,并在每 1024 个循环中检查按键输入吗?
-
或者在单独的线程中处理按键输入和端口输入
-
与其从头试错,不如根据这个示例程序进行修改。 bmo/mttty
标签: c winapi serial-port readfile