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

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