LPC2292和LPC1758板之间的CAN通信“帧起始”错误 [英] CAN communication between LPC 2292 and LPC1758 boards "Start of Frame " error

查看:580
本文介绍了LPC2292和LPC1758板之间的CAN通信“帧起始”错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在两个LPC设备节点之间设置CAN通信。我的设置包括写入CAN总线的几个CAN节点。例如LPC 2292 CAN控制器可以写入CAN总线,LPC1758可以接收数据。这工作完全正常现在LPC1758有2个CAN控制器,我有一个用于接收数据的设置,另一个用于作为响应在总线上传输数据。我还设置了中断处理程序,用于LPC 1758 CAN 1发送&接收和CAN 2发送&接收。 (我没有LPC 2292的代码,它不在我的控制之下)



我的问题是在LPC1758一面。这里CAN 1接收机能够从其他CAN节点获取数据,因为我可以看到被调用的中断向量处理程序。问题是当LPC 1758 CAN 2传输器写入总线时。它得到一个总线错误。更具体地说,开始帧错误。 (我使用Ulink2调试器)。现在阅读CAN规范我知道CAN消息的起始帧应该以低(主导)位开始



如何解决此错误?它不是可配置的寄存器,我可以将第一个位设置为0或1.我运行默认的LPC 1758 CAN代码,附带KEIL C:\Keil_v5\ARM\Boards\Keil\\ \\ MCB1700\CAN 我认为代码很好,因为当我在KEIL的模拟模式下运行代码时,我可以看到CAN通信工作很好。



这个开始帧是一些我失踪的其他配置的产物?

 更新代码:

我运行默认的LPC 1758 CAN代码,附带KEIL C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN 我认为代码很好,因为当我在KEIL的模拟模式下运行代码时,我可以看到CAN通信工作良好。此外,我没有对代码进行任何更改,除了波特率。
CAN设置:

  / * ----------------- -------------------------------------------------- --------- 
设置CAN接口。 CAN控制器(1..2)
* ------------------------------------- --------------------------------------- * /
void CAN_setup(uint32_t ctrl ){
LPC_CAN_TypeDef * pCAN =(ctrl == 1)? LPC_CAN1:LPC_CAN2;

if(ctrl == 1){
LPC_SC-> PCONP | =(1 LPC_PINCON-> PINSEL0 | =(1 <<0); / *引脚P0.0用作RD1(CAN1)* /
LPC_PINCON-> PINSEL0 | =(1 <<2); / * Pin P0.1用作TD1(CAN1)* /

NVIC_EnableIRQ(CAN_IRQn); / *启用CAN中断* /
} else {
LPC_SC-> PCONP | =(1 <14); / *启用CAN2块的电源* /
LPC_PINCON-> PINSEL4 | =(1 <14); / *引脚P2.7用作RD2(CAN2)* /
LPC_PINCON-> PINSEL4 | =(1 <<16); / * Pin P2.8用作TD2(CAN2)* /

NVIC_EnableIRQ(CAN_IRQn); / *启用CAN中断* /
}

LPC_CANAF-> AFMR = 2; / *默认情况下不使用过滤器* /
pCAN-> MOD = 1; / *进入复位模式* /
pCAN-> IER = 0; / *禁用所有中断* /
pCAN-> GSR = 0; / *清除状态寄存器* /
CAN_cfgBaudrate(ctrl,/ * 250000 * / 100000); / *设置位时间* /
pCAN-> IER = 0x0003; / *启用Tx和Rx中断* /
// pCAN-> IER = 0x7FF;

}

这是我的代码发送和接收:

  / * --------------------------- ------------------------------------------------- 
向CAN外设发送消息并传送。 CAN控制器(1..2)
* ------------------------------------- --------------------------------------- * /
void CAN_wrMsg(uint32_t ctrl ,CAN_msg * msg){
LPC_CAN_TypeDef * pCAN =(ctrl == 1)? LPC_CAN1:LPC_CAN2;
uint32_t CANData;

CANData =(((uint32_t)msg-> len)<< 16)& 0x000F0000 |
(msg-> format == EXTENDED_FORMAT)* 0x80000000 |
(msg-> type == REMOTE_FRAME)* 0x40000000;

if(pCAN-> SR&(1< 2)){/ *发送缓冲区1空闲* /
pCAN-> TFI1 = CANData; / *写帧信息* /
pCAN-> TID1 = msg-> id; / *写CAN消息标识符* /
pCAN-> TDA1 = *(uint32_t *)& msg-> data [0]; / *先写4个数据字节* /
pCAN-> TDB1 = *(uint32_t *)& msg-> data [4]; / *写第二个4个数据字节* /
// pCAN-> CMR = 0x31; / *选择Tx1为自发/接收* /
pCAN-> CMR = 0x21; / *开始传输,无回环* / - 这是当开始帧错误发生时

}
}

接收代码正常但仍然发布

  / *  - -------------------------------------------------- ------------------------ 
从CAN外设读取消息并释放它。 CAN控制器(1..2)
* ------------------------------------- --------------------------------------- * /
void CAN_rdMsg(uint32_t ctrl ,CAN_msg * msg){
LPC_CAN_TypeDef * pCAN =(ctrl == 1)? LPC_CAN1:LPC_CAN2;
uint32_t CANData;

/ *阅读框架信息* /
CANData = pCAN-> RFS;
msg-> format =(CANData& 0x80000000)== 0x80000000;
msg-> type =(CANData& 0x40000000)== 0x40000000;
msg-> len =((uint8_t)(CANData>> 16))&为0x0F;

msg-> id = pCAN-> RID; / *读取CAN消息标识符* /

if(msg-> type == DATA_FRAME){/ *读取数据,如果收到的消息是DATA FRAME * /
*(uint32_t *) & msg-> data [0] = pCAN-> RDA;
*(uint32_t *)& msg-> data [4] = pCAN-> RDB;
}
}

波特率计算:

  / * -------------------------------- -------------------------------------------- 
配置要求波特率。 CAN控制器(1..2)
* ------------------------------------- --------------------------------------- * /
static void CAN_cfgBaudrate(uint32_t ctrl,uint32_t baudrate){
LPC_CAN_TypeDef * pCAN =(ctrl == 1)? LPC_CAN1:LPC_CAN2;
uint32_t result = 0;
uint32_t nominal_time;

/ *确定用于PCLK * /
的标称时间,如果(((PCLK / 1000000)%6)== 0){
nominal_time = 12; / * PCLK基于72MHz CCLK * /
} else {
nominal_time = 10; / * PCLK基于100MHz CCLK * /
}

/ *准备适用于位时间寄存器的值* /
result =(PCLK / nominal_time)/ baudrate - 1;
result& = 0x000003FF;
result | = CAN_BIT_TIME [nominal_time];

pCAN-> BTR = result; / *设置位时间* /
}


解决方案

我终于可以摆脱让我陷入困境的开始框架错误。我和其他一些CAN总线代码作者讨论过,他建议我使用相同的CAN控制器进行发送和接收。简而言之:

  **不工作**:
LPC 2292:CAN 1 Rx& CAN 2 Tx
LPC 1750:CAN 1 Rx& CAN 2 TX

**工作**:
LPC 2292:CAN 1 Rx& CAN 1 Tx
LPC 1750:CAN 1 Rx& CAN 1 TX

作为新手,我可能犯了这个错误。但KEIL提供的默认代码显示使用备用CAN控制器进行发送和发送。我希望这有助于某人。


I am trying to setup CAN communication between a couple of LPC device nodes. My setup includes a couple of CAN nodes writing on to the CAN bus. For example LPC 2292 CAN controller can write on to the CAN bus and the LPC1758 can receive the data. This works perfectly fine. Now LPC1758 has 2 CAN controllers and I have setup one for receiving data and the other for transmitting data on the bus as a response. I also setup interrupt handlers for LPC 1758 CAN 1 transmit & receive and CAN 2 transmit & receive. ( I dont have code for LPC 2292. its not under my control)

My problem is at the LPC1758 side. Here the CAN 1 receiver is able to get the data from the other CAN nodes as I can see the interrupt vector handler being called. The problem is when the the LPC 1758 CAN 2 tranmistter writes to the bus . It gets a bus error . More specificially "Start of Frame " error . ( I use a Ulink2 debugger). Now reading the CAN specs I know the start frame of the CAN message should start with a low ( dominant) bit CAN specs ; See page 3

How do I go about fixing this error ? Its not a configurable register that I can set the first bit to 0 or 1. I run the default LPC 1758 CAN code that comes with KEIL C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN I think the code is fine because when I run the code in simulation mode of KEIL I can see the CAN commnication work well.

Is this "Start of Frame" a by product of some other configurations that I am missing ?

Update Code : 

I run the default LPC 1758 CAN code that comes with KEIL C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN I think the code is fine because when I run the code in simulation mode of KEIL I can see the CAN communication work well. Also I did not make any changes to the code except the baudrate. CAN setup :

/*----------------------------------------------------------------------------
  setup CAN interface.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_setup (uint32_t ctrl)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;

  if (ctrl == 1) {
    LPC_SC->PCONP       |=  (1 << 13);           /* Enable power to CAN1 block */
    LPC_PINCON->PINSEL0 |=  (1 <<  0);           /* Pin P0.0 used as RD1 (CAN1) */
    LPC_PINCON->PINSEL0 |=  (1 <<  2);           /* Pin P0.1 used as TD1 (CAN1) */

    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  } else {
    LPC_SC->PCONP       |=  (1 << 14);           /* Enable power to CAN2 block */
    LPC_PINCON->PINSEL4 |=  (1 << 14);           /* Pin P2.7 used as RD2 (CAN2) */
    LPC_PINCON->PINSEL4 |=  (1 << 16);           /* Pin P2.8 used as TD2 (CAN2) */

    NVIC_EnableIRQ(CAN_IRQn);                    /* Enable CAN interrupt */
  }

  LPC_CANAF->AFMR = 2;                           /* By default filter is not used */
  pCAN->MOD   = 1;                               /* Enter reset mode */
  pCAN->IER   = 0;                               /* Disable all interrupts */
  pCAN->GSR   = 0;                               /* Clear status register */
  CAN_cfgBaudrate(ctrl, /*250000*/ 100000);                 /* Set bit timing */
  pCAN->IER   = 0x0003;                          /* Enable Tx and Rx interrupt */
    //pCAN->IER   = 0x7FF;

}

Here is my code to transmit and receive:

/*----------------------------------------------------------------------------
  wite a message to CAN peripheral and transmit it.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_wrMsg (uint32_t ctrl, CAN_msg *msg)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t CANData;

  CANData = (((uint32_t) msg->len) << 16)     & 0x000F0000 | 
            (msg->format == EXTENDED_FORMAT ) * 0x80000000 |
            (msg->type   == REMOTE_FRAME)     * 0x40000000;

  if (pCAN->SR & (1<<2))  {                      /* Transmit buffer 1 free */
    pCAN->TFI1  = CANData;                       /* Write frame informations */
    pCAN->TID1 = msg->id;                        /* Write CAN message identifier */
    pCAN->TDA1 = *(uint32_t *) &msg->data[0];    /* Write first 4 data bytes */
    pCAN->TDB1 = *(uint32_t *) &msg->data[4];    /* Write second 4 data bytes */
    //pCAN->CMR  = 0x31;                           /* Select Tx1 for Self Tx/Rx */
    pCAN->CMR  = 0x21;                           /* Start transmission without loop-back */ -- Here is when "Start of Frame " error happens

  }
}

Receive code is fine but still posting

/*----------------------------------------------------------------------------
  read a message from CAN peripheral and release it.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
void CAN_rdMsg (uint32_t ctrl, CAN_msg *msg)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t CANData;

                                                 /* Read frame informations */
  CANData = pCAN->RFS;
  msg->format   = (CANData & 0x80000000) == 0x80000000;
  msg->type     = (CANData & 0x40000000) == 0x40000000;
  msg->len      = ((uint8_t)(CANData >> 16)) & 0x0F;

  msg->id = pCAN->RID;                           /* Read CAN message identifier */

  if (msg->type == DATA_FRAME)  {                /* Read the data if received message was DATA FRAME  */ 
    *(uint32_t *) &msg->data[0] = pCAN->RDA;
    *(uint32_t *) &msg->data[4] = pCAN->RDB;
  }
}

Baudrate Calculation:

/*----------------------------------------------------------------------------
  configure the requested baudrate.  CAN controller (1..2)
 *----------------------------------------------------------------------------*/
static void CAN_cfgBaudrate (uint32_t ctrl, uint32_t baudrate)  {
  LPC_CAN_TypeDef *pCAN = (ctrl == 1) ? LPC_CAN1 : LPC_CAN2;
  uint32_t result = 0;
  uint32_t nominal_time;

  /* Determine which nominal time to use for PCLK */
  if (((PCLK / 1000000) % 6) == 0) {
    nominal_time = 12;                   /* PCLK based on  72MHz CCLK */
  } else {
    nominal_time = 10;                   /* PCLK based on 100MHz CCLK */
  }

  /* Prepare value appropriate for bit time register */
  result  = (PCLK / nominal_time) / baudrate - 1;
  result &= 0x000003FF;
  result |= CAN_BIT_TIME[nominal_time];

  pCAN->BTR  = result;                           /* Set bit timing */
}

解决方案

I am finally able to get rid of the "Start of Frame " error that had being bogging me down. I had a discussion with some of our other CAN bus code authors and he suggested i use the same CAN controller for sending and receiving. In short this:

** Does not work** : 
LPC 2292 : CAN 1 Rx & CAN 2 Tx
LPC 1750 : CAN 1 Rx & CAN 2 TX 

** WORKS** :
LPC 2292 : CAN 1 Rx & CAN 1 Tx
LPC 1750 : CAN 1 Rx & CAN 1 TX 

Being a newbie i may have made this mistake. But the default code provided by KEIL shows using alternate CAN controllers for sending and transmitting. I hope this helps someone .

这篇关于LPC2292和LPC1758板之间的CAN通信“帧起始”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆