1.CAN通信是实现不同目标板之间的通信,因此需要相同的时钟频率。因此需要进行时钟配置,一般在configPll中进行配置。进行倍频,分频处理等,得到合适的波特率。
2.CAN通信流程:
CAN_INIT();
对CAN进行初始化配置,包括模式,中断等,一般为接收中断。
CAN_Exception();
CAN中断处理,接收中断,按照CAN的帧传输方式接收数据。
void CAN2_Exception(void) {
CAN2ICR &= ~0x0001;
OS_ENTER_CRITICAL(); pDest = (uint32 *)&MsgBuf_RX2[CanFrameCount]; *pDest = CAN2RFS; // Frame pDest++; *pDest = CAN2RID; // ID pDest++; *pDest = CAN2RDA; // Data A pDest++; *pDest = CAN2RDB; // Data B CAN2CMR = 0x04; VICVectAddr = 0; OS_EXIT_CRITICAL();
}
3.CAN接收滤波器特性:
分为三种:关闭模式,旁路模式,工作模式和FullCAN模式。
一般使用旁路模式,即广播模式。
CAN 模式选择函数:
void CAN_SetACCF( uint32 ACCFMode ) { switch ( ACCFMode ) { case ACCF_OFF: CAN_AFMR = ACCFMode; CAN1MOD = CAN2MOD = 1; // Reset CAN CAN1IER = CAN2IER = 0; // Disable Receive Interrupt CAN1GSR = CAN2GSR = 0; // Reset error counter when CANxMOD is in reset break; case ACCF_BYPASS: CAN_AFMR = ACCFMode; break;
case ACCF_ON: case ACCF_FULLCAN: CAN_AFMR = ACCF_OFF; CAN_SetACCF_Lookup(); //Fu'llCAN模式,由验收滤波器来访问,硬件验收过滤。需要进行ID查找。 CAN_AFMR = ACCFMode; break; default: break; } return; }
Fu'llCAN模式下,ID的查找函数:
void CAN_SetACCF_Lookup( void ) { uint32 address = 0; uint32 i; uint32 ID_high, ID_low; // Set explicit standard Frame CAN_SFF_SA = address; for ( i = 0; i < ACCF_IDEN_NUM; i += 2 ) { ID_low = (i << 29) | (EXP_STD_ID << 16); ID_high = ((i+1) << 13) | (EXP_STD_ID << 0); *((volatile uint32 *)(CAN_MEM_BASE + address)) = ID_low | ID_high; address += 4; } // Set group standard Frame CAN_SFF_GRP_SA = address; for ( i = 0; i < ACCF_IDEN_NUM; i += 2 ) { ID_low = (i << 29) | (GRP_STD_ID << 16); ID_high = ((i+1) << 13) | (GRP_STD_ID << 0); *((volatile uint32 *)(CAN_MEM_BASE + address)) = ID_low | ID_high; address += 4; } // Set explicit extended Frame CAN_EFF_SA = address; for ( i=0; i<ACCF_IDEN_NUM; i++) { ID_low = (i << 29) | (EXP_EXT_ID << 0); *((volatile uint32 *)(CAN_MEM_BASE + address)) = ID_low; address += 4; } // Set group extended Frame CAN_EFF_GRP_SA = address; for ( i = 0; i < ACCF_IDEN_NUM; i++ ) { ID_low = (i << 29) | (GRP_EXT_ID << 0); *((volatile uint32 *)(CAN_MEM_BASE + address)) = ID_low; address += 4; } // Set End of Table CAN_EOT = address; return; }
4,CAN2的发送函数:
INT32U CAN2_Send( CAN_MSG *pTxBuf ) { INT32U CANStatus; CANStatus = CAN2SR; if ( CANStatus & 0x00000004 ) { CAN2TFI1 = pTxBuf->Frame & 0xC00F0000; CAN2TID1 = pTxBuf->MsgID; CAN2TDA1 = pTxBuf->DataA; CAN2TDB1 = pTxBuf->DataB; CAN2CMR = 0x21; return ( TRUE ); } else if ( CANStatus & 0x00000400 ) { CAN2TFI2 = pTxBuf->Frame & 0xC00F0000; CAN2TID2 = pTxBuf->MsgID; CAN2TDA2 = pTxBuf->DataA; CAN2TDB2 = pTxBuf->DataB; CAN2CMR = 0x41; return ( TRUE ); } else if ( CANStatus & 0x00040000 ) { CAN2TFI3 = pTxBuf->Frame & 0xC00F0000; CAN2TID3 = pTxBuf->MsgID; CAN2TDA3 = pTxBuf->DataA; CAN2TDB3 = pTxBuf->DataB; CAN2CMR = 0x81; return ( TRUE ); } return ( FALSE ); }
5,注意:CAN的接收中断实现时,在接收到数据后,先关掉CAN中断使能,等数据处理完后,再打开CAN中断使能。这样做是防止CAN数据传输快,而导致之前接收到的数据未处理完,就接收到下一组数据。产生数据混乱。