1  /  1  页   1 跳转 查看:3910

关于MCP2510的开发问题

关于MCP2510的开发问题

我在使用贵公司的MCP2510 CAN控制器时,出现了以下问题,希望能够得到支持。
1. 一节点向MCP2510发送报文过快时,如连续无间隔发送1000帧,若单片机处理比较慢,会丢失一部分报文,这是正常现象。
但是与此同时,会从接收缓存器中收到一些多余的错误报文。不知道是什么原因。
2. 当CANINIF.ERRIE 为1时,ELGF却为0,不知道为何会产生这个中断。

谢谢
 

回复:关于MCP2510的开发问题

接收发送波特率一样吗?估计是设置有问题,是否能把程序粘贴出来看看。
贝能国际智能电子产品解决方案专家
 

回复 2F zengsy 的帖子

波特率一样,都是125K。
现在情况是,如果上层协议模块处理快,则完全没有问题,不会有错误中断,也不会多收到报文。
但是一旦上层处理速度下降(在处理其他模块时),则会出现问题。

我们用的是S3C2440,系统是linux-2.6,12
代码一会贴出来~
 

回复:关于MCP2510的开发问题

代码
感觉错误可能在初始化和中断处理的部分,所以先贴出这两个函数的代码。

#define    BFPCTRL_INIT_VAL    (0x00)
//(0x3c)
/// Transmitter Request to Send pin : Digital Input
#define    TXRTSCTRL_INIT_VAL    (0x00)
/// Configure the bit timing : 125kHZ
#define    CNF1_INIT_VAL        (0x03)
#define    CNF2_INIT_VAL        (0x9e)
#define    CNF3_INIT_VAL        (0x03)

// Configure the interrupt : disable all interrupts
#define    CANINTE_INIT_VAL    (0x63)
//(0xe3)
#define    CANINTF_INIT_VAL    (0x00)
// Reset Error Flag Register
#define    EFLG_INIT_VAL        (0x00)
// Transmitter Buffer Control
#define    TXB0CTRL_INIT_VAL    (0x00)
#define TXB1CTRL_INIT_VAL    (0x00)
#define TXB2CTRL_INIT_VAL    (0x00)
// Receiver Buffer 0 Control Register : Turn remote frame off, turn filter RXF0 on, turn rollover on
#define    RXB0CTRL_INIT_VAL    (0x24)
//#define    RXB0CTRL_INIT_VAL    (0x64)
// Receiver Buffer 1 Control Register : Turn remote frame off, turn filter RXF0 on
#define    RXB1CTRL_INIT_VAL    (0X40)
//(0x20)
// Receiver Buffer n Fliter : set the fliter SID = 20
#define RXFnSIDH_INIT_VAL    (0x02)
#define RXFnSIDL_INIT_VAL    (0x80)

#define RXMnSIDH_INIT_VAL    (0xff)
#define RXMnSIDL_INIT_VAL    (0xff)

void
MCP2510_Init(int MinorNum)
{
    printk("This is MCP2510_Init!\n");
    printk("Configure the SPI Interface in MX1\n");
    /// Configure the SPI Interface in MX1
    SPI_Init();

    printk("Configure the mcp2510 through spi interface\n");
    printk("in test, leave them alone\n");
    /// Configure the mcp2510 through spi interface
   
    /// Reset controller
    CAN_SPI_CMD( SPI_CMD_RESET, ARG_UNUSED, ARG_UNUSED, ARG_UNUSED );

    /// CONFIG MODE
    CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x80 );       

    printk("%x\n", CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED ));
    /// Make sure we are in configuration mode
    while( (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5)!=0x04 );

    /// Start configuration
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->BFPCTRL)),     BFPCTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXRTSCTRL)),     TXRTSCTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF3)),     CNF3_INIT_VAL,         ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF2)),     CNF2_INIT_VAL,         ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF1)),    CNF1_INIT_VAL,         ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTE)),    CANINTE_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTF)),     CANINTF_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->EFLG)),     EFLG_INIT_VAL,         ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0CTRL)),     TXB0CTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB1CTRL)),     TXB1CTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB2CTRL)),     TXB2CTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0CTRL)),     RXB0CTRL_INIT_VAL,     ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1CTRL)),     RXB1CTRL_INIT_VAL,     ARG_UNUSED);
//    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0SIDH)),  RXBnSIDH_INIT_VAL,     ARG_UNUSED);
//    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1SIDH)),  RXBnSIDH_INIT_VAL,    ARG_UNUSED);
//    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0SIDL)),  RXBnSIDL_INIT_VAL,    ARG_UNUSED);
//    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1SIDL)),  RXBnSIDL_INIT_VAL,    ARG_UNUSED);
   
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXM0SIDH)),  RXMnSIDH_INIT_VAL,    ARG_UNUSED);   
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXM0SIDL)),  RXMnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF0SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF0SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF1SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF1SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF2SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF2SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF3SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF3SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF4SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF4SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF5SIDH)),  RXFnSIDH_INIT_VAL,    ARG_UNUSED);
    CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXF5SIDL)),  RXFnSIDL_INIT_VAL,    ARG_UNUSED);       
    /// Switch to normal mode or loopback mode ( for testing)
#if    0
    /// LOOP BACK MODE
    printk("config loop back!%x\n", TOLONG(&MCP2510_MAP->CANCTRL));
    CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x40 );
#endif
    /// NORMAL OPERATION MODE
    CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );
       
    /// Flush the MX1 SPI receive buffer
    CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED );
}



static void
mcpcan0_handler(int irq, void *dev_id, struct pt_regs *regs)
{
    struct MCP_device    *dev = dev_id;
    struct mcpcan_data    datagram;
    char    regvalue, regvalue2;
    int     i;
    regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
//    printk("CANINTF = 0x%02x\n",regvalue);
    //printk("recv is %d\n", recvCount);
    //while (regvalue & 0xe3) {
    while (regvalue & 0x63) {
        if (regvalue & 0x60) {
            /*printk("CAN error with CANINTF = 0x%02x.\n", regvalue);
            if (regvalue & 0x80) {
                printk("MERRF:message error.\n");
            }
            if (regvalue & 0x40) {
                printk("WAKIF:wake up interrupt.\n");
                CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );
                break;
            }
            if (regvalue & 0x20) {
                printk("ERRIF:CAN bus error interrupt.\n");
           

            regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->EFLG)), ARG_UNUSED, ARG_UNUSED );
            printk("EFLG = 0x%02x.\n", regvalue2);
            if (regvalue2) {
                overFlow++;
                CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->EFLG)), 0x00, ARG_UNUSED);
            }
            }*/
            /*
            regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->TEC)), ARG_UNUSED, ARG_UNUSED );
            printk("TEC = 0x%02x.\n", regvalue2);
            regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->REC)), ARG_UNUSED, ARG_UNUSED );
            printk("REC = 0x%02x.\n", regvalue2);
            */
            err++;
            //printk("err is %d, recv is %d, overflow is %d\n", err, recvCount, overFlow);
            /*memcpy(&datagram, (void *)(dev->recvBuf + dev->recvHead - 28), 28);
            for (i = 0; i < 8; i++) {
                printk("%d ", datagram.data[i]);
            }
            printk("\n");*/
            CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x40, 0x00 );
        }
        if (regvalue & 0x01) {
            datagram.BufNo = RXBUF0;
            MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );
            //printk("RXBUF0\n");

            /// Write a 16 byte record. Assume BUF_SIZE is a multiple of 16
            memcpy((void *)(dev->recvBuf + dev->recvHead), &datagram, sizeof(struct mcpcan_data));

            /*
            if (regvalue & 0x20) {
                for (i = 0; i < datagram.DataLen; i++) {
                    printk("%d ", datagram.data[i]);
                }
                printk("\n");
            }*/

            //incr_buffer_pointer(&(dev->recvHead), sizeof(struct mcpcan_data), dev->MinorNum);
            /**
             * process the recvBuf
             * 0. normally move recvHead
             * 1. if recvFlag is 1, meaning that the buffer has full
             * then throw away the earliest frame
             * by keeping recvTail equal with recvHead
             * 2. otherwise, the buffer has not been full
             *
             * after receive the most recent frame, check the buffer
             * if the buffer has been full, set recvFlag
            */
            dev->recvHead += sizeof (struct mcpcan_data);

            if (dev->recvHead >= BUF_SIZE) {
                dev->recvHead = 0;
            }

            if (dev->recvFlag == 1) {
                dev->recvTail = dev->recvHead;
                lost++;
            } else if (dev->recvTail == dev->recvHead) {
                dev->recvFlag = 1;
            }

            /// Awake any reading process
            //wake_up_interruptible(&(dev->inq));

            /// In fact already clear interrupt bit in RX
            CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x01, 0x00 );
            recvCount++;
        }

        if (regvalue & 0x02) {
            datagram.BufNo = RXBUF1;

            MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );
            //printk("RXBUF1, %d\n", recvCount);


            /// Write a 16 byte record. Assume BUF_SIZE is a multiple of 16
            memcpy((void *)(dev->recvBuf + dev->recvHead), &datagram, sizeof(struct mcpcan_data));


            /*if (regvalue & 0x20) {
                for (i = 0; i < datagram.DataLen; i++) {
                    printk("%d ", datagram.data[i]);
                }
                printk("\n");
            }*/
            //incr_buffer_pointer(&(dev->recvHead), sizeof(struct mcpcan_data), dev->MinorNum);
            dev->recvHead += sizeof (struct mcpcan_data);
            if (dev->recvHead == BUF_SIZE) {
                dev->recvHead = 0;
            }

            if (dev->recvFlag == 1) {
                dev->recvTail = dev->recvHead;
                lost++;
            } else if (dev->recvTail == dev->recvHead) {
                dev->recvFlag = 1;
            }

            /// Awake any reading process
            //wake_up_interruptible(&dev->inq);
            /// In fact already clear interrupt bit in RX
            CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x02, 0x00 );
            recvCount++;
        }

        /// Didn't open the 3 send interrupts
        if (regvalue & 0x1c) {
            /// Clear TX bits directly(it will set 1,but no int)
            CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x1c, 0x00 );
        }

        regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
    }
    /*regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );
    printk("after interrupt processing, CANINTF = 0x%02x\n",regvalue);*/
}
 
1  /  1  页   1 跳转

版权所有 贝能国际  Burnon国际  Sitemap

Powered by Discuz!NT 2.1.202    Copyright © 2001-2012 Comsenz Inc.
Processed in 0.0312496 second(s) , 3 queries. 闽ICP备05003850号
返顶部