终端串口打印程序
东东 Lv4

实现一个终端串口打印程序

serial.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <libserialport.h>
#include <string.h>
#include <windows.h>
#include <pthread.h>

struct sp_port *port = NULL;
int connected = 0;

int serialport_connect(const char *port_name)
{
if(port != NULL)
{
sp_close(port);
sp_free_port(port);
port = NULL;
}

sp_get_port_by_name(port_name, &port);

int res = sp_open(port, SP_MODE_READ_WRITE);
if(res != SP_OK)
{
sp_free_port(port);
port = NULL;
return -1;
}

sp_set_baudrate(port, 115200);
sp_set_bits(port, 8);
sp_set_parity(port, SP_PARITY_NONE);
sp_set_stopbits(port, 1);
sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);

return 0;
}

/* 连接到第一个扫描到的串口 */
const int serialport_connect_to_available(void)
{
struct sp_port **port_list = NULL;
enum sp_return result = sp_list_ports(&port_list);
if (result != SP_OK) {
return -1;
}

for (int i = 0; port_list[i] != NULL; i++)
{
struct sp_port *port = port_list[i];
char *port_name = sp_get_port_name(port);

int r = serialport_connect(port_name);
if(r == 0)
{
printf("\n连接到串口 %s\n\n", port_name);

sp_free_port_list(port_list);
return 0;
}
}

sp_free_port_list(port_list);

return -1;
}

void *serial_write_task(void * arg)
{
char buf[8192];

while (1)
{
gets(buf);
int n = strlen(buf);
buf[n++] = '\r';
buf[n++] = '\n';
if(connected)
{
sp_blocking_write(port, buf, n, 1000);
}
}
}

int main(int argc, char const *argv[])
{
SetConsoleOutputCP(65001);
// HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
// SetConsoleMode(hInput, ENABLE_VIRTUAL_TERMINAL_INPUT);
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(hOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

int res = serialport_connect_to_available();
if(res != 0)
printf("\n未找到串口, 请将设备插入USB口\n");
else
connected = 1;

char buf[4096];
int buf_len = sizeof(buf);

gets(buf);

pthread_t t;
pthread_create(&t, NULL, serial_write_task, NULL);

while (1)
{
if(connected == 1)
{
int n = sp_blocking_read(port, buf, buf_len, 1);
if(n < 0)
{
printf("\n串口连接断开了!\n");
connected = 0;
continue;
}
printf("%.*s", n, buf);
fflush(stdout);
}

else if(serialport_connect_to_available() == 0)
{
connected = 1;
}

Sleep(10);
}

getchar();

return 0;
}

其中

1
2
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(hOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
的作用是输出 ANSI 格式彩色文本
1
2
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hInput, ENABLE_VIRTUAL_TERMINAL_INPUT);
的作用是自行处理输入,即键盘输入的每一个字符不通过缓冲区, 直接发送给程序, Ctrl+C 等组合键也会被接收, 可自行处理。但上面程序简单起见,不使用这一功能, 而是直接使用 gets 即从缓冲区接收字符串。

编译运行 (MSYS2环境)

1
gcc serial.c -lserialport -lpthread

源文件来自于

 评论