• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2023 Unionman Technology Co., Ltd.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */
16 
17 #include <cstdio>
18 #include "serial_uart.h"
19 
20 #include <termios.h>
21 
22 constexpr int RECV_HEAD = 0xaa;
23 constexpr int RECV_END = 0x55;
24 constexpr int EVT_RIGHT = 0x01;
25 constexpr int EVT_LEFT = 0x02;
26 constexpr int EVT_BACK = 0x03;
27 constexpr int EVT_FORWARD = 0x04;
28 constexpr int EVT_PULLUP = 0x05;
29 constexpr int EVT_PULLDOWN = 0x06;
30 constexpr int EVT_PULLREMOVE = 0x07;
31 constexpr int EVT_TOUCH1 = 0x21;
32 constexpr int EVT_TOUCH2 = 0x22;
33 constexpr int EVT_TOUCH3 = 0x23;
34 constexpr int EVT_TOUCH4 = 0x24;
35 constexpr int EVT_TOUCH5 = 0x25;
36 constexpr int START = 0;
37 constexpr int DATA = 1;
38 constexpr int CHECK = 2;
39 constexpr int END = 3;
40 
41 // 设置串行端口的波特率
set_baud(int fd,int baud)42 static void set_baud(int fd, int baud)
43 {
44     int ret = -1;
45     struct termios opt; // 用于描述和控制终端设备的各种属性,如波特率、字符大小、停止位等。
46 
47     tcgetattr(fd, &opt); // tcgetattr用来获取终端参数,将从终端获得的信息fd,保存到opt结构体中(这个函数会根据文件描述符(fd)所代表的终端设备,从操作系统内核的终端驱动程序中获取相应的参数信息。)
48     tcflush(fd, TCIOFLUSH); // 清空缓冲区
49     cfsetispeed(&opt, baud);    // 源码应该是//third/musl/src/termios/cfsetospeed.c里那个
50     cfsetospeed(&opt, baud);    // 同上
51 
52     ret = tcsetattr(fd, TCSANOW, &opt); //  将配置信息对象应用到指定的串行端口,TCSANOW表示立即生效
53     if (ret == -1) {
54         perror("tcsetattr fd");
55         return;
56     }
57 
58     tcflush(fd, TCIOFLUSH); // 清空缓冲区
59 }
60 
61 // 根据输入的数据位数量设置相应的标志位,用于配置串行端口的数据位
setup_data_bits(int setup_databits,struct termios * options_databits)62 static int setup_data_bits(int setup_databits, struct termios *options_databits)
63 {
64     switch (setup_databits) {
65         case 5L:
66             options_databits->c_cflag |= CS5; // 按位或运算,只修改对应标志位,其他的保持不变
67             break;
68         case 6L:
69             options_databits->c_cflag |= CS6;
70             break;
71         case 7L:
72             options_databits->c_cflag |= CS7;
73             break;
74         case 8L:
75             options_databits->c_cflag |= CS8;
76             break;
77         default:
78             return -1;
79     }
80     return 1;
81 }
82 
83 // 设置校验位
set_params_parity(int setup_parity,struct termios * options_parity)84 static int set_params_parity(int setup_parity, struct termios *options_parity)
85 {
86     switch (setup_parity) {
87         case 'n':
88         case 'N':                               // 无奇偶校验位
89             options_parity->c_cflag &= ~PARENB; // 清除PARENB位
90             options_parity->c_iflag &= ~INPCK;  // 禁用输入奇偶校验检查
91             break;
92 
93         case 'o':
94         case 'O':                                         // 设置为奇校验
95             options_parity->c_cflag |= (PARODD | PARENB); // 开启奇偶校验并把奇校验开启
96             options_parity->c_iflag |= INPCK;             // 启用输入奇偶校验检查
97             break;
98 
99         case 'e':
100         case 'E':                               // 设置为偶校验
101             options_parity->c_cflag |= PARENB;
102             options_parity->c_cflag &= ~PARODD;
103             options_parity->c_iflag |= INPCK;
104             break;
105 
106         case 'M':
107         case 'm': // 指示使用奇偶校验位作为标记位(奇校验)
108             options_parity->c_cflag |= PARENB | CMSPAR | PARODD;
109             options_parity->c_iflag |= INPCK; // enable parity checking /
110             break;
111 
112         case 'S':
113         case 's': // 指示使用奇偶校验位作为标记位(偶校验)
114             options_parity->c_cflag |= PARENB | CMSPAR;
115             options_parity->c_cflag &= ~PARODD;
116             options_parity->c_iflag |= INPCK; // enable parity checking /
117             break;
118 
119         default:
120             return -1;
121     }
122     return 1;
123 }
124 
125 // 设置串行端口的参数
set_params(int fd,int databits,int stopbits,int parity)126 static int set_params(int fd, int databits, int stopbits, int parity)
127 {
128     struct termios options;
129     int ret = 0;
130 
131     if (tcgetattr(fd, &options) != 0) {
132         perror("tcgetattr fail");
133         return -1;
134     }
135     // 禁用任何特殊的输入和输出处理
136     options.c_iflag = 0;
137     options.c_oflag = 0;
138 
139     // setup data bits
140     options.c_cflag &= ~CSIZE;
141     ret = setup_data_bits(databits, &options);
142     if (ret == -1) {
143         return -1;
144     }
145 
146     // 配置校验选项
147     ret = set_params_parity(parity, &options);
148     if (ret == -1) {
149         return -1;
150     }
151 
152     // stop bits/
153     switch (stopbits) {
154         // CSTOPB对应位0表示一位,1表示两位
155         case 1:
156             options.c_cflag &= ~CSTOPB;
157             break;
158 
159         case 2L:
160             options.c_cflag |= CSTOPB;
161             break;
162 
163         default:
164             return -1;
165     }
166 
167     // 请求发送和清除发送
168     options.c_cflag &= ~CRTSCTS; // 禁用硬件控制流(一种对接收双方之间数据传输速度匹配的控制机制)
169     options.c_lflag = 0; // 禁用本地模式选项
170     options.c_cc[VTIME] = 10; // 读取数据时,如果在该值/10秒内没有数据到达则返回
171     options.c_cc[VMIN] = 1; // 最小读取字符,设置至少读取一个字符后才会返回
172 
173     tcflush(fd, TCIFLUSH);
174     // 将新的参数应用到串口设备上
175     if (tcsetattr(fd, TCSANOW, &options) != 0) {
176         return -1;
177     }
178 
179     return 0;
180 }
181 
182 // 转换波特率为对应的枚举值
conver_baudrate(int baudrate)183 static speed_t conver_baudrate(int baudrate)
184 {
185     switch (baudrate) {
186         case 9600L:
187             return B9600;
188         case 19200L:
189             return B19200;
190         case 38400L:
191             return B38400;
192         case 115200L:
193             return B115200;
194         case 1152000L:
195             return B1152000;
196         default:
197             return B1152000;
198     }
199 }
200 
201 // uart配置
uart_init(int fd,int uartBaud)202 int uart_init(int fd, int uartBaud)
203 {
204     set_baud(fd, conver_baudrate(uartBaud));
205     // uart param /
206     if (set_params(fd, 8L, 1, 'n')) {
207         printf("Set uart parameters fail.\n");
208         return -1;
209     }
210     return 0;
211 }
212 
213 // 传感器数据处理
data_proce(int * recv)214 std::string data_proce(int *recv)
215 {
216     std::string ret;
217     if (recv == nullptr) {
218         printf("data proce error");
219     }
220 
221     if ((recv[START] == RECV_HEAD) && (recv[END] == RECV_END) && (recv[DATA] == (0xff - recv[CHECK]))) {
222         switch (recv[DATA]) {
223             case EVT_BACK:
224                 ret="手势识别为向后";
225                 break;
226             case EVT_FORWARD:
227                 ret="手势识别为向前";
228                 break;
229             case EVT_RIGHT:
230                 ret="手势识别为向右";
231                 break;
232             case EVT_LEFT:
233                 ret="手势识别为向左";
234                 break;
235             case EVT_PULLUP:
236                 ret="手势识别为上拉";
237                 break;
238             case EVT_PULLDOWN:
239                 ret="手势识别为下压";
240                 break;
241             case EVT_PULLREMOVE:
242                 ret="手势识别为上拉下压后松开";
243                 break;
244             case EVT_TOUCH1:
245                 ret="触摸点1";
246                 break;
247             case EVT_TOUCH2:
248                 ret="触摸点2";
249                 break;
250             case EVT_TOUCH3:
251                 ret="触摸点3";
252                 break;
253             case EVT_TOUCH4:
254                 ret="触摸点4";
255                 break;
256             case EVT_TOUCH5:
257                 ret="触摸点5";
258                 break;
259             default:
260                 ret="数据错误";
261                 break;
262         }
263         return ret;
264     }
265     ret="错误";
266     return ret;
267 }