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.
144 lines
2.5 KiB
C
144 lines
2.5 KiB
C
#include <linux/serial.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <termios.h>
|
|
#include <strings.h>
|
|
|
|
/* Driver-specific ioctls: */
|
|
#define TIOCGRS485 0x542E
|
|
#define TIOCSRS485 0x542F
|
|
|
|
struct serial_rs485 rs485conf;
|
|
struct termios options;
|
|
|
|
int fd;
|
|
unsigned char inbuf[16];
|
|
int bufp;
|
|
|
|
static uint16_t crc_ccitt_update(uint16_t crc, uint8_t data)
|
|
{
|
|
data ^= (crc & 0xFF);
|
|
data ^= data << 4;
|
|
|
|
return ((((uint16_t)data << 8) | ((crc >> 8) & 0xFF))
|
|
^ (uint8_t)(data >> 4) ^ ((uint16_t)data << 3));
|
|
}
|
|
|
|
int rs485_crc(unsigned char buf[16])
|
|
{
|
|
uint16_t crc;
|
|
int i;
|
|
|
|
if (buf[0] != 0xAA)
|
|
return -1;
|
|
if (buf[2] != buf[3])
|
|
return -1;
|
|
if (buf[4] != buf[5])
|
|
return -1;
|
|
|
|
crc = 0xFFFF;
|
|
for (i=0; i<14; i++)
|
|
crc = crc_ccitt_update(crc, buf[i]);
|
|
buf[14] = (crc >> 8) & 0xFF;
|
|
buf[15] = crc & 0xFF;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rs485_send(unsigned char buf[16])
|
|
{
|
|
return write(fd, buf, 16);
|
|
}
|
|
|
|
int rs485_recv(unsigned char buf[16])
|
|
{
|
|
int i;
|
|
if (bufp < 16)
|
|
return -1;
|
|
|
|
for (i=0;i<16;i++)
|
|
buf[i] = inbuf[i];
|
|
return 0;
|
|
}
|
|
|
|
int rs485_recv_loop(void)
|
|
{
|
|
int i;
|
|
unsigned char *p;
|
|
uint16_t crc;
|
|
|
|
if (bufp >=16)
|
|
bufp=0;
|
|
|
|
p = &(inbuf[bufp]);
|
|
|
|
if (read(fd, p, 1) < 0)
|
|
return -1;
|
|
|
|
bufp++;
|
|
|
|
if ((bufp == 1) && (inbuf[0] != 0xAA))
|
|
bufp = 0;
|
|
|
|
if ((bufp == 4) && (inbuf[2] != inbuf[3]))
|
|
bufp = 0;
|
|
|
|
if ((bufp == 6) && (inbuf[4] != inbuf[5]))
|
|
bufp = 0;
|
|
|
|
if (bufp == 16) {
|
|
crc = 0xFFFF;
|
|
|
|
for (i=0; i<14; i++)
|
|
crc = crc_ccitt_update(crc, inbuf[i]);
|
|
if ((inbuf[14] == ((crc >> 8) & 0xFF)) && (inbuf[15] == (crc & 0xFF)))
|
|
return 1;
|
|
else
|
|
bufp = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int rs485_close(void)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
int rs485_open(char *path)
|
|
{
|
|
fd = open (path, O_RDWR);
|
|
if (fd < 0) {
|
|
return -1;
|
|
}
|
|
|
|
rs485conf.flags |= SER_RS485_ENABLED;
|
|
rs485conf.flags |= (SER_RS485_RTS_ON_SEND);
|
|
rs485conf.flags |= (SER_RS485_RTS_AFTER_SEND);
|
|
//rs485conf.flags |= SER_RS485_RX_DURING_TX;
|
|
|
|
ioctl (fd, TIOCSRS485, &rs485conf);
|
|
|
|
bzero(&options, sizeof(options));
|
|
cfsetspeed(&options, B9600);
|
|
options.c_cflag &= ~PARENB;
|
|
options.c_cflag &= ~CSTOPB;
|
|
options.c_cflag &= ~CSIZE;
|
|
options.c_cflag |= CS8;
|
|
options.c_cflag |= (CLOCAL | CREAD);
|
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
|
options.c_oflag &= ~OPOST;
|
|
options.c_cc[VMIN] = 0;
|
|
options.c_cc[VTIME] = 1;
|
|
tcflush(fd,TCIOFLUSH);
|
|
tcsetattr(fd, TCSAFLUSH, &options);
|
|
|
|
return fd;
|
|
}
|