📄 can.c
字号:
CAN_InitMailboxRegisters( pCAN0Transfer );
// Init CAN1 Mailbox 15, reception with overwrite
CAN_ResetTransfer( pCAN1Transfer );
pCAN1Transfer->can_number = 1;
pCAN1Transfer->mailbox_number = 15;
pCAN1Transfer->mode_reg = AT91C_CAN_MOT_RX;
pCAN1Transfer->acceptance_mask_reg = 0;
pCAN1Transfer->identifier = 0x0;
pCAN1Transfer->data_low_reg = 0x00000000;
pCAN1Transfer->data_high_reg = 0x00000000;
pCAN1Transfer->control_reg = 0x00000000;
CAN_InitMailboxRegisters( pCAN1Transfer );
// Ask Transmissions on Mailbox 1 & 2 --> AT91C_CAN_MRDY & AT91C_CAN_MMI raises for Mailbox 15 CAN_MB_SR
AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB1 | AT91C_CAN_MB2;
// Wait for Last Transmit Mailbox
tick = 0;
do {
status = AT91C_BASE_CAN1_MB15->CAN_MB_MSR;
}
while( !(status & AT91C_CAN_MMI) && (++tick < AT91C_CAN_TIMEOUT) );
if (tick == AT91C_CAN_TIMEOUT) {
TRACE_ERROR("Test FAILED\n\r");
}
else {
TRACE_DEBUG("Transfer completed: CAN1 Mailbox 15 MRDY and MMI flags have raised\n\r");
TRACE_DEBUG("MB_MDL: 0x%X\n\r", AT91C_BASE_CAN1_MB15->CAN_MB_MDL);
TRACE_DEBUG("MB_MDLH: 0x%X\n\r", AT91C_BASE_CAN1_MB15->CAN_MB_MDH);
if( AT91C_BASE_CAN0_MB2->CAN_MB_MDL != AT91C_BASE_CAN1_MB15->CAN_MB_MDL ) {
TRACE_ERROR("Data Corrupted\n\r");
}
else if( AT91C_BASE_CAN0_MB2->CAN_MB_MDH != AT91C_BASE_CAN1_MB15->CAN_MB_MDH ) {
TRACE_ERROR("Data Corrupted\n\r");
}
else {
TRACE_INFO("Test passed\n\r");
}
}
CAN_ResetAllMailbox();
TRACE_INFO("Without Interrupt ");
TRACE_INFO("CAN0 Mailbox 3 asking for CAN1 Mailbox 3 transmission\n\r");
// Init CAN0 Mailbox 3, consumer mailbox
// Sends a remote frame and waits for an answer
CAN_ResetTransfer( pCAN0Transfer );
pCAN0Transfer->can_number = 0;
pCAN0Transfer->mailbox_number = 3;
pCAN0Transfer->mode_reg = AT91C_CAN_MOT_CONSUMER | AT91C_CAN_PRIOR;
pCAN0Transfer->acceptance_mask_reg = AT91C_CAN_MIDvA | AT91C_CAN_MIDvB;
pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x0B<<18); // ID 11
pCAN0Transfer->data_low_reg = 0x00000000;
pCAN0Transfer->data_high_reg = 0x00000000;
pCAN0Transfer->control_reg = 0x00000000;
CAN_InitMailboxRegisters( pCAN0Transfer );
// Init CAN1 Mailbox 3, porducer mailbox
// Waits to receive a Remote Frame before sending its contents
CAN_ResetTransfer( pCAN1Transfer );
pCAN1Transfer->can_number = 1;
pCAN1Transfer->mailbox_number = 3;
pCAN1Transfer->mode_reg = AT91C_CAN_MOT_PRODUCER | AT91C_CAN_PRIOR;
pCAN1Transfer->acceptance_mask_reg = 0;
pCAN1Transfer->identifier = AT91C_CAN_MIDvA & (0x0B<<18); // ID 11
pCAN1Transfer->data_low_reg = 0xEEDDFF00;
pCAN1Transfer->data_high_reg = 0x34560022;
pCAN1Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16));
CAN_InitMailboxRegisters( pCAN1Transfer );
// Ask Transmissions on Mailbox 3 --> AT91C_CAN_MRDY raises for Mailbox 3 CAN_MB_SR
AT91C_BASE_CAN1->CAN_TCR = AT91C_CAN_MB3;
AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB3;
// Wait for Last Transmit Mailbox
tick = 0;
do {
status = AT91C_BASE_CAN0_MB3->CAN_MB_MSR;
}
while( !(status & AT91C_CAN_MRDY) && (++tick < AT91C_CAN_TIMEOUT) );
if (tick == AT91C_CAN_TIMEOUT) {
TRACE_ERROR("Test FAILED\n\r");
}
else {
TRACE_DEBUG("Transfer Completed: CAN0 & CAN1 Mailboxes 3 MRDY flags have raised\n\r");
if( AT91C_BASE_CAN0_MB3->CAN_MB_MDL != AT91C_BASE_CAN1_MB3->CAN_MB_MDL ) {
TRACE_ERROR("Data Corrupted\n\r");
}
else if( AT91C_BASE_CAN0_MB3->CAN_MB_MDH != AT91C_BASE_CAN1_MB3->CAN_MB_MDH ) {
TRACE_ERROR("Data Corrupted\n\r");
}
else {
TRACE_INFO("Test passed\n\r");
}
}
#endif // AT91C_BASE_CAN1
return;
}
//------------------------------------------------------------------------------
/// Disable CAN and enter in low power
//------------------------------------------------------------------------------
void CAN_disable( void )
{
// Disable the interrupt on the interrupt controller
AIC_DisableIT(AT91C_ID_CAN0);
// disable all IT
AT91C_BASE_CAN0->CAN_IDR = 0x1FFFFFFF;
#if defined AT91C_BASE_CAN1
AIC_DisableIT(AT91C_ID_CAN1);
// disable all IT
AT91C_BASE_CAN1->CAN_IDR = 0x1FFFFFFF;
#endif
// Enable Low Power mode
AT91C_BASE_CAN0->CAN_MR |= AT91C_CAN_LPM;
// Disable CANs Transceivers
// Enter standby mode
PIO_Set(&pin_can_transceiver_rs);
#if defined (PIN_CAN_TRANSCEIVER_RXEN)
// Enable ultra Low Power mode
PIO_Clear(&pin_can_transceiver_rxen);
#endif
// Disable clock for CAN PIO
#if defined(AT91C_ID_PIOA)
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOA);
#elif defined(AT91C_ID_PIOABCD)
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOABCD);
#elif defined(AT91C_ID_PIOABCDE)
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOABCDE);
#endif
// Disable the CAN0 controller peripheral clock
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_CAN0);
}
//------------------------------------------------------------------------------
/// baudrate calcul
/// \param base_CAN CAN base address
/// \param baudrate Baudrate value (kB/s)
/// allowed values: 1000, 800, 500, 250, 125, 50, 25, 10
/// \return return 1 in success, otherwise return 0
//------------------------------------------------------------------------------
unsigned char CAN_BaudRateCalculate( AT91PS_CAN base_CAN,
unsigned int baudrate )
{
unsigned int BRP;
unsigned int PROPAG;
unsigned int PHASE1;
unsigned int PHASE2;
unsigned int SJW;
unsigned int t1t2;
unsigned char TimeQuanta;
base_CAN->CAN_BR = 0;
if( baudrate == 1000) {
TimeQuanta = 8;
}
else {
TimeQuanta = 16;
}
BRP = (BOARD_MCK / (baudrate*1000*TimeQuanta))-1;
//TRACE_DEBUG("BRP = 0x%X\n\r", BRP);
// timing Delay:
// Delay Bus Driver: 50 ns
// Delay Receiver: 30 ns
// Delay Bus Line (20m): 110 ns
if( (TimeQuanta*baudrate*2*(50+30+110)/1000000) >= 1) {
PROPAG = (TimeQuanta*baudrate*2*(50+30+110)/1000000)-1;
}
else {
PROPAG = 0;
}
//TRACE_DEBUG("PROPAG = 0x%X\n\r", PROPAG);
t1t2 = TimeQuanta-1-(PROPAG+1);
//TRACE_DEBUG("t1t2 = 0x%X\n\r", t1t2);
if( (t1t2 & 0x01) == 0x01 ) {
// ODD
//TRACE_DEBUG("ODD\n\r");
PHASE1 = ((t1t2-1)/2)-1;
PHASE2 = PHASE1+1;
}
else {
// EVEN
//TRACE_DEBUG("EVEN\n\r");
PHASE1 = (t1t2/2)-1;
PHASE2 = PHASE1;
}
//TRACE_DEBUG("PHASE1 = 0x%X\n\r", PHASE1);
//TRACE_DEBUG("PHASE2 = 0x%X\n\r", PHASE2);
if( 1 > (4/(PHASE1+1)) ) {
//TRACE_DEBUG("4*Tcsc\n\r");
SJW = 3;
}
else {
//TRACE_DEBUG("Tphs1\n\r");
SJW = PHASE1;
}
//TRACE_DEBUG("SJW = 0x%X\n\r", SJW);
// Verif
if( BRP == 0 ) {
TRACE_DEBUG("BRP = 0 is not authorized\n\r");
return 0;
}
if( (PROPAG + PHASE1 + PHASE2) != (TimeQuanta-4) ) {
TRACE_DEBUG("Pb (PROPAG + PHASE1 + PHASE2) = %d\n\r", PROPAG + PHASE1 + PHASE2);
TRACE_DEBUG("with TimeQuanta-4 = %d\n\r", TimeQuanta-4);
return 0;
}
base_CAN->CAN_BR = (AT91C_CAN_PHASE2 & (PHASE2 << 0))
+ (AT91C_CAN_PHASE1 & (PHASE1 << 4))
+ (AT91C_CAN_PROPAG & (PROPAG << 8))
+ (AT91C_CAN_SYNC & (SJW << 12))
+ (AT91C_CAN_BRP & (BRP << 16))
+ (AT91C_CAN_SMP & (0 << 24));
return 1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Init of the CAN peripheral
/// \param baudrate Baudrate value (kB/s)
/// allowed values: 1000, 800, 500, 250, 125, 50, 25, 10
/// \param canTransfer0 CAN0 structure transfer
/// \param canTransfer1 CAN1 structure transfer
/// \return return 1 if CAN has good baudrate and CAN is synchronized,
/// otherwise return 0
//------------------------------------------------------------------------------
unsigned char CAN_Init( unsigned int baudrate,
CanTransfer *canTransfer0,
CanTransfer *canTransfer1 )
{
unsigned char ret;
// CAN Transmit Serial Data
#if defined (PINS_CAN_TRANSCEIVER_TXD)
PIO_Configure(pins_can_transceiver_txd, PIO_LISTSIZE(pins_can_transceiver_txd));
#endif
#if defined (PINS_CAN_TRANSCEIVER_RXD)
// CAN Receive Serial Data
PIO_Configure(pins_can_transceiver_rxd, PIO_LISTSIZE(pins_can_transceiver_rxd));
#endif
// CAN RS
PIO_Configure(&pin_can_transceiver_rs, PIO_LISTSIZE(pin_can_transceiver_rs));
#if defined (PIN_CAN_TRANSCEIVER_RXEN)
// CAN RXEN
PIO_Configure(&pin_can_transceiver_rxen, PIO_LISTSIZE(pin_can_transceiver_rxen));
#endif
// Enable clock for CAN PIO
#if defined(AT91C_ID_PIOA)
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA);
#elif defined(AT91C_ID_PIOABCD)
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOABCD);
#elif defined(AT91C_ID_PIOABCDE)
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOABCDE);
#endif
// Enable the CAN0 controller peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN0);
// disable all IT
AT91C_BASE_CAN0->CAN_IDR = 0x1FFFFFFF;
// Enable CANs Transceivers
#if defined (PIN_CAN_TRANSCEIVER_RXEN)
// Disable ultra Low Power mode
PIO_Set(&pin_can_transceiver_rxen);
#endif
// Normal Mode (versus Standby mode)
PIO_Clear(&pin_can_transceiver_rs);
// Configure the AIC for CAN interrupts
AIC_ConfigureIT(AT91C_ID_CAN0, AT91C_AIC_PRIOR_HIGHEST, CAN0_Handler);
// Enable the interrupt on the interrupt controller
AIC_EnableIT(AT91C_ID_CAN0);
if( CAN_BaudRateCalculate(AT91C_BASE_CAN0, baudrate) == 0 ) {
// Baudrate problem
TRACE_DEBUG("Baudrate CAN0 problem\n\r");
return 0;
}
pCAN0Transfer = canTransfer0;
#if defined AT91C_BASE_CAN1
if( canTransfer1 != NULL ) {
pCAN1Transfer = canTransfer1;
// Enable CAN1 Clocks
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN1);
// disable all IT
AT91C_BASE_CAN1->CAN_IDR = 0x1FFFFFFF;
// Configure the AIC for CAN interrupts
AIC_ConfigureIT(AT91C_ID_CAN1, AT91C_AIC_PRIOR_HIGHEST, CAN1_Handler);
// Enable the interrupt on the interrupt controller
AIC_EnableIT(AT91C_ID_CAN1);
if( CAN_BaudRateCalculate(AT91C_BASE_CAN1, baudrate) == 0 ) {
// Baudrate problem
TRACE_DEBUG("Baudrate CAN1 problem\n\r");
return 0;
}
}
#endif
// Reset all mailbox
CAN_ResetAllMailbox();
// Enable the interrupt with all error cases
AT91C_BASE_CAN0->CAN_IER = AT91C_CAN_CERR // (CAN) CRC Error
| AT91C_CAN_SERR // (CAN) Stuffing Error
| AT91C_CAN_BERR // (CAN) Bit Error
| AT91C_CAN_FERR // (CAN) Form Error
| AT91C_CAN_AERR; // (CAN) Acknowledgment Error
#if defined AT91C_BASE_CAN1
if( canTransfer1 != NULL ) {
AT91C_BASE_CAN1->CAN_IER = AT91C_CAN_CERR // (CAN) CRC Error
| AT91C_CAN_SERR // (CAN) Stuffing Error
| AT91C_CAN_BERR // (CAN) Bit Error
| AT91C_CAN_FERR // (CAN) Form Error
| AT91C_CAN_AERR; // (CAN) Acknowledgment Error
}
#endif
// Wait for CAN synchronisation
if( CAN_Synchronisation( ) == 1 ) {
ret = 1;
}
else {
ret = 0;
}
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -