aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2024-06-07 14:00:49 +0800
committerWe-unite <3205135446@qq.com>2024-06-07 14:00:49 +0800
commit3a5fb92a375aed63d080658ddd728756b4ca7e7e (patch)
treed42da34e1eed8970cf6610264071ced96f150b8d
downloadWheelCtrl-3a5fb92a375aed63d080658ddd728756b4ca7e7e.tar.gz
WheelCtrl-3a5fb92a375aed63d080658ddd728756b4ca7e7e.zip
initial commit
-rw-r--r--.gitignore2
-rw-r--r--serial.c260
-rw-r--r--server.cpp167
-rw-r--r--testClient.c97
4 files changed, 526 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..367f77e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
1build/*
2.vscode/* \ No newline at end of file
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
32typedef unsigned char byte;
33int fd;
34int port = 5001;
35char portname[50] = "/dev/ttyUSB0"; // 串口设备名
36char clientIP[20] = "";
37
38struct termios tty;
39pthread_t udpSend, udpRecv;
40const int MAX_BUFFER_SIZE = 1024;
41struct sockaddr_in clientAddr;
42
43int 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
87bool 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
111void 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
129void 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
157void 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
238int 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
257err:
258 close(fd);
259 return 0;
260}
diff --git a/server.cpp b/server.cpp
new file mode 100644
index 0000000..5e41eb8
--- /dev/null
+++ b/server.cpp
@@ -0,0 +1,167 @@
1#include <arpa/inet.h>
2#include <chrono>
3#include <cmath>
4#include <condition_variable>
5#include <cstring>
6#include <iostream>
7#include <mutex>
8#include <netinet/in.h>
9#include <sstream>
10#include <string.h>
11#include <string>
12#include <sys/socket.h>
13#include <thread>
14#include <unistd.h>
15
16using namespace std;
17
18enum robotState { // 机器人状态枚举
19 beforeStart,
20 pending,
21 afterEnd, // 建好了图,接下来可选择重新建图或选终点开始路径
22 startRoute,
23};
24
25enum runState { stop, go, left, right };
26
27struct ReceiveDataStruct {
28 int robotId;
29 robotState state;
30 int x;
31 int y;
32 int r;
33};
34
35const int PORT = 5001;
36const char *SERVER_IP = "0.0.0.0";
37const int MAX_BUFFER_SIZE = 1024;
38
39struct ReceiveData {
40 int values[4];
41};
42
43bool newDataAvailable = false;
44string CLIENT_IP = "127.0.0.1";
45struct sockaddr_in clientAddr;
46ReceiveData receivedData = {{0, 1, 2, 3}};
47
48// UDP发送线程函数
49void udpSenderThread() {
50 char values[100] = {0};
51 struct sockaddr_in serverAddr;
52 int sockfd = -1;
53
54 // 创建UDP套接字
55 if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
56 fprintf(stderr, "Error: Failed to create socket\n");
57 return;
58 }
59
60 memset((char *)&serverAddr, 0, sizeof(serverAddr));
61 serverAddr.sin_family = AF_INET;
62 serverAddr.sin_port = htons(PORT);
63 if (inet_aton(CLIENT_IP.c_str(), &serverAddr.sin_addr) == 0) {
64 fprintf(stderr, "Error: Failed to convert IP address\n");
65 close(sockfd);
66 return;
67 }
68
69 while (true) {
70 this_thread::sleep_for(chrono::seconds(1)); // 每1秒发送一次
71
72 // 更新发送的消息
73 memset(values, 0, 100);
74 for (int i = 0; i < 4; ++i) {
75 // values[i] = receivedData.values[i] + 1;
76 sprintf(values + strlen(values), "%d ", receivedData.values[i] + 1);
77 }
78 sprintf(values + strlen(values), "\n");
79 printf("Sending message to %s: %s\n", CLIENT_IP.c_str(), values);
80
81 // 发送消息
82 sendto(sockfd, (const char *)values, sizeof(int) * 4, 0,
83 (struct sockaddr *)&serverAddr, sizeof(serverAddr));
84 }
85
86 close(sockfd);
87}
88
89// 主线程接收UDP消息并打印
90void receiveAndPrintMessages() {
91 int sock;
92 struct sockaddr_in serverAddr;
93 socklen_t addrLen = sizeof(clientAddr);
94 char buffer[MAX_BUFFER_SIZE];
95 ReceiveData receivedData;
96 int pos, bytesReceived;
97
98 // 创建UDP套接字
99 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
100 fprintf(stderr, "Error: Failed to create socket\n");
101 return;
102 }
103
104 memset((char *)&serverAddr, 0, sizeof(serverAddr));
105 memset(buffer, 0, sizeof(buffer));
106 serverAddr.sin_family = AF_INET;
107 serverAddr.sin_port = htons(PORT);
108 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
109
110 // 绑定到端口
111 if (::bind(sock, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) ==
112 -1) {
113 cerr << "Error: Bind failed" << endl;
114 close(sock);
115 return;
116 }
117
118 bytesReceived = recvfrom(sock, buffer, MAX_BUFFER_SIZE, 0,
119 (struct sockaddr *)&clientAddr, &addrLen);
120 if (bytesReceived == -1) {
121 fprintf(stderr, "Error: Failed to receive data\n");
122 return;
123 }
124 printf("Received Message from %s: %s\n", inet_ntoa(clientAddr.sin_addr),
125 buffer);
126 CLIENT_IP = inet_ntoa(clientAddr.sin_addr);
127 thread senderThread2(udpSenderThread);
128 while (true) {
129 // 接收消息
130 bytesReceived = recvfrom(sock, buffer, MAX_BUFFER_SIZE, 0,
131 (struct sockaddr *)&clientAddr, &addrLen);
132 if (bytesReceived == -1) {
133 fprintf(stderr, "Error: Failed to receive data\n");
134 continue;
135 }
136
137 printf("Receive %d bytes from %s: \"%s\"\n", bytesReceived,
138 CLIENT_IP.c_str(), buffer);
139 pos = 0;
140 for (int i = 0; i < 4; ++i) {
141 receivedData.values[i] = atoi(strtok(buffer + pos, " "));
142 // pos += log10(receivedData.values[i]) + 2;
143 // pos需要递增,否则会一直解析第一个数,要求能处理数据为0或负数的情况
144 pos += strlen(strtok(buffer + pos, " ")) + 1;
145 }
146 newDataAvailable = true;
147
148 // 打印消息
149 // CLIENT_IP = inet_ntoa(clientAddr.sin_addr);
150 // cout << "Received Message from " << CLIENT_IP << ": ";
151 // printf("Received Message from %s: ", CLIENT_IP.c_str());
152 // for (int i = 0; i < 4; ++i) {
153 // printf("%d ", receivedData.values[i]);
154 // }
155 printf("\n");
156 }
157
158 close(sock);
159 senderThread2.join();
160}
161
162int main() {
163 thread receiverThread(receiveAndPrintMessages);
164 receiverThread.join();
165
166 return 0;
167}
diff --git a/testClient.c b/testClient.c
new file mode 100644
index 0000000..bbd2529
--- /dev/null
+++ b/testClient.c
@@ -0,0 +1,97 @@
1// 编写一段C程序,使用pthread创建两个线程
2// 发送线程将数据发送到127.0.0.1的5001端口,每0.5s一次
3// 接收线程接收127.0.0.1的5001端口的数据并打印
4
5#include <arpa/inet.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <netinet/in.h>
9#include <pthread.h>
10#include <stdbool.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/socket.h>
15#include <termios.h>
16#include <unistd.h>
17
18pthread_t udpSend, udpRecv;
19pthread_mutex_t mutex;
20int port = 5001;
21char clientIP[20] = "127.0.0.1";
22
23void udpSenderThread() {
24 struct sockaddr_in serverAddr;
25 int sockfd = -1;
26
27 // 创建UDP套接字
28 if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
29 fprintf(stderr, "Error: Failed to create socket\n");
30 return;
31 }
32
33 memset((char *)&serverAddr, 0, sizeof(serverAddr));
34 serverAddr.sin_family = AF_INET;
35 serverAddr.sin_port = htons(port);
36 serverAddr.sin_addr.s_addr = inet_addr(clientIP);
37
38 while (1) {
39 char values[100] = {0};
40 // strcpy(values, "Hello, world!");
41 pthread_mutex_lock(&mutex);
42 printf("Input the data you want to send: ");
43 scanf("%s", values);
44 pthread_mutex_unlock(&mutex);
45 sendto(sockfd, values, strlen(values), 0,
46 (struct sockaddr *)&serverAddr, sizeof(serverAddr));
47 // printf("Send: %s\n", values);
48 sleep(1);
49 }
50}
51
52void udpReceiverThread() {
53 int sockfd = -1;
54 struct sockaddr_in serverAddr;
55 struct sockaddr_in clientAddr;
56 socklen_t clientAddrLen = sizeof(clientAddr);
57 char buffer[1024] = {0};
58
59 // 创建UDP套接字
60 if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
61 fprintf(stderr, "Error: Failed to create socket\n");
62 return;
63 }
64
65 memset((char *)&serverAddr, 0, sizeof(serverAddr));
66 serverAddr.sin_family = AF_INET;
67 serverAddr.sin_port = htons(port - 1);
68 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
69
70 if (bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) ==
71 -1) {
72 fprintf(stderr, "Error: Failed to bind socket\n");
73 close(sockfd);
74 return;
75 }
76
77 while (1) {
78 pthread_mutex_lock(&mutex);
79 int len = recvfrom(sockfd, buffer, 1024, 0,
80 (struct sockaddr *)&clientAddr, &clientAddrLen);
81 pthread_mutex_unlock(&mutex);
82 if (len == -1) {
83 fprintf(stderr, "Error: Failed to receive data\n");
84 close(sockfd);
85 return;
86 }
87 buffer[len] = '\0';
88 printf("Received: %s\n", buffer);
89 }
90}
91
92int main() {
93 pthread_create(&udpSend, NULL, udpSenderThread, NULL);
94 // pthread_create(&udpRecv, NULL, udpReceiverThread, NULL);
95 pthread_join(udpSend, NULL);
96 // pthread_join(udpRecv, NULL);
97} \ No newline at end of file