aboutsummaryrefslogtreecommitdiffstats
path: root/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'serial.c')
-rw-r--r--serial.c260
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
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}