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

📄 sja1000.c

📁 avr上的RTOS
💻 C
📖 第 1 页 / 共 2 页
字号:
        SJA1000_BT0 = 73;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_100K:        SJA1000_BT0 = 68;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_125K:        SJA1000_BT0 = 67;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_250K:        SJA1000_BT0 = 65;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_500K:        SJA1000_BT0 = 64;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_800K:        SJA1000_BT0 = 64;        SJA1000_BT1 = 22;        break;    case CAN_SPEED_1M:        SJA1000_BT0 = 64;        SJA1000_BT1 = 20;        break;    default:        result = 1;    }    do {        SJA1000_MODECTRL = 0x00;    }    while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leave reset state    return result;}/*! * \fn    SJATxFrame(CANFRAME * CAN_frame) * \brief Sends a CAN Frane * * * \param CAN_frame Pointer to the send frame */void SJATxFrame(CANFRAME * CAN_frame){    u_long temp_id;    temp_id = CAN_frame->id << 3;    if (CAN_frame->ext) {        SJA1000_TxFrameInfo = CAN_frame->len | CAN_29 | (CAN_frame->rtr ? CAN_RTR : 0);        SJA1000_Tx1 = (uint8_t) (temp_id >> 24);        // load High Byte        SJA1000_Tx2 = (uint8_t) (temp_id >> 16);        // load High Byte        SJA1000_Tx3 = (uint8_t) (temp_id >> 8); // load High Byte        SJA1000_Tx4 = (uint8_t) (temp_id & 0x00F8);     // Low Byte and ignore bit 0-2        SJA1000_Tx5 = CAN_frame->byte[0];        SJA1000_Tx6 = CAN_frame->byte[1];        SJA1000_Tx7 = CAN_frame->byte[2];        SJA1000_Tx8 = CAN_frame->byte[3];        SJA1000_Tx9 = CAN_frame->byte[4];        SJA1000_Tx10 = CAN_frame->byte[5];        SJA1000_Tx11 = CAN_frame->byte[6];        SJA1000_Tx12 = CAN_frame->byte[7];    } else {        SJA1000_TxFrameInfo = CAN_frame->len | (CAN_frame->rtr ? CAN_RTR : 0);        SJA1000_Tx1 = (uint8_t) ((CAN_frame->id) >> 24);        // load High Byte        SJA1000_Tx2 = (uint8_t) ((CAN_frame->id) >> 16) & 0xE0; // Low Byte and ignore bit 0-4        SJA1000_Tx3 = CAN_frame->byte[0];        SJA1000_Tx4 = CAN_frame->byte[1];        SJA1000_Tx5 = CAN_frame->byte[2];        SJA1000_Tx6 = CAN_frame->byte[3];        SJA1000_Tx7 = CAN_frame->byte[4];        SJA1000_Tx8 = CAN_frame->byte[5];        SJA1000_Tx9 = CAN_frame->byte[6];        SJA1000_Tx10 = CAN_frame->byte[7];    }    SJA1000_CMD = TR_Bit;     // Start Transmission}/*! * \fn    SJARxFrame(CANFRAME * CAN_frame) * \brief Receives a CAN Frane * * * \param CAN_frame Pointer to the receive frame */void SJARxFrame(CANFRAME * CAN_frame){    u_char FrameInfo = SJA1000_RxFrameInfo;    CAN_frame->len = FrameInfo & 0x0F;  // frame info mask off higher 4 bits    CAN_frame->ext = FrameInfo & CAN_29 ? 1 : 0;    CAN_frame->rtr = FrameInfo & CAN_RTR ? 1 : 0;    if (CAN_frame->ext) {        CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) |                         ((uint32_t) SJA1000_Rx2 << 16) |                          ((uint32_t) SJA1000_Rx3 << 8)  |                          ((uint32_t) SJA1000_Rx4 & 0xF8)) >> 3;        CAN_frame->byte[0] = SJA1000_Rx5;        CAN_frame->byte[1] = SJA1000_Rx6;        CAN_frame->byte[2] = SJA1000_Rx7;        CAN_frame->byte[3] = SJA1000_Rx8;        CAN_frame->byte[4] = SJA1000_Rx9;        CAN_frame->byte[5] = SJA1000_Rx10;        CAN_frame->byte[6] = SJA1000_Rx11;        CAN_frame->byte[7] = SJA1000_Rx12;      // just fill the whole struct, less CPU cycles    } else {        CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) |                           (uint32_t) SJA1000_Rx2 << 16) >> 3;   // id_h and id_l        CAN_frame->byte[0] = SJA1000_Rx3;        CAN_frame->byte[1] = SJA1000_Rx4;        CAN_frame->byte[2] = SJA1000_Rx5;        CAN_frame->byte[3] = SJA1000_Rx6;        CAN_frame->byte[4] = SJA1000_Rx7;        CAN_frame->byte[5] = SJA1000_Rx8;        CAN_frame->byte[6] = SJA1000_Rx9;        CAN_frame->byte[7] = SJA1000_Rx10;      // just fill the whole struct, less CPU cycles    }    SJA1000_CMD = RRB_Bit;      // release the receive buffer}/*!  * \fn CAN_Tx(void *arg) * \brief CAN transmitter thread. * *  * This thread transmits data if there's some in the output buffer. * It runs with high priority. */THREAD(CAN_Tx, arg){    NUTDEVICE *dev;    CANINFO *ci;    CANFRAME out_frame;    dev = arg;    ci = (CANINFO *) dev->dev_dcb;    NutThreadSetPriority(16);    while (1) {        NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);        while ((SJA1000_STATUS & TBS_Bit) == TBS_Bit)   // if transmit buffer released        {            out_frame = CANBufferGetMutex(&CAN_TX_BUF);            SJATxFrame(&out_frame);     // using SJA1000 TX buffer            ci->can_tx_frames++;        }    }}/*!  * \fn  SJAInterrupt (void * arg) * \brief SJA interrupt entry. *  * The interrupt handler posts events to the rx and tx thread wait queue. * receive interrupt will be disabled on reception and will be enabled by the * rx thread again. Otherwise interrupt would not stop (level triggered) */static void SJAInterrupt(void *arg){    CANINFO *ci;    volatile u_char irq = SJA1000_INT;    CANFRAME in_frame;        ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);    ci->can_interrupts++;    if (((irq & TI_Bit) == TI_Bit))     // transmit IRQ fired    {        NutEventPostFromIrq(&ci->can_tx_rdy);    }    if ((irq & RI_Bit) == RI_Bit)       // Receive IRQ fired    {        if (CAN_RX_BUF.size-CAN_RX_BUF.datalength > 0)        {            SJARxFrame(&in_frame);            CANBufferPut(&CAN_RX_BUF, &in_frame);            if (CAN_RX_BUF.size==CAN_RX_BUF.datalength)                SJA1000_IEN &= (~RIE_Bit);      // Disable RX IRQ until data has been poped from input buffer            NutEventPostFromIrq(&ci->can_rx_rdy);            ci->can_rx_frames++;        }    }    if ((irq & EI_Bit) == EI_Bit)       //Error IRQ fired    {        ci->can_errors++;        // TODO: Handle error    } else if ((irq & DOI_Bit) == DOI_Bit)      //Error IRQ fired    {        ci->can_overruns++;        SJA1000_CMD = CDO_Bit;          // Clear DO status;        // TODO: Handle overrun    }}/*! * \fn    SJAInit(NUTDEVICE * dev) * \brief Initialize SJA1000 Canbus interface. * * * Applications typically do not use this function, but * call NutRegisterDevice(). * * \param dev Identifies the device to initialize. The *            structure must be properly set. */int SJAInit(NUTDEVICE * dev){    IFCAN *ifc;    CANINFO *ci;    volatile u_char temp;    sja_base = dev->dev_base;    ifc = dev->dev_icb;    memset(dev->dev_dcb, 0, sizeof(CANINFO));    ci = (CANINFO *) dev->dev_dcb;    CANBufferInit(&CAN_RX_BUF, CAN_BufSize);    CANBufferInit(&CAN_TX_BUF, CAN_BufSize);    while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00)      // entering reset mode        SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);    SJA1000_CLK_DIV = (CANMode_Bit | CBP_Bit | DivBy2 | ClkOff_Bit);    // sets clock divide register    SJA1000_IEN = (ClrIntEnSJA);        // Disables CAN IRQ    SJA1000_AC0 = ifc->can_acc_code[0];    SJA1000_AC1 = ifc->can_acc_code[1];    SJA1000_AC2 = ifc->can_acc_code[2];    SJA1000_AC3 = ifc->can_acc_code[3];    SJA1000_AM0 = ifc->can_acc_mask[0];    SJA1000_AM1 = ifc->can_acc_mask[1];    SJA1000_AM2 = ifc->can_acc_mask[2];    SJA1000_AM3 = ifc->can_acc_mask[3];    switch (ifc->can_baudrate)  // setting actual bustiming    {                           // all @ 16 Mhz    case CAN_SPEED_10K:        SJA1000_BT0 = 113;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_20K:        SJA1000_BT0 = 88;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_50K:        SJA1000_BT0 = 73;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_100K:        SJA1000_BT0 = 68;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_125K:        SJA1000_BT0 = 67;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_250K:        SJA1000_BT0 = 65;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_500K:        SJA1000_BT0 = 64;        SJA1000_BT1 = 28;        break;    case CAN_SPEED_800K:        SJA1000_BT0 = 64;        SJA1000_BT1 = 22;        break;    case CAN_SPEED_1M:        SJA1000_BT0 = 64;        SJA1000_BT1 = 20;        break;    default:        return errCAN_INVALID_BAUD;    }    SJA1000_OUTCTRL = (Tx1Float | Tx0PshPull | NormalMode);     // Set up Output Control Register    SJA1000_IEN = (RIE_Bit | TIE_Bit | EIE_Bit | DOIE_Bit );       // Enables receive IRQ    SJA1000_MODECTRL = (AFM_Bit);       // set single filter mode + sleep    // *** Note - if you change SJA1000_MODECTRL, change it in    // functions SJASetAccMask and SJASetAccCode also.        do {        SJA1000_MODECTRL = 0x00;    }    while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leaves reset mode    NutEnterCritical();    if (NutRegisterIrqHandler(&SJA_SIGNAL, SJAInterrupt, dev)) {        NutExitCritical();        return -1;    }    cbi(EIMSK, SJA_SIGNAL_BIT);    if (SJA_SIGNAL_BIT < 4)     // Set corresponding interrupt to low    {                           // level interrupt#ifdef __AVR_ENHANCED__        cbi(EICRA, (SJA_SIGNAL_BIT << 1));        cbi(EICRA, (SJA_SIGNAL_BIT << 1) + 1);#endif /* __AVR_ENHANCED__ */    } else {        cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1));        cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1) + 1);    }    temp = SJA1000_INT;         // Read interrupt register to clear pendin bits        sbi(EIMSK, SJA_SIGNAL_BIT);    sbi(PORTE, SJA_SIGNAL_BIT);    NutThreadCreate("sjacantx", CAN_Tx, dev, 256);    NutExitCritical();    return 0;}/*! * \brief Interface information structure. * * This struct stores some interface parameters like bautdate and  * acceptance mask / code. Beside this Callback handlers are registered. */IFCAN ifc_sja1000 = {    CAN_IF_2B,                  /*!< \brief Interface type. */    CAN_SPEED_500K,             /*!< \brief Baudrate of device. */    {0xFF, 0xFF, 0xFF, 0xFF}    ,                           /*!< \brief Acceptance mask */    {0x00, 0x00, 0x00, 0x00}    ,                           /*!< \brief Acceptance code */    SJARxAvail,                 /*!< \brief Data in RxBuffer available? */    SJATxFree,                  /*!< \brief TxBuffer free? */    SJAInput,                   /*!< \brief CAN Input routine */    SJAOutput,                  /*!< \brief CAN Output routine */    SJASetAccCode,              /*!< \brief Set acceptance code */    SJASetAccMask,              /*!< \brief Set acceptance mask */    SJASetBaudrate              /*!< \brief Set baudrate */};/*! * \brief Device information structure. * * Applications must pass this structure to NutRegisterDevice()  * to bind this CAN device driver to the Nut/OS kernel. */NUTDEVICE devSJA1000 = {    0,                          /*!< Pointer to next device. */    {'s', 'j', 'a', '1', '0', '0', '0', 0, 0}    ,                           /*!< Unique device name. */    IFTYP_CAN,                  /*!< Type of device. */    0,                          /*!< Base address. */    0,                          /*!< First interrupt number. */    &ifc_sja1000,               /*!< Interface control block. */    &dcb_sja1000,               /*!< Driver control block. */    SJAInit,                    /*!< Driver initialization routine. */    0,                          /*!< Driver specific control function. */    0,                          /*!< Read from device. */    0,                          /*!< Write to device. */    0,                          /*!< Write from program space data to device. */    0,                          /*!< Open a device or file. */    0,                          /*!< Close a device or file. */    0                           /*!< Request file size. */};#elsevoid keep_icc_happy(void){}#endif/*@}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -