?? can.c
字號:
/*****************************************************************************
* can.c: CAN module API file for NXP LPC23xx/24xx Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2006.09.13 ver 1.00 Prelimnary version, first Release
*
*****************************************************************************/
#include <target.h>
#include <can.h>
// Receive Queue: one queue for each CAN port
extern CAN_MSG MsgBuf_RX1, MsgBuf_RX2;
extern volatile uint32_t CAN1RxDone, CAN2RxDone;
struct PASSTHRU_MSG passthru_msg;
uint32_t CANStatus;
CAN_MSG First_Frame_buff[4];
uint8_t First_Frame_insert_idx,First_Frame_extract_idx;
uint8_t First_Keep = 0;
CAN_MSG can1_rx_buff[64];
uint16_t can1_rx_insert_idx, can1_rx_extract_idx;
uint32_t CAN1RxCount = 0, CAN2RxCount = 0;
uint32_t CAN1ErrCount = 0, CAN2ErrCount = 0;
extern uint32_t EXT_ID[2];
volatile uint8_t CAN1RX_ID = 0;
/******************************************************************************
** Function name: CAN_ISR_Rx1
**
** Descriptions: CAN Rx1 interrupt handler
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void CAN_ISR_Rx1( void )
{
uint32_t * pDest;
// initialize destination pointer
pDest = (uint32_t *)&MsgBuf_RX1;
*pDest = CAN1RFS; // Frame
pDest++;
*pDest = CAN1RID; // ID //change by gongjun
pDest++;
*pDest = CAN1RDA; // Data A
pDest++;
*pDest = CAN1RDB; // Data B
CAN1RxDone = TRUE;
CAN1CMR = 0x04; // release receive buffer
CAN1RX_ID = 1;
return;
}
/******************************************************************************
** Function name: CAN_ISR_Rx2
**
** Descriptions: CAN Rx2 interrupt handler
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void CAN_ISR_Rx2( void )
{
uint32_t *pDest;
uint32_t temp;
uint32_t Frame_Type;
RX_LED_ON;
temp = CAN2RDA;
Frame_Type = (temp>> 4) & 0x0000000f;
if(Frame_Type == 1) //First Frame
{
if(!First_Keep)
{
temp = (can1_rx_insert_idx + 1) % 64;
can1_rx_buff[can1_rx_insert_idx].Frame = CAN2RFS;
can1_rx_buff[can1_rx_insert_idx].MsgID = CAN2RID;
can1_rx_buff[can1_rx_insert_idx].DataA = CAN2RDA;
can1_rx_buff[can1_rx_insert_idx].DataB = CAN2RDB;
if(temp != can1_rx_extract_idx)
can1_rx_insert_idx = temp;
First_Keep = 1;
passthru_msg_index = 0;
}
else
{
temp = (First_Frame_insert_idx + 1) % 4;
First_Frame_buff[First_Frame_insert_idx].Frame = CAN2RFS;
First_Frame_buff[First_Frame_insert_idx].MsgID = CAN2RID;
First_Frame_buff[First_Frame_insert_idx].DataA = CAN2RDA;
First_Frame_buff[First_Frame_insert_idx].DataB = CAN2RDB;
if(temp != First_Frame_extract_idx)
First_Frame_insert_idx = temp;
}
}
// else if(Frame_Type == 2)
// {
// passthru_msg_data[passthru_msg_index++] = CAN2RDA;
// passthru_msg_data[passthru_msg_index++] = CAN2RDB;
// passthru_fc_cnt --;
// }
else
{
temp = (can1_rx_insert_idx + 1) % 64;
can1_rx_buff[can1_rx_insert_idx].Frame = CAN2RFS;
can1_rx_buff[can1_rx_insert_idx].MsgID = CAN2RID;
can1_rx_buff[can1_rx_insert_idx].DataA = CAN2RDA;
can1_rx_buff[can1_rx_insert_idx].DataB = CAN2RDB;
if(temp != can1_rx_extract_idx)
can1_rx_insert_idx = temp;
}
/* pDest = (uint32_t *)&MsgBuf_RX2;
*pDest = CAN2RFS; // Frame
pDest++;
*pDest = CAN2RID; // ID
pDest++;
*pDest = CAN2RDA; // Data A
*pDest = Reverse(*pDest);
pDest++;
*pDest = CAN2RDB; // Data B
*pDest = Reverse(*pDest);
*/
CAN2RxDone = TRUE;
CAN2CMR = 0x04; // release receive buffer
return;
}
/*****************************************************************************
** Function name: CAN_Handler
**
** Descriptions: CAN interrupt handler
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void CAN_Handler(void)
{
// perform proper ISR entry so thumb-interwork works properly
ISR_ENTRY();
CANStatus = CAN_RX_SR;
if ( CANStatus & (1 << 8) )
{
CAN1RxCount++;
CAN_ISR_Rx1();
}
if ( CANStatus & (1 << 9) )
{
CAN2RxCount++;
CAN_ISR_Rx2();
}
if ( CAN1GSR & (1 << 6 ) )
{
/* The error count includes both TX and RX */
CAN1ErrCount = (CAN1GSR >> 16 );
}
if ( CAN2GSR & (1 << 6 ) )
{
/* The error count includes both TX and RX */
CAN2ErrCount = (CAN2GSR >> 16 );
}
VICVectAddr = 0; /* Acknowledge Interrupt */
ISR_EXIT(); // recover registers and return
return;
}
/******************************************************************************
** Function name: CAN_Init
**
** Descriptions: Initialize CAN, install CAN interrupt handler
**
** parameters: bitrate
** Returned value: true or false, false if initialization failed.
**
******************************************************************************/
uint32_t CAN_Init( uint32_t can_btr )
{
CAN1RxDone = CAN2RxDone = FALSE;
can1_rx_extract_idx = can1_rx_insert_idx = 0;
PCONP |= (1 << 13) | (1 << 14); // Enable clock to the peripheral
PINSEL0 &= ~0x00000F0F;
PINSEL0 |= 0x0000A05; // port0.0~1, function 0x01, port0.4~5, function 0x10
CAN1MOD = CAN2MOD = 1; // Reset CAN
CAN1IER = CAN2IER = 0; // Disable Receive Interrupt
CAN1GSR = CAN2GSR = 0; // Reset error counter when CANxMOD is in reset
CAN1BTR = CAN2BTR = can_btr;
CAN1MOD = CAN2MOD = 0x04; // CAN in normal operation mode
// Install CAN interrupt handler
install_irq( 23, (void *)CAN_Handler, 4 );
// CAN1IER = CAN2IER = 0x01; // Enable receive interrupts
CAN1IER = 0x01; // Enable receive interrupts
CAN_SetACCF( ACCF_BYPASS );
return( TRUE );
}
/******************************************************************************
** Function name: CAN_SetACCF_Lookup
**
** Descriptions: Initialize CAN, install CAN interrupt handler
**
** parameters: bitrate
** Returned value: true or false, false if initialization failed.
**
******************************************************************************/
void CAN_SetACCF_Lookup( void )
{
uint32_t address = 0;
uint32_t i;
uint32_t ID_high, ID_low;
// Set explicit standard Frame
CAN_SFF_SA = address;
for ( i = 0; i < ACCF_IDEN_NUM; i += 1 )
{
ID_low = (i << 29) | (EXP_STD_ID << 16);
ID_high = ((i) << 13) | (EXP_STD_ID << 0);
*((volatile uint32_t *)(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 += 1 )
{
ID_low = (i << 29) | (GRP_STD_ID_LOW << 16);
ID_high = ((i) << 13) | (GRP_STD_ID_HIGH << 0);
*((volatile uint32_t *)(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_t *)(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) | (EXT_ID[0] << 0);
// *((volatile uint32_t *)(CAN_MEM_BASE + address)) = ID_low;
// address += 4;
// ID_high = (i << 29) | (EXT_ID[1] << 0);
// *((volatile uint32_t *)(CAN_MEM_BASE + address)) = ID_high;
// address += 4;
}
// Set End of Table
CAN_EOT = address;
return;
}
/******************************************************************************
** Function name: CAN_SetACCF
**
** Descriptions: Set acceptance filter and SRAM associated with
**
** parameters: ACMF mode
** Returned value: None
**
**
******************************************************************************/
void CAN_SetACCF( uint32_t 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();
CAN_AFMR = ACCFMode;
break;
default:
break;
}
return;
}
/******************************************************************************
** Function name: CAN1_SendMessage
**
** Descriptions: Send message block to CAN1
**
** parameters: pointer to the CAN message
** Returned value: true or false, if message buffer is available,
** message can be sent successfully, return TRUE,
** otherwise, return FALSE.
**
******************************************************************************/
uint32_t CAN1_SendMessage( CAN_MSG *pTxBuf )
{
// uint32_t CANStatus;
CANStatus = CAN1SR;
if ( CANStatus & 0x00000004 )
{
CAN1TFI1 = pTxBuf->Frame & 0xC00F0000;
CAN1TID1 = pTxBuf->MsgID;
CAN1TDA1 = pTxBuf->DataA;
CAN1TDB1 = pTxBuf->DataB;
CAN1CMR = 0x21;
return ( TRUE );
}
else if ( CANStatus & 0x00000400 )
{
CAN1TFI2 = pTxBuf->Frame & 0xC00F0000;
CAN1TID2 = pTxBuf->MsgID;
CAN1TDA2 = pTxBuf->DataA;
CAN1TDB2 = pTxBuf->DataB;
CAN1CMR = 0x41;
return ( TRUE );
}
else if ( CANStatus & 0x00040000 )
{
CAN1TFI3 = pTxBuf->Frame & 0xC00F0000;
CAN1TID3 = pTxBuf->MsgID;
CAN1TDA3 = pTxBuf->DataA;
CAN1TDB3 = pTxBuf->DataB;
CAN1CMR = 0x81;
return ( TRUE );
}
else
{
return ( FALSE );
}
}
/******************************************************************************
** Function name: CAN2_SendMessage
**
** Descriptions: Send message block to CAN2
**
** parameters: pointer to the CAN message
** Returned value: true or false, if message buffer is available,
** message can be sent successfully, return TRUE,
** otherwise, return FALSE.
**
******************************************************************************/
uint32_t CAN2_SendMessage( CAN_MSG *pTxBuf )
{
// uint32_t 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 );
}
else
{
return ( FALSE );
}
}
CAN_MSG * CAN1Getch(void)
{
CAN_MSG * ch;
if (can1_rx_insert_idx == can1_rx_extract_idx) // check if character is available
return 0;
ch = &can1_rx_buff[can1_rx_extract_idx++]; // get character, bump pointer
can1_rx_extract_idx %= 64; // limit the pointer
return ch;
}
CAN_MSG * CAN1GetFirstch(void)
{
CAN_MSG * ch;
if (First_Frame_insert_idx == First_Frame_extract_idx) // check if character is available
return 0;
ch = &First_Frame_buff[First_Frame_extract_idx++]; // get character, bump pointer
First_Frame_extract_idx %= 4; // limit the pointer
return ch;
}
/******************************************************************************
** End Of File
******************************************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -