diff options
Diffstat (limited to 'serial.c')
-rw-r--r-- | serial.c | 196 |
1 files changed, 29 insertions, 167 deletions
@@ -1,50 +1,46 @@ | |||
1 | /* | 1 | #include "path/path_ctrl_t.h" |
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> | 2 | #include <errno.h> |
17 | #include <fcntl.h> | 3 | #include <fcntl.h> |
18 | #include <netinet/in.h> | ||
19 | #include <poll.h> | ||
20 | #include <pthread.h> | ||
21 | #include <stdbool.h> | 4 | #include <stdbool.h> |
22 | #include <stdio.h> | 5 | #include <stdio.h> |
23 | #include <stdlib.h> | 6 | #include <stdlib.h> |
24 | #include <string.h> | 7 | #include <string.h> |
25 | #include <sys/socket.h> | ||
26 | #include <termios.h> | 8 | #include <termios.h> |
27 | #include <unistd.h> | 9 | #include <unistd.h> |
28 | 10 | ||
29 | #define FULL_SPEED 1.0f // 全速前进的速度 | ||
30 | #define R 0.15f // 轮距的一半 | ||
31 | |||
32 | typedef unsigned char byte; | 11 | typedef unsigned char byte; |
33 | int fd; | 12 | #define MAX_BUFFER_SIZE 1024 |
34 | int port = 5001; | 13 | |
14 | int fd; // 轮子的串口文件描述符 | ||
35 | char portname[50] = "/dev/ttyUSB0"; // 串口设备名 | 15 | char portname[50] = "/dev/ttyUSB0"; // 串口设备名 |
36 | char clientIP[20] = ""; | 16 | char clientIP[20] = ""; |
37 | |||
38 | struct termios tty; | 17 | struct termios tty; |
39 | pthread_t udpSend, udpRecv; | ||
40 | const int MAX_BUFFER_SIZE = 1024; | ||
41 | struct sockaddr_in clientAddr; | ||
42 | 18 | ||
43 | int whellInit() { | 19 | bool whellInit(); |
20 | bool wheelSend(byte a, byte a_v, byte b, byte b_v); | ||
21 | void speedControl(byte status, byte speed); | ||
22 | void parseCmd(const path_ctrl_t *msg, void *user); | ||
23 | |||
24 | int main() { | ||
25 | if (!whellInit()) { | ||
26 | goto err; | ||
27 | } | ||
28 | lcm *path_lcm = lcm_create(NULL); | ||
29 | if (!path_lcm) { | ||
30 | fprintf(stderr, "Failed to create LCM\n"); | ||
31 | goto err; | ||
32 | } | ||
33 | path_ctrl_t_subscribe(path_lcm, "PATH_CTRL", parseCmd); | ||
34 | |||
35 | err: | ||
36 | close(fd); | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | bool whellInit() { | ||
44 | // 打开串口 | 41 | // 打开串口 |
45 | fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); | 42 | fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); |
46 | if (fd < 0) { | 43 | if (fd < 0) { |
47 | // C语言报error | ||
48 | fprintf(stderr, "Error opening %s: %s\n", portname, strerror(errno)); | 44 | fprintf(stderr, "Error opening %s: %s\n", portname, strerror(errno)); |
49 | return false; | 45 | return false; |
50 | } | 46 | } |
@@ -52,7 +48,6 @@ int whellInit() { | |||
52 | // 设置串口参数 | 48 | // 设置串口参数 |
53 | memset(&tty, 0, sizeof tty); | 49 | memset(&tty, 0, sizeof tty); |
54 | if (tcgetattr(fd, &tty) != 0) { | 50 | if (tcgetattr(fd, &tty) != 0) { |
55 | // cerr << "Error from tcgetattr: " << strerror(errno) << endl; | ||
56 | fprintf(stderr, "Error from tcgetattr: %s\n", strerror(errno)); | 51 | fprintf(stderr, "Error from tcgetattr: %s\n", strerror(errno)); |
57 | return false; | 52 | return false; |
58 | } | 53 | } |
@@ -77,7 +72,6 @@ int whellInit() { | |||
77 | tty.c_cflag &= ~CRTSCTS; | 72 | tty.c_cflag &= ~CRTSCTS; |
78 | 73 | ||
79 | if (tcsetattr(fd, TCSANOW, &tty) != 0) { | 74 | if (tcsetattr(fd, TCSANOW, &tty) != 0) { |
80 | // cerr << "Error from tcsetattr: " << strerror(errno) << endl; | ||
81 | fprintf(stderr, "Error from tcsetattr: %s\n", strerror(errno)); | 75 | fprintf(stderr, "Error from tcsetattr: %s\n", strerror(errno)); |
82 | return false; | 76 | return false; |
83 | } | 77 | } |
@@ -108,7 +102,8 @@ bool wheelSend(byte a, byte a_v, byte b, byte b_v) { | |||
108 | return true; | 102 | return true; |
109 | } | 103 | } |
110 | 104 | ||
111 | void speedControl(byte status, byte speed) { | 105 | void parseCmd(const path_ctrl_t *msg, void *user) { |
106 | byte status = msg->cmd, speed = msg->speed; | ||
112 | switch (status) { | 107 | switch (status) { |
113 | case 1: | 108 | case 1: |
114 | wheelSend(0x01, speed, 0x01, speed); | 109 | wheelSend(0x01, speed, 0x01, speed); |
@@ -124,137 +119,4 @@ void speedControl(byte status, byte speed) { | |||
124 | wheelSend(0x00, 0x00, 0x00, 0x00); | 119 | wheelSend(0x00, 0x00, 0x00, 0x00); |
125 | break; | 120 | break; |
126 | } | 121 | } |
127 | } | 122 | } \ No newline at end of file |
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 | } | ||