/* * Infypwr_PsuCommObj.c * * Created on: 2019年11月26日 * Author: 7564 */ #include "Infypwr_PsuCommObj.h" struct Current_cmd_Proc Psu_cmd={ 0, 0x02000200, 0x01000300, 0x01000400, 0x01000500, 0x01000600, 0x01000700, 0x01000800, 0x01000900, 0x02000A00, 0x02000B00, 0x01000C00, 0x02000F00, 0x02001000, 0x02001100, 0x02001200, 0x01001300, 0x02001400, 0x01001500, 0x01001600, 0x02001700, 0x01001800, 0x01001900, 0x01001A00, 0x02001B00, 0x0E001C00, }; //================================================ // Callback function //================================================ void GetPsuAddressReq(void *func) { get_psu_addr_req = func; } void RefreshStatus(void *func) { return_status = func; } void RefreshInputVol(void *func) { return_input_vol = func; } void RefreshGetOutput(void *func) { return_get_output = func; } void RefreshHWVersion(void *func) { //return_hw_version = func; } void RefreshAvailableCap(void *func) { return_available_cap = func; } void RefreshOutputPowerSwitch(void *func) { return_output_pow_switch = func; } //================================================ // CANBUS initialization //================================================ int InitCanBus() { int s0,nbytes; struct timeval tv; struct ifreq ifr0; struct sockaddr_can addr0; system("/sbin/ip link set can1 down"); system("/sbin/ip link set can1 type can bitrate 125000 restart-ms 100"); system("/sbin/ip link set can1 up"); s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW); tv.tv_sec = 0; tv.tv_usec = 10000; if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0) { #ifdef SystemLogMessage printf("Set SO_RCVTIMEO NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_RCVBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage printf("Set SO_RCVBUF NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage printf("Set SO_SNDBUF NG"); #endif } strcpy(ifr0.ifr_name, "can1" ); ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */ addr0.can_family = AF_CAN; addr0.can_ifindex = ifr0.ifr_ifindex; bind(s0, (struct sockaddr *)&addr0, sizeof(addr0)); return s0; } //================================================ // Receive Cmd from canbus //================================================ void ReceiveDataFromCanBus() { int nbytes; struct can_frame frame; int intCmd; byte target, group, address; while(1) { memset(&frame, 0, sizeof(struct can_frame)); nbytes = read(CanFd, &frame, sizeof(struct can_frame)); if (nbytes > 0) { frame.can_id = frame.can_id & CAN_EFF_MASK; intCmd = (uint) (frame.can_id & 0x003F0000); target = (byte) ((frame.can_id & 0x0000FF00)>>8); group = (word) ((frame.can_id & 0x03C00000)>>22); address = (byte) (frame.can_id & 0xFF); //if master id if(target == 0xF0) { //printf("Get-INFYPWR-Msg : %08x - %02x%02x%02x%02x%02x%02x%02x%02x\n", frame.can_id,frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7]); //printf("Get-INFYPWR-Msg : %08x cmd:%08x target:%02x group:%02x address:%02x\n", frame.can_id, intCmd, target, group, address); switch (intCmd) { case INFYPWR_GET_TOTAL_MOULE_MSG: { byte Quantity; char sn[7]; Quantity = frame.data[2]; for (byte index = 0; index < Quantity; index++) { memcpy(sn, (char *)"INFY00", 6); sn[7] = index + 48; //sacii get_psu_addr_req((index), sn); } } break; case ACK_ADDRESS_ASSINGMENT: { } break; case INFYPWR_GET_STATUS_MSG: { //英飛源狀態 (如果是使用 Group 命令發問模組會使用 Group 命令回覆) if(group == 0x0B) { //data[2] = group //data[4] = temp //data[5,6,7] = alarm return_status(frame.data[2], address,frame.data[4], (((int) frame.data[5] << 16) + ((int) frame.data[6] << 8) + (int) frame.data[7]) & 0x00ffffff); } } break; case INFYPWR_GET_PRESENT_INPUT_VOLTAGE_MSG: { return_input_vol(address, ((word) frame.data[0] * 256 ) + (word) frame.data[1], ((word) frame.data[2] * 256 ) + (word) frame.data[3], ((word) frame.data[4] * 256 ) + (word) frame.data[5]); } break; case INFYPWR_GET_PRESENT_OUTPUT_MSG: { //英飛源狀態 (如果是使用 Group 命令發問模組會使用 Group 命令回覆) //電壓值及電流值 = 4byte 精度 0.001位(高位在byte0)(轉為CSU使用 0.1位) //if(group == 0x0B) //{ //uint vol = (((unit) frame.data[0] << 24) + ((unit) frame.data[1] << 16) + ((unit) frame.data[2] << 8) + (unit) frame.data[3])/100); //uint cur = (((unit) frame.data[4] << 24) + ((unit) frame.data[5] << 16) + ((unit) frame.data[6] << 8) + (unit) frame.data[7])/100); //vol = vol / 100; //cur = cur / 100; return_get_output(address, (word)((((unit) frame.data[0] << 24) + ((unit) frame.data[1] << 16) + ((unit) frame.data[2] << 8) + (unit) frame.data[3])/100), (word)((((unit) frame.data[4] << 24) + ((unit) frame.data[5] << 16) + ((unit) frame.data[6] << 8) + (unit) frame.data[7])/100)); //} } break; case INFYPWR_GET_AVAILABLE_CAP_MSG: { //英飛源狀態 (如果是使用 Group 命令發問模組會使用 Group 命令回覆) if(group == 0x0B) { //英飛源單位 //最大電壓 1:1 (CSU使用是0.1位所以 X 10) //最小電壓 1:1 (CSU使用是0.1位所以 X 10) //電流 0.1位 (CSU使用是0.1位單位一樣) //功率 0.01位 (CSU使用是0.1位所以再除 10) return_available_cap(address, ((((word) frame.data[0] * 256) + (word) frame.data[1]) * 10), ((((word) frame.data[2] * 256) + (word) frame.data[3]) * 10), (((word) frame.data[4] * 256) + (word) frame.data[5]), ((((word) frame.data[6] * 256) + (word) frame.data[7]))/10); } } break; case INFYPWR_SET_POWER_SWITCH_MSG: { return_output_pow_switch(address, frame.data[0]); } break; case ACK_SET_PRESENT_OUTPUT: { } break; } } } else { } usleep(10000); } } //================================================ // Private Function //================================================ void SendCmdToPsu(int cmd, byte *data, byte dataLen) { struct can_frame frame; //設定 CANBSU 2.0B 長封包 cmd = cmd | 0x80000000; frame.can_id = cmd; frame.can_dlc = dataLen; memcpy(frame.data, data, dataLen); write(CanFd, &frame, sizeof(struct can_frame)); } //================================================ // API Function //================================================ bool InitialCommunication() { CanFd = InitCanBus(); if(CanFd < 0) { printf("Init can bus fail.\n"); return false; } recFork = fork(); if(recFork > 0) { ReceiveDataFromCanBus(); } else if(recFork > 0) { printf("fork fail\n"); } return true; } void RequestModuleTotalMumbert(void) { uint cmd = INFYPWR_MODULE_CMD | INFYPWR_GET_TOTAL_MOULE_MSG | (INFYPWR_BROADCAST_ID << 8) | INFYPWR_MASTER_TXID; byte data[8]; memset(data, 0x00, ARRAY_SIZE(data)); SendCmdToPsu(cmd, data, sizeof(data)); } //void PsuAddressAssignment(byte phy_addr, char *serial_number, byte real_addr, byte group) void PsuAddressAssignment(byte phy_addr, byte group) { uint cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_GROUP_ASSINGMENT_MSG | (phy_addr << 8) | INFYPWR_MASTER_TXID; byte data[8]; memset(data, 0x00, ARRAY_SIZE(data)); data[0] = group; SendCmdToPsu(cmd, data, sizeof(data)); } void GetStatus(byte group, byte address) { //如果用 group 發送 (該 group 內的模組會自動依序回應) //printf("PSU_C_DLL : GetStatus. group = %x, address = %x \n", group, address); uint cmd; byte data[8]; //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_GET_STATUS_MSG | (address << 8) | INFYPWR_MASTER_TXID; } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_GET_STATUS_MSG | (address << 8) | INFYPWR_MASTER_TXID; } memset(data, 0x00, ARRAY_SIZE(data)); SendCmdToPsu(cmd, data, sizeof(data)); } void GetFwVersion(byte group, byte address, byte type) { } void GetSerialNumber(byte group, byte address) { } void GetAvailableCap(byte group, byte address, short _outputVol) { //如果用 group 發送 (該 group 內的模組會自動依序回應) uint cmd; byte data[8]; //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_GET_AVAILABLE_CAP_MSG | (address << 8) | INFYPWR_MASTER_TXID; } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_GET_AVAILABLE_CAP_MSG | (address << 8) | INFYPWR_MASTER_TXID; } memset(data, 0x00, ARRAY_SIZE(data)); SendCmdToPsu(cmd, data, sizeof(data)); } void GetPresentInputVol(byte group, byte address) { //printf("PSU_C_DLL : GetPresentInputVol. group = %x, address = %x \n", group, address); //如果用 group 發送 (該 group 內的模組會自動依序回應) uint cmd; byte data[8]; //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_GET_PRESENT_INPUT_VOLTAGE_MSG | (address << 8) | INFYPWR_MASTER_TXID; } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_GET_PRESENT_INPUT_VOLTAGE_MSG | (address << 8) | INFYPWR_MASTER_TXID; }; memset(data, 0x00, ARRAY_SIZE(data)); SendCmdToPsu(cmd, data, sizeof(data)); } void GetPresentOutput(byte group, byte address) { //printf("PSU_C_DLL : GetPresentOutput. group = %x, address = %x \n", group, address); int cmd; byte data[8]; //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_GET_PRESENT_OUTPUT_MSG | (address << 8) | INFYPWR_MASTER_TXID; } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_GET_PRESENT_OUTPUT_MSG | (address << 8) | INFYPWR_MASTER_TXID; } memset(data, 0x00, ARRAY_SIZE(data)); SendCmdToPsu(cmd, data, sizeof(data)); } void SetPresentOutput(byte group, byte address, float vol, float cur, float AvailableCur) { uint cmd; byte data[8]; //bool isSearch = false; //if (cur >= AvailableCur) //cur = AvailableCur; //if(vol == 0 && cur == 0)printf("output v=0 a =0 \n"); printf("group = %d, address = %d, vol = %f, cur = %f \n", group, address, vol, cur); //英飛源使用 0.001 精度 uint vol2 = vol * 100; uint cur2 = cur * 100; printf("vol = %f, cur = %f, vol2 = %d, cur2 = %d \n", vol, cur, vol2, cur2); // 電壓 data[0] = (vol2 >> 24) & 0xff; data[1] = (vol2 >> 16) & 0xff; data[2] = (vol2 >> 8) & 0xff; data[3] = vol2 & 0xff; // 電壓 data[4] = (cur2 >> 24) & 0xff; data[5] = (cur2 >> 16) & 0xff; data[6] = (cur2 >> 8) & 0xff; data[7] = cur2 & 0xff; //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_GROUP_PERSENT_OUTPUT_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("setout(G) :%08x /n",cmd); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { //search group /* for (byte groupIndex = 0; groupIndex < ShmPsuData->GroupCount; groupIndex++) { for (byte index = 0; index < ShmPsuData->PsuGroup[groupIndex].GroupPresentPsuQuantity; index++) { //search id if (ShmPsuData->PsuGroup[groupIndex].PsuModule[index].Address == address) { //修改英飛為 id address = ShmPsuData->PsuGroup[groupIndex].PsuModule[index].PhysicalID; isSearch = true; break; } } if(isSearch) break; } */ cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_MODULE_PERSENT_OUTPUT_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("setout(M) :%08x /n",cmd); } printf("typecmd = %02x, addr = %02x ,vol = %d, tot_Amp = %f, need_cur = %d, \n", group, address, vol2, AvailableCur, cur2); SendCmdToPsu(cmd, data, sizeof(data)); } void EnableGreenLedFlash(byte group, byte address, byte value) { int cmd; byte data[8]; if(value){ //pwr off data[0] = 0x01; }else{ //pwr on data[0] = 0x00; } //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_GREEN_KED_FLASH_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("Green Led Flash(g) :%08x - %d - %d \n",cmd, data[0],address); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_GREEN_KED_FLASH_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("Green Led Flash(M) :%08x - %d - %d \n",cmd, data[0],address); } SendCmdToPsu(cmd, data, sizeof(data)); } void EnableWalkInMode(byte group, byte address, byte value) { int cmd; byte data[8]; if(value){ //pwr off data[0] = 0x01; }else{ //pwr on data[0] = 0x00; } //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_WALKIN_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("WalkIn(g) :%08x - %d - %d \n",cmd, data[0],address); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_WALKIN_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; // printf("WalkIn(M) :%08x - %d - %d \n",cmd, data[0],address); } SendCmdToPsu(cmd, data, sizeof(data)); } void EnableSleepMode(byte group, byte address, byte value) { int cmd; byte data[8]; if(value){ //pwr off data[0] = 0x01; }else{ //pwr on data[0] = 0x00; } //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_SLEEP_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("SleepMode(g) :%08x - %d - %d \n",cmd, data[0],address); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_SLEEP_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("SleepMode(M) :%08x - %d - %d \n",cmd, data[0],address); } SendCmdToPsu(cmd, data, sizeof(data)); } void EnableDipAddrMode(byte group, byte address, byte value) { int cmd; byte data[8]; if(value){ //pwr off data[0] = 0x01; }else{ //pwr on data[0] = 0x00; } //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_ADDRESS_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("DipAddrMode(g) :%08x - %d - %d \n",cmd, data[0],address); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_ADDRESS_MODE_MSG | (address << 8) | INFYPWR_MASTER_TXID; // printf("DipAddrMode(M) :%08x - %d - %d \n",cmd, data[0],address); } SendCmdToPsu(cmd, data, sizeof(data)); } void EnableOutputPower(byte group, byte address, byte value) { int cmd; byte data[8]; //printf("cmd = %x \n", cmd); memset(data, 0x00, ARRAY_SIZE(data)); if(value == 0){ //pwr off data[0] = 0x01; }else{ //pwr on data[0] = 0x00; } //如果是群組命令 if(group == SET_GROUP_CMD) { cmd = INFYPWR_GROUP_CMD | INFYPWR_SET_POWER_SWITCH_MSG | (address << 8) | INFYPWR_MASTER_TXID; //printf("Module-onoff(g) :%08x - %d - %d \n",cmd, data[0],address); } //如果是模組命令則找出模組對應到 (英飛源的ID) else { cmd = INFYPWR_MODULE_CMD | INFYPWR_SET_POWER_SWITCH_MSG | (address << 8) | INFYPWR_MASTER_TXID; // printf("Modele-onoff(M) :%08x - %d - %d \n",cmd, data[0],address); } SendCmdToPsu(cmd, data, sizeof(data)); }