CAN通信机制

xiaoxiao2021-02-28  86

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数据传输快,而导致之前接收到的数据未处理完,就接收到下一组数据。产生数据混乱。

转载请注明原文地址: https://www.6miu.com/read-32449.html

最新回复(0)