commit
2c5fbe2195
9 changed files with 383 additions and 0 deletions
-
5.clang-format
-
0.gitignore
-
5.vscode/settings.json
-
19README.md
-
1build.sh
-
172uart.cpp
-
28uart.hpp
-
153zuart.cpp
-
BINzuart.out
@ -0,0 +1,5 @@ |
|||
# Defines the Chromium style for automatic reformatting. |
|||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html |
|||
Language: Cpp |
|||
BasedOnStyle: Google |
|||
ColumnLimit: 300 |
@ -0,0 +1,5 @@ |
|||
{ |
|||
"files.associations": { |
|||
"string_view": "cpp" |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
# README |
|||
|
|||
|
|||
``` |
|||
用于将板子上的串口以网络透传出去。客户端通过tcp协议链接上之后,即可通过socket_fd直接和串口通信。 |
|||
|
|||
v1: |
|||
1.支持基本功能 |
|||
2.支持多个客户端同时链接服务器。多个客户端同时链接时,串口来消息,是以广播的形势发个各个Tcp客户端。 |
|||
|
|||
v1.1: |
|||
1.修复占用CPU过高的BUG |
|||
``` |
|||
|
|||
``` |
|||
Usage: |
|||
net_tty.out /dev/ttyUSB0 115200 port |
|||
|
|||
``` |
@ -0,0 +1 @@ |
|||
aarch64-linux-gnu-g++ zuart.cpp uart.cpp -o zuart.out -lpthread |
@ -0,0 +1,172 @@ |
|||
|
|||
/*
|
|||
* uart.c |
|||
* |
|||
* Created on: Aug 5, 2019 |
|||
* Author: Cristian Fatu |
|||
* Implements basic UART functionality, over Uart Lite linux driver, using termios. |
|||
* After booting linux, a device like "/dev/ttyUL1" must be present. |
|||
* These functions work in both canonic and not canonic modes. |
|||
* In the canonic communication mode, the received chars can be retrieved by read only after \n is detected. |
|||
* In the non canonic communication mode, the received chars can be retrieved by read as they are received. |
|||
*/ |
|||
#include "uart.hpp"
|
|||
|
|||
#include <fcntl.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
#include <termios.h>
|
|||
/*
|
|||
Parameters: |
|||
struct UartDevice* dev - pointer to the UartDevice struct |
|||
unsigned char canonic - communication mode |
|||
1 - canonic communication (chars are only received after \n is detected). |
|||
0 - non canonic communication (chars are received as they arrive over UART). |
|||
Return value: |
|||
UART_FAILURE -1 failure |
|||
UART_SUCCESS 0 success |
|||
Description: |
|||
Initializes the UART device. |
|||
When calling the function, the device name (usually "/dev/ttyUL1") must be filled in dev->name and the baud rate must be filled in dev->rate. |
|||
The canonic function parameter indicates communication mode (canonic or not). |
|||
In the canonic communication mode, the received chars can be retrieved by read only after \n is detected. |
|||
In the non canonic communication mode, the received chars can be retrieved by read as they are received, as the non canonic mode is configured with no wait. |
|||
*/ |
|||
int uartStart(struct UartDevice* dev, unsigned char canonic) { |
|||
struct termios* tty; |
|||
int fd; |
|||
int rc; |
|||
|
|||
fd = open(dev->name, O_RDWR | O_NOCTTY); |
|||
if (fd < 0) { |
|||
printf("%s: failed to open file descriptor for file %s\r\n", __func__, dev->name); |
|||
return UART_FAILURE; |
|||
} |
|||
|
|||
tty = (struct termios*)calloc(1, sizeof(*dev->tty)); |
|||
if (!tty) { |
|||
printf("%s: failed to allocate tty instance\r\n", __func__); |
|||
return UART_FAILURE; |
|||
} |
|||
// memset(tty, 0, sizeof(struct termios));
|
|||
|
|||
/*
|
|||
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. |
|||
CRTSCTS : output hardware flow control (only used if the cable has |
|||
all necessary lines. See sect. 7 of Serial-HOWTO) |
|||
CS8 : 8n1 (8bit,no parity,1 stopbit) |
|||
CLOCAL : local connection, no modem contol |
|||
CREAD : enable receiving characters |
|||
*/ |
|||
// tty->c_cflag = dev->rate | CRTSCTS | CS8 | CLOCAL | CREAD;
|
|||
tty->c_cflag = dev->rate | CS8 | CLOCAL | CREAD; |
|||
if (canonic) { |
|||
// canonic
|
|||
/*
|
|||
IGNPAR : ignore bytes with parity errors |
|||
ICRNL : map CR to NL (otherwise a CR input on the other computer |
|||
will not terminate input) |
|||
otherwise make device raw (no other input processing) |
|||
*/ |
|||
tty->c_iflag = IGNPAR | ICRNL; |
|||
/*
|
|||
ICANON : enable canonical input |
|||
disable all echo functionality, and don't send signals to calling program |
|||
*/ |
|||
tty->c_lflag = ICANON; |
|||
} else { |
|||
// not canonic
|
|||
/*
|
|||
IGNPAR : ignore bytes with parity errorsc_cc[VTIME] |
|||
*/ |
|||
tty->c_iflag = IGNPAR; |
|||
/* set input mode (non-canonical, no echo,...) */ |
|||
tty->c_lflag = 0; |
|||
/* Do not wait for data */ |
|||
tty->c_cc[VTIME] = 10; /* inter-character timer unused */ |
|||
tty->c_cc[VMIN] = 0; /* blocking read until 5 chars received */ |
|||
} |
|||
|
|||
/*
|
|||
Raw output. |
|||
*/ |
|||
tty->c_oflag = 0; |
|||
|
|||
/* Flush port */ |
|||
tcflush(fd, TCIFLUSH); |
|||
|
|||
/* Apply attributes */ |
|||
rc = tcsetattr(fd, TCSANOW, tty); |
|||
if (rc) { |
|||
printf("%s: failed to set TCSANOW attr\r\n", __func__); |
|||
return UART_FAILURE; |
|||
} |
|||
|
|||
dev->fd = fd; |
|||
dev->tty = tty; |
|||
|
|||
return UART_SUCCESS; |
|||
} |
|||
|
|||
/*
|
|||
Parameters: |
|||
struct UartDevice* dev - pointer to the UartDevice struct |
|||
char *data - pointer to the array of chars to be sent over UART |
|||
int size |
|||
positive value - number of chars to be sent over UART |
|||
-1 - indicates that all the chars until string terminator \0 will be sent |
|||
Return value: |
|||
number of chars sent over UART |
|||
Description: |
|||
This function sends a number of chars over UART. |
|||
If the size function parameter is -1 then all the characters until string terminator \0 will be sent. |
|||
*/ |
|||
int uartSend(struct UartDevice* dev, char* data, int size) { |
|||
int sent = 0; |
|||
if (size == -1) { |
|||
size = strlen(data); |
|||
} |
|||
sent = write(dev->fd, data, size); |
|||
|
|||
#ifdef DEBUG
|
|||
printf("%s: sent %d characters\r\n", __func__, sent); |
|||
#endif
|
|||
return sent; |
|||
} |
|||
|
|||
/*
|
|||
Parameters: |
|||
struct UartDevice* dev - pointer to the UartDevice struct |
|||
char *data - pointer to the array of chars to hold the cars revceived over UART |
|||
int size_max - the maximum number of characters to be received |
|||
Return value: |
|||
number of chars received over UART |
|||
Description: |
|||
This function receives characters over UART. |
|||
In the canonic communication mode, the received chars will be retrieved by read only after \n is detected. |
|||
In the non canonic communication mode, the received chars will be retrieved by read as they are received, as the non canonic mode is configured with no wait. |
|||
*/ |
|||
int uartReceive(struct UartDevice* dev, char* data, int size_max) { |
|||
int received = 0; |
|||
|
|||
#ifdef DEBUG
|
|||
// printf("%s: receiving characters %d\r\n", __func__, size_max);
|
|||
#endif
|
|||
received = read(dev->fd, data, size_max - 1); |
|||
data[received] = '\0'; |
|||
|
|||
#ifdef DEBUG
|
|||
// if(received > 0)
|
|||
// printf("%s: received %d characters\r\n", __func__, received);
|
|||
// else
|
|||
// printf("%s: r%d/%d\r\n", __func__, received, size_max);
|
|||
#endif
|
|||
return received; |
|||
} |
|||
|
|||
int uartStop(struct UartDevice* dev) { |
|||
free(dev->tty); |
|||
|
|||
return UART_SUCCESS; |
|||
} |
@ -0,0 +1,28 @@ |
|||
/*
|
|||
* uart.h |
|||
* |
|||
* Created on: Aug 5, 2019 |
|||
* Author: cristian |
|||
*/ |
|||
|
|||
#include <termios.h>
|
|||
#include <unistd.h>
|
|||
#ifndef SRC_UART_H_
|
|||
#define SRC_UART_H_
|
|||
#define UART_FAILURE -1
|
|||
#define UART_SUCCESS 0
|
|||
// #define DEBUG
|
|||
struct UartDevice { |
|||
char* name; |
|||
int rate; |
|||
|
|||
int fd; |
|||
struct termios* tty; |
|||
}; |
|||
|
|||
int uartStart(struct UartDevice* dev, unsigned char canonic); |
|||
int uartSend(struct UartDevice* dev, char* data, int size); |
|||
int uartReceive(struct UartDevice* dev, char* data, int size_max); |
|||
int uartStop(struct UartDevice* dev); |
|||
|
|||
#endif /* SRC_UART_H_ */
|
@ -0,0 +1,153 @@ |
|||
|
|||
#include <fcntl.h>
|
|||
#include <stdint.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
#include <termios.h>
|
|||
#include <unistd.h>
|
|||
//
|
|||
#include <arpa/inet.h>
|
|||
#include <netinet/in.h>
|
|||
#include <sys/socket.h>
|
|||
#include <sys/types.h>
|
|||
//
|
|||
#include <map>
|
|||
#include <set>
|
|||
#include <string>
|
|||
|
|||
#include "uart.hpp"
|
|||
using namespace std; |
|||
#define BACK_LOG 10
|
|||
#define MAX_RECV_SIZE 235
|
|||
|
|||
typedef struct { |
|||
int fd; |
|||
struct sockaddr_in client; |
|||
} tcpclient_t; |
|||
map<string, uint32_t> g_baundmap = { |
|||
{"0", 0000000}, {"50", 0000001}, {"75", 0000002}, {"110", 0000003}, //
|
|||
{"134", 0000004}, {"150", 0000005}, {"200", 0000006}, {"300", 0000007}, //
|
|||
{"600", 0000010}, {"1200", 0000011}, {"1800", 0000012}, {"2400", 0000013}, //
|
|||
{"4800", 0000014}, {"9600", 0000015}, {"19200", 0000016}, {"38400", 0000017}, //
|
|||
{"57600", 0010001}, {"115200", 0010002}, {"230400", 0010003}, {"460800", 0010004}, //
|
|||
{"500000", 0010005}, {"576000", 0010006}, {"921600", 0010007}, {"1000000", 0010010}, //
|
|||
{"1152000", 0010011}, {"1500000", 0010012}, {"2000000", 0010013}, {"2500000", 0010014}, //
|
|||
{"3000000", 0010015}, {"3500000", 0010016}, {"4000000", 0010017}, |
|||
}; |
|||
UartDevice g_uart_device = {0}; |
|||
void printf_buf(char *rx, ssize_t size) { |
|||
for (int i = 0; i < size; i++) { |
|||
printf("0x%02x,", rx[i]); |
|||
} |
|||
printf("\n"); |
|||
} |
|||
|
|||
void *uart_rx_thread_func(void *arg) { |
|||
char buff[4096]; |
|||
while (true) { |
|||
int ret = uartReceive(&g_uart_device, buff, 1024); // send the received text over UART
|
|||
if (ret < 0) { |
|||
printf("uartReceive fail\n"); |
|||
exit(-1); |
|||
} |
|||
|
|||
//
|
|||
if (ret > 0) { |
|||
printf("net<-uart: %d\n", ret); |
|||
printf_buf(buff, ret); |
|||
} |
|||
//
|
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
int openuart(struct UartDevice *device, const char *devname, int rate) { |
|||
device->name = (char *)devname; |
|||
device->rate = rate; |
|||
|
|||
printf("UART open %s\n", device->name); |
|||
return uartStart(device, 0); |
|||
} |
|||
|
|||
static int strtohex(const char *str, uint8_t *hex) { |
|||
/**
|
|||
* @brief |
|||
* str: 02 34 78 92 65 AF |
|||
*/ |
|||
int len = strlen(str); |
|||
int i = 0; |
|||
int j = 0; |
|||
while (i < len) { |
|||
if (str[i] == ' ') { |
|||
i++; |
|||
continue; |
|||
} |
|||
char tmp[3] = {0}; |
|||
tmp[0] = str[i]; |
|||
tmp[1] = str[i + 1]; |
|||
hex[j] = strtol(tmp, NULL, 16); |
|||
i += 2; |
|||
j++; |
|||
} |
|||
if(j == 0){ |
|||
return 0; |
|||
} |
|||
return j-1; |
|||
} |
|||
|
|||
int main(int argc, char const *argv[]) { |
|||
/* code */ |
|||
//"net_uart /dev/ttyUSB0 115200 port"
|
|||
|
|||
if (argc != 4) { |
|||
printf("Usage: %s /dev/ttyUSB0 115200 port\n", argv[0]); |
|||
return -1; |
|||
} |
|||
printf("device name:%s\n", argv[1]); |
|||
printf("baundrate :%s\n", argv[2]); |
|||
printf("port :%s\n", argv[3]); |
|||
|
|||
auto baundrate_find_result = g_baundmap.find(argv[2]); |
|||
if (baundrate_find_result == g_baundmap.end()) { |
|||
printf("unsupport baundrate\n"); |
|||
return -1; |
|||
// baundrate_find_result.
|
|||
}; |
|||
|
|||
/**
|
|||
* 打开串口 |
|||
*/ |
|||
int rc = openuart(&g_uart_device, argv[1], baundrate_find_result->second); |
|||
if (rc) { |
|||
perror("open uart fail"); |
|||
exit(-1); |
|||
} |
|||
|
|||
pthread_t uart_rx_thread; |
|||
pthread_create(&uart_rx_thread, NULL, uart_rx_thread_func, NULL); |
|||
|
|||
while (true) { |
|||
char input[1024] = {0}; |
|||
uint8_t hex[1024] = {0}; |
|||
// scanf("%s", input);
|
|||
fgets(input, 1024, stdin); |
|||
// printf("input:%s\n", input);
|
|||
// 将输入的字符串转换为16进制
|
|||
|
|||
int nhex = strtohex(input, hex); |
|||
printf("tx:"); |
|||
printf_buf((char *)hex, nhex); |
|||
|
|||
// int ret = uartSend(&g_uart_device, input, strlen(input)); // send the received text over UART
|
|||
int ret = uartSend(&g_uart_device, (char *)hex, nhex); // send the received text over UART
|
|||
|
|||
if (ret < 0) { |
|||
printf("uartSend fail\n"); |
|||
} else { |
|||
printf("uartSend ok\n"); |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue