⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 Tried to make CAN logger on AT91sam7X-ek, but have no idea how to implement FATFs... -( I m just a
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -