/* * Can_Driver.c * * Created on: 2021. 8. 3. * Author: KimJeongWoo */ #include sCanMsg CanaTxMbox1; sCanMsg CanaTxMbox2; sCanMsg CanbTxMbox; sCanMsg CanaRxMbox[32]; sCanMsg CanbRxMbox[32]; unsigned int TerminalResSet = 0xff; void InitCan() { // InitCanGpio(); CAN_initModule(CANA_BASE); CAN_initModule(CANB_BASE); CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 16); CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 16); CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0); CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0); CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0); CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0); //송신용 // CAN_setupMessageObject(CANA_BASE, 32, 0x000 + CanBe_TxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0x7FF, CAN_MSG_OBJ_USE_ID_FILTER, 8); // CAN_setupMessageObject(CANA_BASE, 31, 0x01F + CanBe_TxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0x7F0, CAN_MSG_OBJ_USE_ID_FILTER, 8); //수신용 // CAN_setupMessageObject(CANA_BASE, 1, 0x000 + CanBe_RxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x7FF, (CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER), 0); // CAN_setupMessageObject(CANA_BASE, 2, 0x01F + CanBe_RxId_Offset, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0x7F0, (CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER), 0); CAN_startModule(CANA_BASE); CAN_startModule(CANB_BASE); } int FlagCanReset = 0; /* bp_16 LEC:3; // 2:0 Last Error Code bp_16 TxOk:1; // 3 Transmission status bp_16 RxOk:1; // 4 Reception status bp_16 EPass:1; // 5 Error Passive State bp_16 EWarn:1; // 6 Warning State bp_16 BOff:1; // 7 Bus-Off State bp_16 PER:1; // 8 Parity Error Detected */ void CanErrorReset() { if ((CanaRegs.CAN_ES.bit.BOff == 1) || (CanaRegs.CAN_ES.bit.PER == 1)) { CAN_startModule(CANA_BASE); } if ((CanbRegs.CAN_ES.bit.BOff == 1) || (CanbRegs.CAN_ES.bit.PER == 1)) { CAN_startModule(CANB_BASE); } if (FlagCanReset == 1) { InitCan(); FlagCanReset = 0; } } //todo 일단은 std만.. 나중에 고칠 것 //ID 변경가능, DLC 변경 가능, Std 모드 void CanTxMsg(uint32_t base, uint32_t objID, sCanMsg *Msg) { uint32_t msgCtrl = 0U; uint32_t arbReg = 0U; HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t) CAN_IF1CMD_CONTROL | (objID & CAN_IF1CMD_MSG_NUM_M)); while ((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY); msgCtrl = HWREGH(base + CAN_O_IF1MCTL); arbReg = HWREGH(base + CAN_O_IF1ARB); // 데이터 길이 업데이트 msgCtrl &= ~CAN_IF1MCTL_DLC_M; msgCtrl |= (Msg->Lenth & CAN_IF1MCTL_DLC_M); HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl; //ID 업데이트 Id std. arbReg |= ((Msg->Id << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M) | CAN_IF1ARB_MSGVAL | CAN_IF1ARB_DIR; HWREG_BP(base + CAN_O_IF1ARB) = arbReg; HWREG_BP(base + CAN_O_IF1CMD) = (CAN_IF1CMD_CONTROL | CAN_IF1CMD_DIR | (objID & CAN_IF1CMD_MSG_NUM_M)); uint16_t Cnt = 0; uint16_t idx = 0; uint32_t dataReg = 0; //Data 주소위치 dataReg = (base + CAN_O_IF1DATA); //16bit 처리를 위한 인덱스 카운트 생성, 데이터길이가 홀수일 때 + 1 Cnt = ((Msg->Lenth * 0.5) + (Msg->Lenth % 2)); //MassageRam 영역에 데이터 쓰기 for (idx = 0U; idx < Cnt; idx++) { //HWREGH는16bit, HWREGB는 8bit HWREGH(dataReg) = Msg->Data.U16.Word[idx]; dataReg = dataReg + 2; } // Set Data to be transferred from IF if (Msg->Lenth > 0U) { msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A; } else { msgCtrl = 0U; } HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | (uint32_t) CAN_IF1CMD_DIR | CAN_IF1CMD_ARB | (uint32_t) CAN_IF1CMD_TXRQST | (objID & CAN_IF1CMD_MSG_NUM_M)); } bool CanRxMsg(uint32_t base, uint32_t objID, sCanMsg *Msg) { bool status; uint16_t msgCtrl = 0U; uint32_t idx; uint32_t dataReg; HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t) CAN_IF2CMD_DATA_A | (uint32_t) CAN_IF2CMD_DATA_B | (uint32_t) CAN_IF2CMD_CONTROL | (objID & CAN_IF2CMD_MSG_NUM_M) | (uint32_t) CAN_IF2CMD_ARB); while ((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY); msgCtrl = HWREGH(base + CAN_O_IF2MCTL); Msg->Lenth = (msgCtrl & CAN_IF2MCTL_DLC_M); if ((msgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT) { uint16_t Cnt; Cnt = ((Msg->Lenth * 0.5) + (Msg->Lenth % 2)); dataReg = (base + CAN_O_IF2DATA); for(idx = 0; idx < Cnt; idx++) { Msg->Data.U16.Word[idx] = HWREGH(dataReg); dataReg = dataReg + 2; } status = true; // // Now clear out the new data flag // HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t) CAN_IF2CMD_TXRQST | (objID & CAN_IF2CMD_MSG_NUM_M)); // // Wait for busy bit to clear // while ((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY); } else { status = false; } if (status == true) { if ((HWREG_BP(base + CAN_O_IF2ARB) & CAN_IF2ARB_XTD) != 0U) { *Msg->frameType = CAN_MSG_FRAME_EXT; Msg->Id = ((HWREG_BP(base + CAN_O_IF2ARB)) & CAN_IF2ARB_ID_M); } else { *Msg->frameType = CAN_MSG_FRAME_STD; Msg->Id = (((HWREG_BP(base + CAN_O_IF2ARB)) & CAN_IF2ARB_STD_ID_M) >> CAN_IF2ARB_STD_ID_S); } Msg->Cnt++; //정상적인 수신일 경우 카운트 } return (status); }