You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
5.5 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#define LOG_TAG "serial"
#include "serial.h"
#include "elog.h"
#include <sys/time.h>
/*
TTU使用4路UART实现两路RS485串口、两路RS232/RS485可切换串口设备节点与串口对应关系为:
UART 设备节点 对应串口 GPIO状态
3 /dev/ttySZ3 RS485-1 -
4 /dev/ttySZ4 RS485-2 -
5 /dev/ttySZ5 RS485-3 PB08为高电平
6 /dev/ttySZ6 RS485-4 PB09为高电平
7 /dev/ttySZ5 RS232-1 PB08为低电平
8 /dev/ttySZ6 RS232-2 PB09为低电平
详情参考:边缘计算框架使用说明/融合终端驱动程序使用说明书
*/
static int speed_arr[] = {B115200,B57600,B38400,B19200,B9600,B4800,B2400,B1200,B300};
static int name_arr[] = {115200,57600,38400,19200,9600,4800,2400,1200,300};
// Common Helper /////////////////////////////////////////////////////////////
//
static void SetACommMode(int fd,int combaud,int databit,int stopbit,int checkmode)
{
struct termios tty_termios;
int flags;
unsigned int i;
if ((tcgetattr(fd, &tty_termios) == -1)) {
log_e("tcgetattr()");
return;
}
cfmakeraw(&tty_termios);
for (i=0; i<sizeof(speed_arr)/sizeof(int); i++) {
if (combaud == name_arr[i]) {
cfsetispeed(&tty_termios, speed_arr[i]);
cfsetospeed(&tty_termios, speed_arr[i]);
break;
}
}
tty_termios.c_cflag &= ~CSIZE;
switch (databit) {
case 7:
tty_termios.c_cflag |= CS7;
break;
case 8:
default:
tty_termios.c_cflag |= CS8;
break;
}
switch (checkmode) {
case 0://none
tty_termios.c_cflag &= ~PARENB;
tty_termios.c_iflag &= ~INPCK;
break;
case 1://ji
tty_termios.c_cflag |= (PARODD | PARENB);
tty_termios.c_iflag |= INPCK;
break;
case 2://ou
tty_termios.c_cflag |= PARENB; // Enable parity????У??
tty_termios.c_cflag &= ~PARODD; //?????У??
tty_termios.c_iflag |= INPCK; //???У?????
break;
default:
tty_termios.c_cflag &= ~PARENB;
tty_termios.c_iflag &= ~INPCK;
break;
}
// Set input parity option
if (checkmode)
tty_termios.c_iflag |= INPCK;
// Set stop bit
switch (stopbit) {
case 1:
tty_termios.c_cflag &= ~CSTOPB;
break;
case 2:
tty_termios.c_cflag |= CSTOPB;
break;
default:
tty_termios.c_cflag &= ~CSTOPB;
break;
}
tty_termios.c_cflag|=(CLOCAL|CREAD);//new add
tty_termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Input
tty_termios.c_oflag &= ~OPOST; // Output
tty_termios.c_oflag &=~(ONLCR|OCRNL);//new add
tty_termios.c_iflag &=~(ICRNL|INLCR);//new add
tty_termios.c_iflag &=~(IXON|IXOFF|IXANY);//new add
tty_termios.c_cc[VTIME] = 0; // Set timeout 0 seconds
tty_termios.c_cc[VMIN] = 0; // Update the tty_termios and do it NOW
if(tcsetattr(fd,TCSANOW,&tty_termios)!=0) {
log_e("tcsetattr()");
}
tcflush(fd,TCIOFLUSH);
flags = fcntl(fd,F_GETFL);
//fcntl(fd,F_SETFL,flags|FNDLAY);
fcntl(fd,F_SETFL,flags|O_NONBLOCK);
}
int SerialOpen(const char *dev_name,int baud,int databit,int stopbit,int chk_mode)
{
int com_fd;
if((com_fd=open(dev_name,O_RDWR|O_NOCTTY|O_NONBLOCK))==-1)
{
log_e("SerialOpen failed");
return -1;
}
SetACommMode(com_fd,baud,databit,stopbit,chk_mode);//
return com_fd;
}
/**
* Read from Serial device
* @param timeout millisecond
*/
int SerialRead(int m_comFd,unsigned char *buf,int sz,int timeout)
{
int iDataNum;
int rxlen = 0;
int recvflag = 0;
if(timeout<0)
return 0;
if(timeout>0)
timeout /= 100;
#ifdef DEBUG_COM
int i;
printf("RX:\t");
#endif
for(;;)
{
iDataNum = read(m_comFd,buf+rxlen,sz-rxlen);
#ifdef DEBUG_COM
for (int i = 0; i < iDataNum; i++) {
printf("%02X ", buf[rxlen + i]);
if (!((i + 1) % 10))
printf("\n\t");
}
#endif
if (iDataNum <= 0) {
if (recvflag==0 && timeout--)
usleep(100000);//100ms
else
break;
} else {
recvflag = 1;
rxlen += iDataNum;
}
}
return (rxlen > 0) ? rxlen : 0;
}
long long get_msec(void)
{
struct timeval tv;
long long time_in_msec = 0;
gettimeofday(&tv, NULL);
time_in_msec = tv.tv_sec;
time_in_msec *= 1000;
time_in_msec += tv.tv_usec / 1000;
return time_in_msec;
}
#if 0
//timeout is in 100ms
int SerialReadEx(int m_comFd,unsigned char *buf,int sz,int timeout)
{
int curr_length=0,last_length=0,rx_length=0;
//int rx_tick=0;
//tcflush(m_comFd,TCIFLUSH);
while(timeout--)
{
usleep(100000);//wait 100ms
curr_length=read(m_comFd,buf+rx_length,sz-rx_length);
if(curr_length>0)
{
rx_length+=curr_length;
last_length=curr_length;
if(rx_length>=sz)
{
return rx_length;
}
}
else
{
if(last_length>0)//上次读取到了字节本次没有,认为读完了一帧
{
return rx_length;
}
last_length=0;
//rx_length=0;
}
}
return rx_length;
}
#endif
int SerialReadEx(int m_comFd,unsigned char *buf,int sz,int timeout)
{
int curr_length=0/*,last_length=0*/,rx_length=0;
long long t0, t1;
t0 = get_msec();
for(;;)
{
rx_length += curr_length;
usleep(5000);
curr_length = read(m_comFd,buf+rx_length, 1040-rx_length);/* 在串口读取字符串 */
t1 = get_msec();
if(t1-t0 >= 350)
break;
}
if (rx_length < 1)
return rx_length;
return rx_length;
}
/**
* Write to Serial device
*/
int SerialWrite(int m_comFd,const unsigned char *buf,int sz)
{
// Avoid rush
usleep(10000);
tcflush(m_comFd,TCOFLUSH);
if (write(m_comFd, buf, sz) != sz) {
log_e("SerialWrite:write()");
return -1;
}
#ifdef DEBUG_COM
int i;
printf("\nTX:\t");
for (i = 0; i < len; i++) {
printf("%02X ", buf[i]);
if (!((i + 1) % 10))
printf("\n\t");
}
printf("\n");
fflush(stdout);
#endif
return sz;
}