#include "Common/crc16.h" #include "rs485_wired_cell.h" //--------------------------------------------------------------------- #include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include #include /*Unix 标准函数定义*/ #include #include #include /*文件控制定义*/ #include /*PPSIX 终端控制定义*/ #include /*错误号定义*/ //#define EN_THREAD_WORK_DEBUG #ifdef EN_THREAD_WORK_DEBUG #define THREAD_WORK_DEBUG qDebug #else #define THREAD_WORK_DEBUG(...) #endif #define CMD_READ 0x00A0 #define CMD_SET_ADDR 0x00A2 #define CMD_ADJ_VOL 0x00A3 RS485_WIRED::RS485_WIRED(const char *Dev, int order) { AdjStart = 0; adj_index = 0; adj_vol = 0; adj_addr = 0; AdjStatue = 0; memset(battVolData,0x00,sizeof(battVolData)); Work_Order = order; Work_Num = 0; BattGroup = 0; EachGroupBattSum = 1; EachGroupModule = 1; if (-1 == this->OpenDev(Dev)) qDebug("Can't Open %s\n", Dev); else qDebug("Open %s OK!\n", Dev); this->SetDevAttr(19200, 8,1,'N'); com_error_count = 200; } RS485_WIRED::~RS485_WIRED() { RS485_RUN_EN =false; quit(); wait(); } //--------------------------------------------------------------------- //--------------------------------------------------------------------- /** *@brief 设置串口通信速率 *@param fd 类型 int 打开串口的文件句柄 *@param speed 类型 int 串口速度 *@return void */ //--------------------------------------------------------------------- //--------------------------------------------------------------------- static int speed_arr[] = { B115200, B57600, B38400, B19200, B9600}; static int name_arr[] = { 115200, 57600, 38400, 19200, 9600}; void RS485_WIRED::set_speed(int fd, int speed) { int status; struct termios Opt; tcgetattr(fd, &Opt); for ( unsigned int 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); } } } //--------------------------------------------------------------------- /** *@brief 设置串口数据位,停止位和效验位 *@param fd 类型 int 打开的串口文件句柄 *@param databits 类型 int 数据位 取值 为 7 或者8 *@param stopbits 类型 int 停止位 取值为 1 或者2 *@param parity 类型 int 效验类型 取值为N,E,O,,S */ //--------------------------------------------------------------------- int RS485_WIRED::set_Parity(int fd, int databits,int stopbits,int parity) { if(fd < 0) return -1; struct termios options; if(tcgetattr(fd, &options) != 0) { perror("SetupSerial 1"); return(-1); } //--------------- 二进制传输模式 ------------------------- options.c_iflag = 0; options.c_oflag = 0; //------------------------------------------------------ options.c_cflag &= ~CSIZE; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/*Input*/ options.c_oflag &= ~OPOST;/*Output*/ switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (-1); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'M': case 'm': /**/ options.c_cflag |= (PARENB|CMSPAR|PARODD); options.c_iflag |= INPCK; break; case 'S': case 's': /**/ options.c_cflag |= (PARENB|CMSPAR); options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; break; //case 'S': //case 's': /*as no parity*/ // options.c_cflag &= ~PARENB; // options.c_cflag &= ~CSTOPB; // break; default: fprintf(stderr,"Unsupported parity\n"); return (-1); } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return (-1); } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; tcflush(fd, TCIFLUSH); options.c_cc[VTIME] = 0; /* 0.1S */ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("SetupSerial 3"); return (-1); } return (0); } //--------------------------------------------------------------------- int RS485_WIRED::OpenDev(const char *Dev) { FD = open(Dev, O_RDWR|O_NOCTTY|O_NDELAY); return FD; } //--------------------------------------------------------------------- void RS485_WIRED::SetDevAttr(int bitrate, char bitlen, char stopbitlen, char checktype) { if(FD < 0) return; set_speed(FD, bitrate); if(set_Parity(FD, bitlen, stopbitlen, checktype) < 0) { qDebug("Set Parity Error\n"); } if(fcntl(FD, F_SETFL, FNDELAY) < 0)//非阻塞,覆盖前面open的属性 { qDebug("fcntl failed\n"); } } //--------------------------------------------------------------------- int RS485_WIRED::WriteDev(void *buf, int len) { if(FD < 0) return 0; return write(FD, (char *)buf, len); } //--------------------------------------------------------------------- int RS485_WIRED::ReadDev(void *buf, int len) { if(FD < 0) return 0; char *pbuff = (char *)buf; return (read(FD, pbuff, len)); } bool RS485_WIRED::ReadData(void *RxData, const int RxDataLen) { bool res = true; quint16 rx_len = 0; quint8 rx_dat_t = 0; quint16 rx_time_out = 0; quint8 *p_rxdata = (quint8 *)RxData; while(RxDataLen > 0) { while(1 == ReadDev(&rx_dat_t, 1)) { //qDebug("%x-",rx_dat_t); rx_time_out = 0; if(rx_len < RxDataLen) { p_rxdata[rx_len++] = rx_dat_t; if(rx_len >= RxDataLen) break; } else break; } if(rx_len >= RxDataLen) break; else if(rx_len > 0) { if(rx_time_out > 10) { res = false; break; } } else { //if(rx_time_out > 40) { res = false; break; } } rx_time_out++; msleep(5); } return res; } void RS485_WIRED::ReadWiredData(quint8 Addr) { RFData data_buf; Rx_Data_RF temp; bool read_success = false; for(int i=0;i<5;i++) { memset(&data_buf,0,sizeof(data_buf)); data_buf.Addr[0] = 0xAB; data_buf.Addr[1] = 0xCD; data_buf.Addr[2] = 0x00; data_buf.Addr[3] = Addr+1; data_buf.CMD = CMD_READ; data_buf.CRC = CRC16::CalCRC16(&data_buf,14); SentAddrData(&data_buf.Addr[3],&data_buf,sizeof(data_buf)); msleep(80); memset(&data_buf,0,sizeof(data_buf)); memset(&temp,0,sizeof(temp)); for(int i=0;i<4;i++) temp.VolData[i] = 20000; temp.Addr = Addr+1; if(ReadData(&data_buf,sizeof(data_buf))) { if(data_buf.CRC == CRC16::CalCRC16(&data_buf,14)) { memcpy(temp.VolData,data_buf.VolData,8); read_success = true; break; } else { THREAD_WORK_DEBUG("addr=%d CRC ERR",Addr+1); } } else { THREAD_WORK_DEBUG("addr=%d read err",temp.Addr); } msleep(80); } ClassXML::set_battVolData(Addr,temp.VolData,battVolData,Work_Order, EachGroupBattSum,EachGroupModule,BattGroup); if(read_success) com_error_count = 0; else { if(com_error_count<200) com_error_count++; } } quint8 RS485_WIRED::isOdd(quint8 Addr) { quint8 cnt = 0; /*quint8 cnt1 = 0; for(int i=0;i<8;i++) { if(Addr & (0x01< 0) continue; else break; } } void RS485_WIRED::setWorkNum(int num_g,int num_eachm){ BattGroup = num_g; EachGroupBattSum = num_eachm; if((EachGroupBattSum%4) == 0) EachGroupModule = EachGroupBattSum/4; else EachGroupModule = EachGroupBattSum/4 + 1; Work_Num = EachGroupModule*num_g; } void RS485_WIRED::setWorkParam(int param1){ //编号顺序、频段 Work_Order = param1; memset(battVolData,0x00,sizeof(battVolData)); } void RS485_WIRED::GetBattVolData(void *data) { memcpy(data,battVolData,sizeof(battVolData)); } bool RS485_WIRED::if_com_normal() { // qDebug("com_error_count = %d",com_error_count); if(com_error_count= Work_Num) return AdjStatue; RFData data_buf; data_buf.Addr[0] = 0xAB; data_buf.Addr[1] = 0xCD; data_buf.Addr[2] = 0x00; data_buf.Addr[3] = addr_index+1; data_buf.CMD = CMD_ADJ_VOL; for(int i=0;i<4;i++) data_buf.VolData[i] = 0; ClassXML::set_addr_VolData(addr_index,data_buf.VolData,battVolData,Work_Order,EachGroupBattSum,EachGroupModule,BattGroup); for(int i=0;i<4;i++) data_buf.VolData[i] = ClassXML::getMonomerVol(MONO_TYPE_WIRED,data_buf.VolData[i]); ClassXML::set_adj_vol(addr_index,index,data_buf.VolData,vol, Work_Order,EachGroupBattSum,EachGroupModule); data_buf.CRC = CRC16::CalCRC16(&data_buf,14); SentAddrData(&data_buf.Addr[3],&data_buf,sizeof(data_buf)); //for(int i=0;i<16;i++) // qDebug("0x%x",*((char *)&data_buf + i)); msleep(80); memset(&data_buf,0,sizeof(data_buf)); Rx_Data_RF temp; memset(&temp,0,sizeof(temp)); temp.Addr = addr_index+1; if(ReadData(&data_buf,sizeof(data_buf))) { if(data_buf.CRC == CRC16::CalCRC16(&data_buf,14)) { memcpy(temp.VolData,data_buf.VolData,8); AdjStatue = 0; //AddDataTemp(temp); THREAD_WORK_DEBUG("addr=%d-%d-%d-%d-%d",temp.Addr,temp.VolData[0],temp.VolData[1],temp.VolData[2],temp.VolData[3]); } else { AdjStatue = -1; THREAD_WORK_DEBUG("ReadWiredData CRC ERR"); } } else { AdjStatue = -1; THREAD_WORK_DEBUG("adj addr=%d read err",temp.Addr); } //for(int i=0;i<16;i++) // qDebug("0x%x",*((char *)&data_buf + i)); return AdjStatue; } int RS485_WIRED::AdjMonoAddr(const quint8 Addr) { AdjStatue = 0; RFData data_buf; data_buf.Addr[0] = 0xAB; data_buf.Addr[1] = 0xCD; data_buf.Addr[2] = 0x00; data_buf.Addr[3] = 0x00; data_buf.CMD = CMD_SET_ADDR; data_buf.VolData[0] = 0xCDAB; data_buf.VolData[1] = Addr<<8; data_buf.VolData[2] = 0x00; data_buf.VolData[3] = 0x00; data_buf.CRC = CRC16::CalCRC16(&data_buf,14); SentAddrData(&data_buf.Addr[3],&data_buf,sizeof(data_buf)); //for(int i=0;i<16;i++) // qDebug("0x%x",*((char *)&data_buf + i)); msleep(80); memset(&data_buf,0,sizeof(data_buf)); if(ReadData(&data_buf,sizeof(data_buf))) { if(data_buf.CRC == CRC16::CalCRC16(&data_buf,14)) { if(data_buf.CMD == CMD_SET_ADDR && data_buf.Addr[3] == Addr) { if(Addr>=1){ //数据清零 Rx_Data_RF temp; memset(&temp,0,sizeof(temp)); temp.Addr = Addr; ClassXML::set_battVolData(Addr-1,temp.VolData,battVolData,Work_Order, EachGroupBattSum,EachGroupModule,BattGroup); } } } else { AdjStatue = -1; THREAD_WORK_DEBUG("ReadWiredData CRC ERR"); } } else { AdjStatue = -1; THREAD_WORK_DEBUG("adj addr=%d read err",Addr); } //for(int i=0;i<16;i++) // qDebug("0x%x",*((char *)&data_buf + i)); return AdjStatue; }