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

📄 atcan.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2005 FOCUS Software Engineering Pty Ltd <www.focus-sw.com> * Copyright (c) 2005 proconX <www.proconx.com> * * This driver has been closely modeled after the existing Nut/OS SJA1000 * driver and the buffer management and some code snippets have been borrowed * from sja1000.c. * * Portions Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>, * Kernelconcepts http://www.kernelconcepts.de * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * *//* * $Log: atcan.c,v $ * Revision 1.3  2005/12/04 10:53:59  hwmaier * no message * * Revision 1.2  2005/10/07 22:02:33  hwmaier * no message * * Revision 1.1  2005/10/04 06:00:59  hwmaier * Added AT90CAN128 CAN driver * *//*! * \addtogroup xgCanAvr *//*@{*/#ifdef __GNUC__#include <cfg/os.h>#include <string.h>#include <sys/event.h>#include <sys/heap.h>#include <sys/atom.h>#include <dev/irqreg.h>#include <dev/can_dev.h>#include <avr/io.h>#include <dev/atcan.h>/***************************************************************************** * Definitions *****************************************************************************/#define MAX_NO_MOB 15/** * CAN result codes * * @ingroup can */enum CAN_RESULT{   CAN_SUCCESS       =  0,   ///< Successful operation   CAN_TXBUF_FULL    = -1,   ///< All TX message objects busy   CAN_RXBUF_EMPTY   = -2,   ///< All RX message objects busy   CAN_ILLEGAL_MOB   = -3,   ///< Message object index out of range   CAN_INVALID_SPEED = -4,   ///< Invalid baud rate parameter};#define RX_MOB 8#ifndef CAN_BUF_SIZE#  define CAN_BUF_SIZE 64#endif/***************************************************************************** * CAN baud rate table * * Sampling point is 75%, SJW = 1 *****************************************************************************///// 12.00 MHz//#if NUT_CPU_FREQ == 12000000// 10 kbit/s - brp=59 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1#define CAN_BT1_10K  0x76#define CAN_BT2_10K  0x0E#define CAN_BT3_10K  0x4B// 20 kbit/s - brp=29 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1#define CAN_BT1_20K  0x3A#define CAN_BT2_20K  0x0E#define CAN_BT3_20K  0x4B// 50 kbit/s - brp=19 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1#define CAN_BT1_50K  0x26#define CAN_BT2_50K  0x08#define CAN_BT3_50K  0x25// 100 kbit/s - brp=9 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1#define CAN_BT1_100K 0x12#define CAN_BT2_100K 0x08#define CAN_BT3_100K 0x25// 125 kbit/s - brp=5 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_125K 0x0A#define CAN_BT2_125K 0x0C#define CAN_BT3_125K 0x37// 250 kbit/s - brp=2 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_250K 0x04#define CAN_BT2_250K 0x0C#define CAN_BT3_250K 0x37// 500 kbit/s - brp=1 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1#define CAN_BT1_500K 0x02#define CAN_BT2_500K 0x08#define CAN_BT3_500K 0x25// 800 kbit/s - brp=0 bits=15 Tprs=8 Tph1=3 Tph2=3 Tsjw=1#define CAN_BT1_800K 0x00#define CAN_BT2_800K 0x0E#define CAN_BT3_800K 0x25// 1000 kbit/s - brp=0 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1#define CAN_BT1_1M   0x00#define CAN_BT2_1M   0x08#define CAN_BT3_1M   0x25//// 16.00 MHz//#elif NUT_CPU_FREQ == 16000000// 10 kbit/s - brp=63 bits=25 Tprs=8 Tph1=10 Tph2=6 Tsjw=1#define CAN_BT1_10K  0x7E#define CAN_BT2_10K  0x0E#define CAN_BT3_10K  0x53// 20 kbit/s - brp=39 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1#define CAN_BT1_20K  0x4E#define CAN_BT2_20K  0x0E#define CAN_BT3_20K  0x4B// 50 kbit/s - brp=19 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_50K  0x26#define CAN_BT2_50K  0x0C#define CAN_BT3_50K  0x37// 100 kbit/s - brp=9 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_100K 0x12#define CAN_BT2_100K 0x0C#define CAN_BT3_100K 0x37// 125 kbit/s - brp=7 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_125K 0x0E#define CAN_BT2_125K 0x0C#define CAN_BT3_125K 0x37// 250 kbit/s - brp=3 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_250K 0x06#define CAN_BT2_250K 0x0C#define CAN_BT3_250K 0x37// 500 kbit/s - brp=1 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_500K 0x02#define CAN_BT2_500K 0x0C#define CAN_BT3_500K 0x37// 800 kbit/s - brp=0 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1#define CAN_BT1_800K 0x00#define CAN_BT2_800K 0x0E#define CAN_BT3_800K 0x4B// 1000 kbit/s - brp=0 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1#define CAN_BT1_1M   0x00#define CAN_BT2_1M   0x0C#define CAN_BT3_1M   0x37#else#  error Frequency not supported or not set to a Fixed MCU clock!#endif/***************************************************************************** * Buffer management * * Note: Buffer concept borrowed from existing Nut/OS sja1000.c driver *****************************************************************************/struct _CANBuffer {    CANFRAME *dataptr;    // the physical memory address where the buffer is stored    uint8_t size;         // the allocated size of the buffer    uint8_t datalength;   // the length of the data currently in the buffer    uint8_t dataindex;    // the index into the buffer where the data starts};typedef struct _CANBuffer CANBuffer;/***************************************************************************** * Driver data *****************************************************************************/CANBuffer canRxBuf;CANINFO dcb_atcan;IFCAN ifc_atcan;NUTDEVICE devAtCan;/***************************************************************************** * Low level functions *****************************************************************************//** * @internal * Search for a free message object * @return Index of free message object or -1 if none is available */int8_t AtCanGetFreeMob(void){   int8_t mob;   uint8_t ctrlReg;   for (mob = 0; mob < MAX_NO_MOB; mob++)   {      CANPAGE = mob << 4;      ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));      if (ctrlReg == 0)         return mob;      if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))      {          // Free MOB          CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));          return mob;      }   }   return -1;}/** * Configure a single message object for receiption. * * @param mob        Message object index (0-14) * @param id         Acceptance code * @param idIsExt    Flag if acceptance code is extended (0 = standard, 1 = extended) * @param idRemTag   Id's remote tag (0 or 1) * @param mask       Acceptance mask * @param maskIsExt  Flag if acceptance mask is extended (0 = standard, 1 = extended) * @param maskRemTag Mask's remote tag (0 or 1) * @return Result code. See @ref CAN_RESULT */int8_t AtCanEnableMsgObj(uint8_t mob,                         uint32_t id, int8_t idIsExt, int8_t idRemTag,                         uint32_t mask, int8_t maskIsExt, int8_t maskRemTag){    if (mob < MAX_NO_MOB)    {        // Select MOB        CANPAGE = mob << 4;        // Abort MOB        CANCDMOB = 0;        // Set identifier and mask        if (idIsExt)        {            CANCDMOB |= _BV(IDE);            CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);            CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);            CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);            CANIDT4 = (((uint8_t *) &(id))[0] << 3);            CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);            CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);            CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);            CANIDM4 = (((uint8_t *) &(mask))[0] << 3);        }        else        {            CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);            CANIDT2 = (((uint8_t *) &(id))[0] << 5);            CANIDT3 = 0;            CANIDT4 = 0;            CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);            CANIDM2 = (((uint8_t *) &(mask))[0] << 5);            CANIDM3 = 0;            CANIDM4 = 0;        }        if (idRemTag)            CANIDT4 |= _BV(RTRTAG);        if (maskIsExt)            CANIDM4 |= _BV(IDEMSK);        if (maskRemTag)            CANIDM4 |= _BV(RTRMSK);        // Enable reception        CANCDMOB |= _BV(CONMOB1);        return CAN_SUCCESS;    }    else        return CAN_ILLEGAL_MOB;}/** * Configure message objects for receiption. * * @param noOfMsgObjs Number of message objects used for receiption (1-14). *                    Message objects not configured for receiption are used for *                    transmission. *                    The same acceptance filter and mask is applied to the *                    message objects. *                    If it is required to set-up more complex *                    filtering mechanisms use canEnableMsgObj() instead, which *                    allows setting filters on a per message object basis. * @param id          Acceptance code * @param idIsExt     Flag if acceptance code is extended (0 = standard, 1 = extended) * @param idRemTag    Id's remote tag (0 or 1) * @param mask        Acceptance mask * @param maskIsExt   Flag if acceptance mask is extended (0 = standard, 1 = extended) * @param maskRemTag  Mask's remote tag (0 or 1) * @return Result code. See @ref CAN_RESULT */int8_t AtCanEnableRx(uint8_t noOfMsgObjs,                     uint32_t id, int8_t idIsExt, int8_t idRemTag,                     uint32_t mask, int8_t maskIsExt, int8_t maskRemTag){    int8_t i;    int8_t result;    for (i = 0; i < noOfMsgObjs; i++)    {        result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);        if (result != CAN_SUCCESS)            return result;    }    return CAN_SUCCESS;}/** * Send a CAN message * * @param frame Container for CAN message to be sent * @return Result code. See @ref CAN_RESULT */int8_t AtCanSendMsg(CANFRAME *frame){    signed char mob, j;    mob = AtCanGetFreeMob();    if (mob < 0)        return CAN_TXBUF_FULL;    // Select MOB    CANPAGE = mob << 4;    // Abort MOB and set length fields    CANCDMOB = frame->len;    // Check for ID type    if (frame->ext)    {        CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);        CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);        CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);        CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);        CANCDMOB |= _BV(IDE);    }    else    {        CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);        CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);        CANIDT3 = 0;        CANIDT4 = 0;    }    if (frame->rtr)        CANIDT4 |= _BV(RTRTAG);    for (j = 0; j < 8; j++)        CANMSG = frame->byte[j];    // Enable transmission    CANCDMOB |= _BV(CONMOB0);    return CAN_SUCCESS;}

⌨️ 快捷键说明

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