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.
246 lines
3.7 KiB
C
246 lines
3.7 KiB
C
#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>
|
|
|
|
void send_ack(int addr) {
|
|
unsigned char buf[16];
|
|
|
|
buf[0] = 0xAA;
|
|
buf[1] = 2;
|
|
buf[2] = addr;
|
|
buf[3] = addr;
|
|
buf[4] = 1;
|
|
buf[5] = 1;
|
|
buf[6] = 0;
|
|
buf[7] = 0;
|
|
buf[8] = 0;
|
|
buf[9] = 0;
|
|
buf[10] = 0;
|
|
buf[11] = 0;
|
|
buf[12] = 0;
|
|
buf[13] = 0;
|
|
buf[14] = 0;
|
|
|
|
rs485_crc(buf);
|
|
rs485_send(buf);
|
|
}
|
|
|
|
void send_read_req(int addr, int channel) {
|
|
unsigned char buf[16];
|
|
|
|
buf[0] = 0xAA;
|
|
buf[1] = 0;
|
|
buf[2] = addr;
|
|
buf[3] = addr;
|
|
buf[4] = 1;
|
|
buf[5] = 1;
|
|
buf[6] = 0x40 + channel;
|
|
buf[7] = 0;
|
|
buf[8] = 0;
|
|
buf[9] = 0;
|
|
buf[10] = 0;
|
|
buf[11] = 0;
|
|
buf[12] = 0;
|
|
buf[13] = 0;
|
|
buf[14] = 0;
|
|
|
|
rs485_crc(buf);
|
|
rs485_send(buf);
|
|
}
|
|
|
|
void send_write_req(int addr, int channel, int data) {
|
|
unsigned char buf[16];
|
|
|
|
buf[0] = 0xAA;
|
|
buf[1] = 0;
|
|
buf[2] = addr;
|
|
buf[3] = addr;
|
|
buf[4] = 1;
|
|
buf[5] = 1;
|
|
buf[6] = 0x60 + channel + ((data & 0x300 ) >> 5);
|
|
buf[7] = data & 0xFF;
|
|
buf[8] = 0;
|
|
buf[9] = 0;
|
|
buf[10] = 0;
|
|
buf[11] = 0;
|
|
buf[12] = 0;
|
|
buf[13] = 0;
|
|
buf[14] = 0;
|
|
|
|
rs485_crc(buf);
|
|
rs485_send(buf);
|
|
}
|
|
|
|
void send_poll(void) {
|
|
unsigned char buf[16];
|
|
|
|
buf[0] = 0xAA;
|
|
buf[1] = 0;
|
|
buf[2] = 0;
|
|
buf[3] = 0;
|
|
buf[4] = 1;
|
|
buf[5] = 1;
|
|
buf[6] = 0;
|
|
buf[7] = 0;
|
|
buf[8] = 0;
|
|
buf[9] = 0;
|
|
buf[10] = 0;
|
|
buf[11] = 0;
|
|
buf[12] = 0;
|
|
buf[13] = 0;
|
|
buf[14] = 0;
|
|
|
|
rs485_crc(buf);
|
|
rs485_send(buf);
|
|
}
|
|
|
|
void mainloop(int fd) {
|
|
struct timeval timeout;
|
|
int rd;
|
|
fd_set rset;
|
|
fd_set wset;
|
|
fd_set eset;
|
|
int quit;
|
|
int alt;
|
|
int ret;
|
|
int req_dev;
|
|
int req_channel;
|
|
int req_data;
|
|
int req_write;
|
|
int ack_dev;
|
|
int dev_poll;
|
|
unsigned char rbuf[16];
|
|
|
|
alt = 0;
|
|
quit = 0;
|
|
req_dev = 0;
|
|
req_channel = 0;
|
|
ack_dev = 0;
|
|
dev_poll = 2;
|
|
|
|
while (!quit) {
|
|
FD_ZERO(&rset);
|
|
FD_ZERO(&wset);
|
|
FD_ZERO(&eset);
|
|
FD_SET(fd, &rset);
|
|
FD_SET(0, &rset);
|
|
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 40000;
|
|
|
|
rd = select(fd + 1, &rset, &wset, &eset, &timeout);
|
|
|
|
if (rd == 0) {
|
|
if (alt) {
|
|
send_poll();
|
|
alt = 0;
|
|
continue;
|
|
}
|
|
alt = 1;
|
|
|
|
if (ack_dev) {
|
|
send_ack(ack_dev);
|
|
ack_dev = 0;
|
|
continue;
|
|
}
|
|
|
|
if (req_dev) {
|
|
if (req_write)
|
|
send_write_req(req_dev, req_channel, req_data);
|
|
else
|
|
send_read_req(req_dev, req_channel);
|
|
req_dev = 0;
|
|
continue;
|
|
}
|
|
|
|
send_read_req(dev_poll, 0);
|
|
dev_poll++;
|
|
if (dev_poll > 126)
|
|
dev_poll = 2;
|
|
} else {
|
|
if (FD_ISSET(fd, &rset)) {
|
|
ret = rs485_recv_loop();
|
|
if (ret < 0)
|
|
exit(-1);
|
|
if (ret == 0)
|
|
continue;
|
|
|
|
rs485_recv(&rbuf);
|
|
|
|
if ((rbuf[1] == 1) && (rbuf[2] == 1))
|
|
ack_dev = rbuf[4];
|
|
|
|
if ((rbuf[2] == 1) && (rbuf[6] >= 0x40) && (rbuf[6] < 0x60)) {
|
|
printf ("R %d %d %d\n", rbuf[4], (rbuf[6] - 0x40) & 0x7, rbuf[7] + (((rbuf[6] - 0x40) & 0x18) << 5));
|
|
fflush(stdout);
|
|
}
|
|
continue;
|
|
}
|
|
if (FD_ISSET(0, &rset)) {
|
|
unsigned char a;
|
|
unsigned char ibuf[100];
|
|
int d, c, v;
|
|
unsigned char *p;
|
|
|
|
p = fgets(ibuf, 100, stdin);
|
|
if (p == NULL)
|
|
exit(-1);
|
|
|
|
sscanf(ibuf, "%c %d %d %d\n", &a, &d, &c, &v);
|
|
if (a == 'Q') {
|
|
quit = 1;
|
|
continue;
|
|
}
|
|
if (a == 'R') {
|
|
req_dev = d;
|
|
req_channel = c;
|
|
req_write = 0;
|
|
continue;
|
|
}
|
|
if (a == 'W') {
|
|
req_dev = d;
|
|
req_channel = c;
|
|
req_data = v;
|
|
req_write = 1;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
char *dev = "/dev/ttyS2";
|
|
int c;
|
|
|
|
int fd;
|
|
|
|
while ((c = getopt(argc, argv, "d:")) != -1)
|
|
switch (c) {
|
|
case 'd':
|
|
dev = optarg;
|
|
break;
|
|
}
|
|
|
|
fd = rs485_open(dev);
|
|
if (fd < 0) {
|
|
printf("RS485 open failed\n");
|
|
return -1;
|
|
}
|
|
|
|
mainloop(fd);
|
|
|
|
rs485_close();
|
|
|
|
return 0;
|
|
}
|