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

1 year ago
#define LOG_TAG "serial"
#include "serial.h"
#include "elog.h"
6 months ago
#include <sys/time.h>
1 year ago
/*
TTU使4UARTRS485RS232/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;
}
6 months ago
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
1 year ago
//timeout is in 100ms
int SerialReadEx(int m_comFd,unsigned char *buf,int sz,int timeout)
{
6 months ago
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(;;)
1 year ago
{
6 months ago
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;
1 year ago
}
6 months ago
if (rx_length < 1)
return rx_length;
return rx_length;
1 year ago
}
/**
* 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;
}