#include "main.h" CAN_RXMessage canrx, cantx; uint8_t CAN_error = 0; uint8_t CANFrameReceiveFlag = 0, CANFrameSendFlag = 0; /****************************************************************************************************************************************** * 函数名称: sameBits() * 功能说明: 找到所有ID中相同位置值相同的位,比如所有ID的第10位都是0(或1)则返回值的第10位为1 * 输 入: * 输 出: * 注意事项: 无 ******************************************************************************************************************************************/ uint32_t sameBits(uint32_t std_id[], uint32_t std_n, uint32_t ext_id[], uint32_t ext_n) { uint32_t i, j; uint32_t mask = 0; for(i = 0; i < std_n; i++) std_id[i] = std_id[i] << 18; for(i = 0; i < std_n - 1; i++) { for(j = i + 1; j < std_n; j++) { mask |= std_id[i] ^ std_id[j]; } } for(i = 0; i < ext_n - 1; i++) { for(j = i + 1; j < ext_n; j++) { mask |= ext_id[i] ^ ext_id[j]; } } return ~mask; } void CANInit(void) { CAN_InitStructure CAN_initStruct; #if 0 //for CAN1 PORT_Init(PORTN, PIN16, FUNMUX0_CAN_RX, 1); //GPION.16 配置为CAN输入引脚 PORT_Init(PORTN, PIN15, FUNMUX1_CAN_TX, 0); //GPION.15 配置为CAN输出引脚 #else //for CAN0 PORT_Init(PORTN, PIN8, FUNMUX0_CAN_RX, 1); //GPION.8 配置为CAN输入引脚 PORT_Init(PORTN, PIN7, FUNMUX1_CAN_TX, 0); //GPION.7 配置为CAN输出引脚 #endif CAN_initStruct.Mode = CAN_MODE_NORMAL; CAN_initStruct.CAN_BS1 = CAN_BS1_5tq; CAN_initStruct.CAN_BS2 = CAN_BS2_4tq; CAN_initStruct.CAN_SJW = CAN_SJW_2tq; CAN_initStruct.Baudrate = CAN_BPS; CAN_initStruct.FilterMode = CAN_FILTER_32b; CAN_initStruct.FilterMask32b = 0xFFFFFFFF; CAN_initStruct.FilterCheck32b = 0xFFFFFFFF; switch(0) { case 0: // 接收ID为任意值的帧 CAN_initStruct.FilterMask32b = 0xFFFFFFFF; // 0 must match 1 don't care CAN_initStruct.FilterCheck32b = 0xFFFFFFFF; break; case 1: // 接收ID为0x122的标准帧 CAN_initStruct.FilterMask32b = ~(0x7FFu << 21); CAN_initStruct.FilterCheck32b = (0x122 << 21); // 标准帧ID在第21位到31位,详见手册 break; case 2: // 接收ID为0x122的扩展帧 CAN_initStruct.FilterMask32b = ~(0x1FFFFFFFu << 3); CAN_initStruct.FilterCheck32b = (0x00000122 << 3); // 扩展帧ID在第 3位到31位,详见手册 break; case 3: // 接收ID为0x12X的标准帧,X表示ID的低4位是什么值无所谓 CAN_initStruct.FilterMask32b = ~(0x7F0u << 21); CAN_initStruct.FilterCheck32b = (0x122 << 21); break; case 4: // 接收ID为0x122和0x101的标准帧 CAN_initStruct.FilterMode = CAN_FILTER_16b; CAN_initStruct.FilterMask16b1 = (uint16_t)~(0x7FFu << 5); CAN_initStruct.FilterCheck16b1 = (0x122 << 5); CAN_initStruct.FilterMask16b2 = (uint16_t)~(0x7FFu << 5); CAN_initStruct.FilterCheck16b2 = (0x101 << 5); break; case 5: // 即接收ID为0x122、0x235、0x450的标准帧,也接收ID为0x101, 0x235, 0x1780的扩展帧 { // 并不是只接收ID为这6个值的帧,而是接收尽量最少的帧、且能保证ID为要求值的帧都能接收到 uint32_t stdID[] = {0x122, 0x235, 0x450}; uint32_t extID[] = {0x101, 0x235, 0x1780}; CAN_initStruct.FilterMask32b = ~(sameBits(stdID, 3, extID, 3) << 3); CAN_initStruct.FilterCheck32b = (extID[0] << 3); // 或者: // CAN_initStruct.FilterCheck32b = (stdID[0] << 21); } break; } CAN_initStruct.RXNotEmptyIEn = 1; CAN_initStruct.RXOverflowIEn = 0; CAN_initStruct.ArbitrLostIEn = 0; CAN_initStruct.ErrPassiveIEn = 0; CAN_Init(CAN, &CAN_initStruct); NVIC_SetPriority(CAN_IRQn, 2); CAN_Open(CAN); } int CAN_SendMsg(CAN_RXMessage msg) { while(CAN_TXBufferReady(CAN) == 0) { DelayMs(1); } //单次发送 // CAN_Transmit(CAN, CAN_FRAME_EXT, msg.id, msg.data, msg.size, 1); // while(CAN_TXComplete(CAN) == 0){DelayMs(1);} //多次重发 CAN_error = 0; CAN_Transmit(CAN, CAN_FRAME_EXT, msg.id, msg.data, msg.size, 0); for(uint16_t i = 0; CAN_TXComplete(CAN) == 0; i++) { if(i > 100) { CAN_AbortTransmit(CAN); //超时,终止发送 CAN_error = 1; } DelayMs(1); } return CAN_TXSuccess(CAN); } void CAN_Handler(void) { uint32_t int_sr = CAN_INTStat(CAN); if(int_sr & CAN_IF_RXDA_Msk) { CAN_Receive(CAN, &canrx); CANFrameReceiveFlag = 1; } }