diff options
Diffstat (limited to 'serial.c')
-rw-r--r-- | serial.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/serial.c b/serial.c new file mode 100644 index 0000000..43506ec --- /dev/null +++ b/serial.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * 在OpenHarmony系统下开发串口通信的应用与在Linux系统中类似, | ||
3 | * 但需要确保你的设备支持串口操作,并且有适当的驱动支持。 | ||
4 | * | ||
5 | * 以下是一个用C++编写的示例,展示如何在OpenHarmony中打开串口, | ||
6 | * 设置波特率为115200,并发送指定的16进制数。 | ||
7 | * - 打开串口:使用open()函数打开指定的串口设备。 | ||
8 | * - 配置串口:使用termios结构体配置串口参数如波特率、字符大小、奇偶校验等。 | ||
9 | * - 发送数据:使用write()函数将数据写入串口。 | ||
10 | * - 关闭串口:操作完成后,使用close()函数关闭串口。 | ||
11 | * 确保你的OpenHarmony设备有对应的串口设备文件/dev/ttyS1, | ||
12 | * 并且你的应用有足够的权限来访问这个设备。根据你的硬件和操作系统配置,设备文件的路径可能不同。 | ||
13 | */ | ||
14 | |||
15 | #include <arpa/inet.h> | ||
16 | #include <errno.h> | ||
17 | #include <fcntl.h> | ||
18 | #include <netinet/in.h> | ||
19 | #include <poll.h> | ||
20 | #include <pthread.h> | ||
21 | #include <stdbool.h> | ||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <sys/socket.h> | ||
26 | #include <termios.h> | ||
27 | #include <unistd.h> | ||
28 | |||
29 | #define FULL_SPEED 1.0f // 全速前进的速度 | ||
30 | #define R 0.15f // 轮距的一半 | ||
31 | |||
32 | typedef unsigned char byte; | ||
33 | int fd; | ||
34 | int port = 5001; | ||
35 | char portname[50] = "/dev/ttyUSB0"; // 串口设备名 | ||
36 | char clientIP[20] = ""; | ||
37 | |||
38 | struct termios tty; | ||
39 | pthread_t udpSend, udpRecv; | ||
40 | const int MAX_BUFFER_SIZE = 1024; | ||
41 | struct sockaddr_in clientAddr; | ||
42 | |||
43 | int whellInit() { | ||
44 | // 打开串口 | ||
45 | fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); | ||
46 | if (fd < 0) { | ||
47 | // C语言报error | ||
48 | fprintf(stderr, "Error opening %s: %s\n", portname, strerror(errno)); | ||
49 | return false; | ||
50 | } | ||
51 | |||
52 | // 设置串口参数 | ||
53 | memset(&tty, 0, sizeof tty); | ||
54 | if (tcgetattr(fd, &tty) != 0) { | ||
55 | // cerr << "Error from tcgetattr: " << strerror(errno) << endl; | ||
56 | fprintf(stderr, "Error from tcgetattr: %s\n", strerror(errno)); | ||
57 | return false; | ||
58 | } | ||
59 | |||
60 | cfsetospeed(&tty, B115200); // 设置输出波特率为115200 | ||
61 | cfsetispeed(&tty, B115200); // 设置输入波特率为115200 | ||
62 | |||
63 | tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars | ||
64 | tty.c_iflag &= ~IGNBRK; // ignore break signal | ||
65 | tty.c_lflag = 0; // no signaling chars, no echo, | ||
66 | // no canonical processing | ||
67 | tty.c_oflag = 0; // no remapping, no delays | ||
68 | tty.c_cc[VMIN] = 0; // read doesn't block | ||
69 | tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout | ||
70 | |||
71 | tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl | ||
72 | tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, | ||
73 | // enable reading | ||
74 | tty.c_cflag &= ~(PARENB | PARODD); // shut off parity | ||
75 | tty.c_cflag |= 0; | ||
76 | tty.c_cflag &= ~CSTOPB; | ||
77 | tty.c_cflag &= ~CRTSCTS; | ||
78 | |||
79 | if (tcsetattr(fd, TCSANOW, &tty) != 0) { | ||
80 | // cerr << "Error from tcsetattr: " << strerror(errno) << endl; | ||
81 | fprintf(stderr, "Error from tcsetattr: %s\n", strerror(errno)); | ||
82 | return false; | ||
83 | } | ||
84 | return true; | ||
85 | } | ||
86 | |||
87 | bool wheelSend(byte a, byte a_v, byte b, byte b_v) { | ||
88 | unsigned char data[7] = {0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
89 | byte checksum = 0; | ||
90 | data[2] = a; | ||
91 | data[3] = a_v; | ||
92 | data[4] = b; | ||
93 | data[5] = b_v; | ||
94 | |||
95 | for (int i = 0; i < 6; i++) { | ||
96 | checksum ^= data[i]; | ||
97 | } | ||
98 | data[6] = checksum; | ||
99 | |||
100 | // 发送数据 | ||
101 | if (write(fd, data, 7) != 7) { | ||
102 | fprintf(stderr, "Failed to write to the serial port\n"); | ||
103 | return false; | ||
104 | } | ||
105 | |||
106 | printf("Data %02X %02X %02X %02X %02X %02X %02X wheelSend successfully!\n", | ||
107 | data[0], data[1], data[2], data[3], data[4], data[5], data[6]); | ||
108 | return true; | ||
109 | } | ||
110 | |||
111 | void speedControl(byte status, byte speed) { | ||
112 | switch (status) { | ||
113 | case 1: | ||
114 | wheelSend(0x01, speed, 0x01, speed); | ||
115 | break; | ||
116 | case 2: | ||
117 | wheelSend(0x02, speed, 0x01, speed); | ||
118 | break; | ||
119 | case 3: | ||
120 | wheelSend(0x01, speed, 0x02, speed); | ||
121 | break; | ||
122 | case 0: | ||
123 | default: | ||
124 | wheelSend(0x00, 0x00, 0x00, 0x00); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void udpSendThread() { | ||
130 | // 创建UDP套接字 | ||
131 | int sockfd = -1; | ||
132 | struct sockaddr_in serverAddr; | ||
133 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | ||
134 | fprintf(stderr, "Error: Failed to create socket\n"); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | memset((char *)&serverAddr, 0, sizeof(serverAddr)); | ||
139 | serverAddr.sin_family = AF_INET; // 设置地址族为IPv4 | ||
140 | serverAddr.sin_port = htons(port); // 设置端口号 | ||
141 | if (inet_aton(clientIP, &serverAddr.sin_addr) == 0) { | ||
142 | fprintf(stderr, "Error: Failed to convert IP address\n"); | ||
143 | close(sockfd); | ||
144 | return; | ||
145 | } | ||
146 | while (true) { | ||
147 | // 每秒向socket发送一次0x30 | ||
148 | byte a = 0x39; | ||
149 | // 发送消息 | ||
150 | sendto(sockfd, (const char *)&a, 1, 0, (struct sockaddr *)&serverAddr, | ||
151 | sizeof(serverAddr)); | ||
152 | printf("Send: Data %02X udpSend successfully!\n", a); | ||
153 | sleep(1); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void udpRecvThread() { | ||
158 | int socketfd = -1; | ||
159 | char buffer[MAX_BUFFER_SIZE]; | ||
160 | struct sockaddr_in serverAddr; | ||
161 | socklen_t addrLen = sizeof(serverAddr); | ||
162 | int bytesReceived; | ||
163 | |||
164 | // fd_set readfds; | ||
165 | // struct timeval tv; | ||
166 | int retval; | ||
167 | struct pollfd fds; | ||
168 | |||
169 | if ((socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { | ||
170 | fprintf(stderr, "Error: Failed to create socket\n"); | ||
171 | return; | ||
172 | } | ||
173 | memset((char *)&serverAddr, 0, sizeof(serverAddr)); | ||
174 | memset(buffer, 0, sizeof(buffer)); | ||
175 | serverAddr.sin_family = AF_INET; | ||
176 | serverAddr.sin_port = htons(port); | ||
177 | serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
178 | |||
179 | if (bind(socketfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == | ||
180 | -1) { | ||
181 | // cerr << "Error: Bind failed" << endl; | ||
182 | fprintf(stderr, "Error: Bind failed\n"); | ||
183 | close(socketfd); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | bytesReceived = recvfrom(socketfd, buffer, MAX_BUFFER_SIZE, 0, | ||
188 | (struct sockaddr *)&clientAddr, &addrLen); | ||
189 | if (bytesReceived == -1) { | ||
190 | fprintf(stderr, "Error: Failed to receive data\n"); | ||
191 | close(socketfd); | ||
192 | return; | ||
193 | } | ||
194 | printf("Received start message from %s: %s\n", | ||
195 | inet_ntoa(clientAddr.sin_addr), buffer); | ||
196 | strcpy(clientIP, inet_ntoa(clientAddr.sin_addr)); | ||
197 | |||
198 | if (pthread_create(&udpSend, NULL, udpSendThread, NULL) != 0) { | ||
199 | fprintf(stderr, "Error creating udpSend thread\n"); | ||
200 | close(socketfd); | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | fds.fd = socketfd; | ||
205 | fds.events = POLLIN; | ||
206 | |||
207 | while (true) { | ||
208 | // /* Watch sock to see when it has input. */ | ||
209 | // FD_ZERO(&readfds); | ||
210 | // FD_SET(socketfd, &readfds); | ||
211 | // /* Wait up to three seconds. */ | ||
212 | // tv.tv_sec = 3; | ||
213 | // tv.tv_usec = 0; | ||
214 | |||
215 | // retval = select(socketfd + 1, &readfds, NULL, NULL, &tv); | ||
216 | retval = poll(&fds, 1, 3000); | ||
217 | if (retval == -1) { | ||
218 | fprintf(stderr, "Error: select failed\n"); | ||
219 | break; | ||
220 | } else if (retval == 0) { | ||
221 | printf("No data within three seconds.\n"); | ||
222 | speedControl(0, 0); | ||
223 | // break; | ||
224 | } else { | ||
225 | bytesReceived = recvfrom(socketfd, buffer, MAX_BUFFER_SIZE, 0, | ||
226 | (struct sockaddr *)&clientAddr, &addrLen); | ||
227 | if (bytesReceived == -1) { | ||
228 | fprintf(stderr, "Error: Failed to receive data\n"); | ||
229 | continue; | ||
230 | } | ||
231 | printf("Received Message from %s: %2x %2x\n", | ||
232 | inet_ntoa(clientAddr.sin_addr), buffer[0], buffer[1]); | ||
233 | speedControl(buffer[0], buffer[1]); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | int main() { | ||
239 | // 关闭1号和2号文件描述符 | ||
240 | // close(1); | ||
241 | // close(2); | ||
242 | // // 打开serial.log文件,并将其复制到1号和2号文件描述符 | ||
243 | // open("serial.log", O_RDWR | O_CREAT, 0666); | ||
244 | // dup(1); | ||
245 | // dup(2); | ||
246 | |||
247 | if (!whellInit()) { | ||
248 | goto err; | ||
249 | } | ||
250 | |||
251 | if (pthread_create(&udpRecv, NULL, udpRecvThread, NULL) != 0) { | ||
252 | fprintf(stderr, "Error creating udpRecv thread\n"); | ||
253 | goto err; | ||
254 | } | ||
255 | pthread_join(udpRecv, NULL); | ||
256 | |||
257 | err: | ||
258 | close(fd); | ||
259 | return 0; | ||
260 | } | ||