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.

773 lines
24 KiB
C++

1 year ago
// file: rs485.c
// serial port communiction
// rs485
// tc400 communication protocol
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#define FALSE -1
#define TRUE 0
#define uint16 unsigned short
#define uint8 unsigned char
const uint16 genpoly16 = 0x8408;
// crc table
const uint16 crc16_256_table[256] =
{
0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF,
0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C,0xDBE5,0xE97E,0xF8F7,
0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E,
0x9CC9,0x8D40,0xBFDB,0xAE52,0xDAED,0xCB64,0xF9FF,0xE876,
0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434,0x55BD,
0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E,0xFAE7,0xC87C,0xD9F5,
0x3183,0x200A,0x1291,0x0318,0x77A7,0x662E,0x54B5,0x453C,
0xBDCB,0xAC42,0x9ED9,0x8F50,0xFBEF,0xEA66,0xD8FD,0xC974,
0x4204,0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB,
0xCE4C,0xDFC5,0xED5E,0xFCD7,0x8868,0x99E1,0xAB7A,0xBAF3,
0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A,
0xDECD,0xCF44,0xFDDF,0xEC56,0x98E9,0x8960,0xBBFB,0xAA72,
0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9,
0xEF4E,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1,
0x7387,0x620E,0x5095,0x411C,0x35A3,0x242A,0x16B1,0x0738,
0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70,
0x8408,0x9581,0xA71A,0xB693,0xC22C,0xD3A5,0xE13E,0xF0B7,
0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76,0x7CFF,
0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324,0xF1BF,0xE036,
0x18C1,0x0948,0x3BD3,0x2A5A,0x5EE5,0x4F6C,0x7DF7,0x6C7E,
0xA50A,0xB483,0x8618,0x9791,0xE32E,0xF2A7,0xC03C,0xD1B5,
0x2942,0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD,
0xB58B,0xA402,0x9699,0x8710,0xF3AF,0xE226,0xD0BD,0xC134,
0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C,
0xC60C,0xD785,0xE51E,0xF497,0x8028,0x91A1,0xA33A,0xB2B3,
0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB,
0xD68D,0xC704,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232,
0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1,0x0D68,0x3FF3,0x2E7A,
0xE70E,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1,
0x6B46,0x7ACF,0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9,
0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9,0x8330,
0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1,0x0F78
};
// LSB-first transmission, the genpoly need be inversed.
// CRC-16 CCITT
// X^16 + X^12 + X^5 + 1
uint16 cal_crc(uint8 *data, int data_len, uint16 init_val_of_crc)
{
uint16 crc = init_val_of_crc;
while (data_len-- >0)
{
crc ^= *data ++;
crc = (crc >> 8) ^ crc16_256_table[crc & 255];
}
return crc;
}
int open_dev(char *Dev)
{
int fd = open( Dev, O_RDWR);
if (-1 == fd)
{
perror("Can't Open Serial Port");
return -1;
}
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
{
printf("Unable set to NONBLOCK mode");
return -1;
}
return fd;
}
// set serial speed
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, \
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = { 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, \
19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i=0; i<sizeof(speed_arr)/sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
{
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
// set serial port data, stop and crc bit.
int set_parity(int fd, int databits, int stopbits, int parity)
{
struct termios options;
if ( tcgetattr(fd, &options) != 0)
{
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
// data bit
switch (databits)
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; // Clear parity enable
options.c_iflag &= ~INPCK; // Enable parity checking
options.c_lflag &= 0; // add comment it's very important to set this parameter.
options.c_oflag &= ~OPOST; /*Output*/
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); // set odd parity
options.c_iflag |= INPCK; // disnable parity checking
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; // enable parity
options.c_cflag &= ~PARODD; // change into even
options.c_iflag |= INPCK; // disnable parity checking
break;
case 'S':
case 's': // as no parity
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
// set stop bit
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
// Set input parity option
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 150; // set time out for 15 seconds
options.c_cc[VMIN] = 0; // update the options and do it now
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
void config_s(int fd)
{
struct termios oldtio, newtio;
tcgetattr(fd, &oldtio);
memset(&newtio, 0, sizeof(newtio));
newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CSTOPB;
newtio.c_cflag &= ~CRTSCTS;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_iflag &= ~( IXON | IXOFF | IXANY );
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
}
int main(int argc, char **argv)
{
int nread;
int nwrite;
uint8 rev_buf[512];
uint8 send_buf[512];
uint8 user_name[11];
uint8 rev_tmp[39];
int send_len;
int rev_len;
uint16 send_crc;
uint16 rev_crc;
uint16 tmp_crc;
int i;
int num;
int tmp_num;
time_t seconds;
FILE *fp = 0;
int fd;
char *dev = "/dev/ttyS0";
// open serial port and set parameters
fd = open_dev(dev);
set_speed(fd,9600);
config_s(fd); // it's so important that we must face this.
if (set_parity(fd,8,1,'N') == FALSE)
{
printf("set parity error\n");
exit (0);
}
else
{
printf("set serial ok!\n");
}
// -------------------------------------------
// send cmd common part
// stx
send_buf[0] = 0xa5;
// ch (machine id)
send_buf[1] = 0x00;
send_buf[2] = 0x00;
send_buf[3] = 0x00;
send_buf[4] = 0x00;
while(1)
{
// print menu
printf("0. exit!\n");
printf("1. get counts.\n");
printf("2. get date/time.\n");
printf("3. get device network info.\n");
printf("4. get person info.\n");
printf("5. get records.\n");
printf("6. get fp template.\n");
printf("7. get configure.\n");
printf("\nplsease enter num: ");
scanf("%d", &num);
// num = 3;
switch(num)
{
// exit
case 0:
printf("exiting ..\n");
close(fd);
return 0;
break;
// get the num of the account
case 1:
// send cmd 0x3c
// send cmd
send_buf[5] = 0x3c;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x00;
// send_crc
send_crc = cal_crc(send_buf, 8, -1);
send_buf[8] = (uint8)(send_crc & 0xFF);
send_buf[9] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 10);
printf("send len: %d\n", send_len);
sleep(2);
// receive data
if((rev_len=read(fd, rev_buf, 512)) == -1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_buf[rev_len-1]*256 + rev_buf[rev_len-2]);
tmp_crc = cal_crc(rev_buf, (rev_len-2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
printf("-------------------------------------\n");
printf(" staffs: %d\n", ( rev_buf[9]*256*256 + \
rev_buf[10]*256 + \
rev_buf[11] ) );
printf(" fp: %d\n", ( rev_buf[12]*256*256 + \
rev_buf[13]*256 + \
rev_buf[14] ) );
printf(" records: %d\n", ( rev_buf[21]*256*256 + \
rev_buf[22]*256 + \
rev_buf[23] ) );
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
// get data/time
case 2:
// send cmd 0x38
// send cmd
send_buf[5] = 0x38;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x00;
// send_crc
send_crc = cal_crc(send_buf, 8, -1);
send_buf[8] = (uint8)(send_crc & 0xFF);
send_buf[9] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 10);
printf("send len: %d\n", send_len);
sleep(3);
// receive data
if((rev_len = read(fd, rev_buf, 512))==-1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_buf[rev_len-1]*256 + rev_buf[rev_len-2]);
tmp_crc = cal_crc(rev_buf, (rev_len - 2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
printf("-------------------------------------\n");
// date/time
printf(" date/time: 20%d/%02d/%02d \n %02d:%02d:%02d\n", \
rev_buf[9] , rev_buf[10], rev_buf[11], \
rev_buf[12], rev_buf[13], rev_buf[14]);
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
// get device net info
case 3:
// send cmd 0x3a
// send cmd
send_buf[5] = 0x3a;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x00;
// send_crc
send_crc = cal_crc(send_buf, 8, -1);
send_buf[8] = (uint8)(send_crc & 0xFF);
send_buf[9] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 10);
printf("send len: %d\n", send_len);
sleep(3);
// receive data
if((rev_len=read(fd, rev_tmp, 512)) == -1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_tmp[rev_len-1]*256 + rev_tmp[rev_len-2]);
tmp_crc = cal_crc(rev_tmp, (rev_len-2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
printf("-------------------------------------\n");
// ip addr
printf(" ip: %d.%d.%d.%d\n", \
rev_tmp[9] ,rev_tmp[10], \
rev_tmp[11], rev_tmp[12]);
// network mask
printf("network mask: %d.%d.%d.%d\n", \
rev_tmp[13] ,rev_tmp[14], \
rev_tmp[15], rev_tmp[16]);
// mac addr
printf(" mac: %02x:%02x:%02x:%02x:%02x:%02x\n", \
rev_tmp[17] ,rev_tmp[18], rev_tmp[19],\
rev_tmp[20], rev_tmp[21], rev_tmp[22]);
// gateway
printf(" gateway: %d.%d.%d.%d\n", \
rev_tmp[23] ,rev_tmp[24], \
rev_tmp[25], rev_tmp[26]);
// server addr
printf(" server: %d.%d.%d.%d\n", \
rev_tmp[27] ,rev_tmp[28], \
rev_tmp[29], rev_tmp[30]);
// limit
printf(" limit: %d\n", rev_tmp[31]);
// port
printf(" port: %d\n", rev_tmp[32]*256 + rev_tmp[33]);
// mode
printf(" mode: %d\n", rev_tmp[34]);
// dhcp
printf(" dhcp: %d\n", rev_tmp[35]);
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
// get person info.
case 4:
// send cmd 0x42
// send cmd
send_buf[5] = 0x42;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x02;
// data
send_buf[8] = 0x01;
send_buf[9] = 0x0c;
// send_crc
send_crc = cal_crc(send_buf, 10, -1);
send_buf[10] = (uint8)(send_crc & 0xFF);
send_buf[11] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 12);
printf("send len: %d\n", send_len);
sleep(1);
// receive data
if((rev_len=read(fd, rev_buf, 512)) == -1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_buf[rev_len-1]*256 + rev_buf[rev_len-2]);
tmp_crc = cal_crc(rev_buf, (rev_len-2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
tmp_num = rev_buf[9];
printf("-------------------------------------\n");
printf("=====================\n");
for(i=0; i<tmp_num; i++)
{
// user no
printf(" user no: %d%d%d%d%d\n", \
rev_buf[i*27+10], rev_buf[i*27+11], \
rev_buf[i*27+12], rev_buf[i*27+13], \
rev_buf[i*27+14] );
// passwd
if((rev_buf[i*27+16]*256 + rev_buf[i*27+17]) != 0)
{
printf(" passwd: \n");
}
else
{
printf(" passwd: %d\n", (rev_buf[i*27+16]*256 + \
rev_buf[i*27+17]) );
}
// card no
printf(" card no: %d\n", (rev_buf[i*27+18]*256*256 + \
rev_buf[i*27+19]*256 + rev_buf[i*27+20]));
// name
strncpy(user_name, &rev_buf[i*27+21], 10);
user_name[10] = '\0';
printf(" name: %s\n", user_name);
// dept
printf(" dept: %d\n", rev_buf[i*27+30]);
// group
printf(" group: %d\n", rev_buf[i*27+31]);
// mode
printf(" mode: %d\n", rev_buf[i*27+32]);
printf("=====================\n");
}
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
// get records
case 5:
// send cmd 0x40
// send cmd
send_buf[5] = 0x40;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x02;
// data
send_buf[8] = 0x01;
send_buf[9] = 0x19;
// send_crc
send_crc = cal_crc(send_buf, 10, -1);
send_buf[10] = (uint8)(send_crc & 0xFF);
send_buf[11] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 12);
printf("send len: %d\n", send_len);
sleep(1);
// receive data
if((rev_len=read(fd, rev_buf, 512)) == -1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_buf[rev_len-1]*256 + rev_buf[rev_len-2]);
tmp_crc = cal_crc(rev_buf, (rev_len-2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
tmp_num = rev_buf[9];
printf("-------------------------------------\n");
printf("=====================\n");
for(i=0; i<tmp_num; i++)
{
printf(" %d\n", i+1);
// user no
printf(" user no: %d%d%d%d%d\n", \
rev_buf[i*14+10], rev_buf[i*14+11],\
rev_buf[i*14+12], rev_buf[i*14+13], \
rev_buf[i*14+14] );
// date/time
seconds = rev_buf[i*14+15]*256*256*256 + \
rev_buf[i*14+16]*256*256 + \
rev_buf[i*14+17]*256 + \
rev_buf[i*14+18];
printf(" date/time: %d/%02d/%02d \n %02d:%02d:%02d\n",\
gmtime(&seconds)->tm_year+1930, gmtime(&seconds)->tm_mon+1, \
gmtime(&seconds)->tm_mday+1, gmtime(&seconds)->tm_hour, \
gmtime(&seconds)->tm_min, gmtime(&seconds)->tm_sec);
// bac no
printf(" bac no: %d\n", rev_buf[i*14+19]);
// record type
printf("record type: %d\n", rev_buf[i*14+20]);
printf("=====================\n");
}
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
// get fp template
case 6:
// send cmd 0x44
// send cmd
send_buf[5] = 0x44;
// send length
send_buf[6] = 0x00;
send_buf[7] = 0x06;
// data
send_buf[8] = 0x00;
send_buf[9] = 0x00;
send_buf[10] = 0x00;
send_buf[11] = 0x00;
send_buf[12] = 0x01;
send_buf[13] = 0x01;
// send_crc
send_crc = cal_crc(send_buf, 14, -1);
send_buf[14] = (uint8)(send_crc & 0xFF);
send_buf[15] = (uint8)(send_crc >> 8);
// send and rev data
// send data
send_len = write(fd, send_buf, 16);
printf("send len: %d\n", send_len);
sleep(2);
// receive data
if((rev_len=read(fd, rev_buf, 512)) == -1)
{
printf("read error!\n");
}
else
{
printf("rev len: %d\n", rev_len);
rev_crc = (rev_buf[rev_len-1]*256 + rev_buf[rev_len-2]);
tmp_crc = cal_crc(rev_buf, (rev_len-2), -1);
if (rev_crc==tmp_crc && rev_buf[6]==0)
{
printf("ack successful!\n");
printf("ack information, as follows:\n");
printf("-------------------------------------\n");
fp = fopen("template/1_1.anv", "wb");
printf(" writing fp template ..\n");
fwrite(&rev_buf[9], 1, 338, fp);
fclose(fp);
printf("-------------------------------------\n");
}
else
{
printf("ack failed!\n");
}
printf("\n");
}
break;
default:
printf("error num!\n");
break;
}
}
close(fd);
return 0;
}