|
|
|
|
#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;
|
|
|
|
|
}
|