打印
[CAN-bus/DeviceNet]

LPC2378的CAN接口求助

[复制链接]
3790|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mildlioncn|  楼主 | 2009-10-31 14:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 mildlioncn 于 2009-11-1 09:22 编辑

驱动器用的是TJA1050,做了两块板子,进行CAN总线通讯实验。一发一收正常,速率大约为100K,并且启动了滤波器。但是我改了两个都发送,并且都可以接收对方的数据,就不能正常工作了。好像收不到数据了。估计可能总线竞争吧。在论坛里找了半天看有无解决办法,好像有一篇和我的类似,但没有给出解决方法。论坛里都说可能是应用层的问题,但在应用上应注意什么问题呢????
波特率肯定没有问题的,否则没有办法一发一收。
通信距离近得很,可以不计。
100K也不算太快。
接收采用的中断方法,在ISR里也仅仅是把数据放在缓冲区里,没有做别的事情。
发送采用查询的方式。
标准帧的格式。一个为0x100,另一个0x110。
我想有没有可能是因为总线竞争导致总线关闭,CAN控制器**了???
就是不知道在应用层里有些什么设置可以解决总线竞争的问题。
谢谢了。

相关帖子

沙发
mildlioncn|  楼主 | 2009-11-1 09:24 | 只看该作者
我已经部分解决问题了。确实是软件上的问题。但是还是会出现错误。
1# mildlioncn

使用特权

评论回复
板凳
mildlioncn|  楼主 | 2009-11-1 18:49 | 只看该作者
自己顶一个了。经过一天一夜的奋战,终于初步告捷。采用了FULLCAN的模式。之前没有成功,可能因为中断和中断标志位的问题。还是很感谢论坛里的帖子,让我受益匪浅,任何协议必须吃透,才能解决问题。

使用特权

评论回复
地板
mildlioncn|  楼主 | 2009-11-1 18:51 | 只看该作者
初步成功的代码贴出来和大家分享了:

#include "LPC23xx.h"                                       
#include "type.h"
#include "irq.h"
#include "can.h"
#include "uart.h"

// Receive Queue: one queue for each CAN port
extern CAN_MSG MsgBuf_RX1;
extern volatile DWORD CAN1RxDone;
extern volatile DWORD FullCANRxDone;

DWORD CANStatus;
DWORD CAN1RxCount = 0;
DWORD CAN1ErrCount = 0;

_AF_AUTO_STORE_MSG FullCanAutoMsg;

/******************************************************************************
** Function name:                CAN_ISR_Rx1
**
** Descriptions:                CAN Rx1 interrupt handler
**
** parameters:                        None
** Returned value:                None
**
******************************************************************************/
void CAN_ISR_Rx1( void )
{
  DWORD * pDest;

  Print_Enter();
  Print_String("The pro has entered the CAN_ISR_Rx1!");

  // initialize destination pointer
  pDest = (DWORD *)&MsgBuf_RX1;
  *pDest = CAN1RFS;  // Frame

  pDest++;
  *pDest = CAN1RID; // ID                //change by gongjun

  pDest++;
  *pDest = CAN1RDA; // Data A

  pDest++;
  *pDest = CAN1RDB; // Data B
       
  CAN1RxDone = TRUE;
  CAN1CMR = CAN1CMR | 0x04; // release receive buffer and reset RI flag
  return;
}

/*****************************************************************************
** Function name:                CAN_Handler
**
** Descriptions:                CAN interrupt handler
**
** parameters:                        None
** Returned value:                None
**
*****************************************************************************/
void CAN_Handler(void) __irq
{
        unsigned int StatInt;
        unsigned int StatIntOfFullCAN;
        unsigned int dat;
        unsigned int *pFrame;
        _AF_ATUO_FRMSTAT_MSG * pAutoFrm;               

        //print the CAN1ICR register       
        StatInt = CAN1ICR;        //when CAN1ICR is read,the relevant bit will be cleared but the RI
        Print_Enter();
        Print_String("The Pro has entered the CAN_Handler!");
        Print_Enter();
        PrintLong(StatInt);
       
        //print the CAN_FULLCAN_IC0 register
        Print_Enter();
        StatIntOfFullCAN = CAN_FULLCAN_IC0;
        Print_String("The CAN_FULLCAN_IC0 is : ");       
        PrintLong(StatIntOfFullCAN);
        Print_Enter();

        if(StatIntOfFullCAN)        //received the FULLCAN Message
        {
                FullCANRxDone = TRUE;
                //the Index is certain to be 2, and it may be modified.
                pFrame = (unsigned int *)(0xE0038000+Size_LookUp_Table+2*12);
                pAutoFrm = (_AF_ATUO_FRMSTAT_MSG *)(0xE0038000+Size_LookUp_Table+2*12);       
                //save the Message Frame State
                FullCanAutoMsg.FRM.dwValue = *pFrame;
                PrintLong(*pFrame);        //print the Frame State
                pAutoFrm->Bits.SEM = 0;        //clear the semaphore               
                Print_Enter();
                pFrame++;
                FullCanAutoMsg.DataA = *pFrame;         //Get the Data
                PrintLong(FullCanAutoMsg.DataA);
                Print_Enter();
                pFrame++;
                FullCanAutoMsg.DataB = *pFrame;                //Get the Data
                PrintLong(FullCanAutoMsg.DataB);
                Print_Enter();
        }

        if(StatInt)
        {
                if(StatInt & (1<<0))        //the receive int
                {
                        CAN_ISR_Rx1();                 
                }
       
                if(StatInt & (1<<1))        //the TX1 Interrupt
                {
                        Print_Enter();
                        Print_String("The TX1 Int has taken place!");                 
                }
       
                if(StatInt & (1<<2))        //the error warning        Interrupt
                {
                        Print_Enter();
                        Print_String("The error warning        Int has taken place!");                 
                }
       
                if(StatInt & (1<<3))        //the data overrun Interrupt
                {
                        Print_Enter();
                        Print_String("The data overrun Int has taken place!");                 
                }
       
                if(StatInt & (1<<4))        //the Wake-Up Interrupt
                {
                        Print_Enter();
                        Print_String("The Wake-Up Int has taken place!");                 
                }
               
                if(StatInt & (1<<5))        //the error passive Interrupt
                {
                        Print_Enter();
                        Print_String("The Error Passive Int has taken place!");                 
                }
       
                if(StatInt & (1<<6))        //the Arbitration Lost Interrupt
                {
                        Print_Enter();
                        Print_String("The Arbitration Lost Int has taken place!");                 
                }
       
                if(StatInt & (1<<7))        //the Bus Error Interrupt
                {
                        Print_Enter();
                        Print_String("The Bus Error Int has taken place!");                 
                }
       
                if(StatInt & (1<<8))        //the ID Ready Interrupt
                {
                        Print_Enter();
                        Print_String("The ID Ready Int has taken place!");                 
                }
       
                if(StatInt & (1<<9))        //the TX2 Interrupt
                {
                        Print_Enter();
                        Print_String("The TX2 Int has taken place!");                 
                }
       
                if(StatInt & (1<<10))        //the TX3 Interrupt
                {
                        Print_Enter();
                        Print_String("The TX3 Int has taken place!");                 
                }
        }
       
        if ( CAN1GSR & (1 << 6 ) )
        {
                /* The error count includes both TX and RX */
                CAN1ErrCount = (CAN1GSR >> 16 );
        }

  VICVectAddr = 0;                /* Acknowledge Interrupt */
  return;
}

/******************************************************************************
** Function name:                CAN_Init
**
** Descriptions:                Initialize CAN, install CAN interrupt handler
**
** parameters:                        bitrate
** Returned value:                true or false, false if initialization failed.
**
******************************************************************************/
DWORD CAN_Init( DWORD can_btr )
{
  CAN1RxDone = FALSE;
  FullCANRxDone = FALSE;

  PCONP |= (1 << 13) | (1 << 14);        // Enable clock to the peripheral

  PINSEL0        &= ~0x00000F0F;
  PINSEL0 |= 0x0000A05;        // port0.0~1, function 0x01, port0.4~5, function 0x10

  CAN1MOD = CAN2MOD = 1;        // Reset CAN
  CAN1IER = CAN2IER = 0;        // Disable Receive Interrupt
  CAN1GSR = CAN2GSR = 0;        // Reset error counter when CANxMOD is in reset

  CAN1BTR = CAN2BTR = can_btr;
  CAN1MOD = CAN2MOD = 0x0;        // CAN in normal operation mode

  // Install CAN interrupt handler
  install_irq( 23, (void *)CAN_Handler, HIGHEST_PRIORITY );
  CAN1IER = CAN2IER = EIE | DOIE | WUIE | EPIE | ALIE | BEIE;//0x7FF;//0x01;                // Enable receive interrupts
  return( TRUE );
}

/******************************************************************************
** Function name:                CAN_SetACCF_Lookup
**
** Descriptions:                Initialize CAN, install CAN interrupt handler
**
** parameters:                        bitrate
**
** Returned value:                true or false, false if initialization failed.
**
** Revised:                                2009.11.1: add enable-bit of fullcan interrupt
******************************************************************************/
void CAN_SetACCF_Lookup( void )
{
        DWORD address = 0;
        _AF_SFF_CELL Id_Sff_Set;

           CAN_SFF_SA = Size_LookUp_Table;        // Set byte size of fullcan look-up table;

        Id_Sff_Set.dwValue = 0;
        Id_Sff_Set.Bits.UpID = EXP_STD_ID - 1;        //the upper id
        Id_Sff_Set.Bits.UpFuE = 1;                                 //enble fullcan int bit
        Id_Sff_Set.Bits.UpCh = 0;

        Id_Sff_Set.Bits.LoID = EXP_STD_ID - 2;                //the lower id
        Id_Sff_Set.Bits.LoFuE = 1;
        Id_Sff_Set.Bits.LoCh = 0;
          
        *((volatile DWORD *)(CAN_MEM_BASE + address)) = Id_Sff_Set.dwValue;
        address += 4;

        Id_Sff_Set.dwValue = 0;
        Id_Sff_Set.Bits.UpID = EXP_STD_ID+1;        //the upper id
        Id_Sff_Set.Bits.UpFuE = 1;                                 //enble fullcan int bit
        Id_Sff_Set.Bits.UpCh = 0;

        Id_Sff_Set.Bits.LoID = EXP_STD_ID;                //the lower id
        Id_Sff_Set.Bits.LoFuE = 1;
        Id_Sff_Set.Bits.LoCh = 0;
          
        *((volatile DWORD *)(CAN_MEM_BASE + address)) = Id_Sff_Set.dwValue;
        address += 4;

        CAN_SFF_GRP_SA = address;                 // Set group standard Frame
        CAN_EFF_SA = address;                         // Set explicit extended Frame
        CAN_EFF_GRP_SA = address;                  // Set group extended Frame  
        CAN_EOT = address;                                  // Set End of Table

        CAN_FULLCAN_IE = 0x01;                        // Global Enable-bit of FullCan interrupt

        return;
}

/******************************************************************************
** Function name:                CAN_SetACCF
**
** Descriptions:                Set acceptance filter and SRAM associated with       
**
** parameters:                        ACMF mode
** Returned value:                None
**
**
******************************************************************************/
void CAN_SetACCF( DWORD ACCFMode )
{
        switch ( ACCFMode )
        {
                case ACCF_OFF:
                         CAN_AFMR = ACCFMode;
                         CAN1MOD = CAN2MOD = 1;        // Reset CAN
                         CAN1IER = CAN2IER = 0;        // Disable Receive Interrupt
                         CAN1GSR = CAN2GSR = 0;        // Reset error counter when CANxMOD is in reset
                         break;
               
                case ACCF_BYPASS:
                         CAN_AFMR = ACCFMode;
                         break;
               
                case ACCF_ON:
                case ACCF_FULLCAN:
                         CAN_AFMR = ACCF_OFF;
                         CAN_SetACCF_Lookup();
                         CAN_AFMR = ACCF_FULLCAN;//ACCFMode;
                         break;
               
                default:
                         break;
        }
        return;
}

/******************************************************************************
** Function name:                CAN1_SendMessage
**
** Descriptions:                Send message block to CAN1       
**
** parameters:                        pointer to the CAN message
** Returned value:                true or false, if message buffer is available,
**                                                message can be sent successfully, return TRUE,
**                                                otherwise, return FALSE.
**
******************************************************************************/
DWORD CAN1_SendMessage( CAN_MSG *pTxBuf )
{
  DWORD CANStatus;

  CANStatus = CAN1SR;
  if ( CANStatus & 0x00000004 )        //visit TBS1 bit
  {
        CAN1TFI1 = pTxBuf->Frame & 0xC00F0000;
        CAN1TID1 = pTxBuf->MsgID;
        CAN1TDA1 = pTxBuf->DataA;
        CAN1TDB1 = pTxBuf->DataB;
        CAN1CMR = 0x21;                                //set TR and STB1 bit
        return ( TRUE );        
  }
  else if ( CANStatus & 0x00000400 )
  {
        CAN1TFI2 = pTxBuf->Frame & 0xC00F0000;
        CAN1TID2 = pTxBuf->MsgID;
        CAN1TDA2 = pTxBuf->DataA;
        CAN1TDB2 = pTxBuf->DataB;
        CAN1CMR = 0x41;                          //set TR and STB2 bit
        return ( TRUE );
  }
  else if ( CANStatus & 0x00040000 )
  {       
        CAN1TFI3 = pTxBuf->Frame & 0xC00F0000;
        CAN1TID3 = pTxBuf->MsgID;
        CAN1TDA3 = pTxBuf->DataA;
        CAN1TDB3 = pTxBuf->DataB;
        CAN1CMR = 0x81;                         //set TR and STB3 bit
        return ( TRUE );
  }
  return ( FALSE );
}
          
/******************************************************************************
**                            End Of File
******************************************************************************/

使用特权

评论回复
5
mildlioncn|  楼主 | 2009-11-1 18:54 | 只看该作者
在中断服务程序里头,我只是简单的打印了一些信号,如果真的出现了这些错误,程序该如何处理呢?重新初始化CAN?还是?

使用特权

评论回复
6
huajinok| | 2009-11-9 22:09 | 只看该作者
有没有不用FULLCAN的报文滤波

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

22

帖子

1

粉丝