LPC 2292 和 LPC1758 板之间的 CAN 通信 "Start of Frame " 错误
CAN communication between LPC 2292 and LPC1758 boards "Start of Frame " error
我正在尝试在几个 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 传输器写入总线时。它得到一个总线错误。更具体地说 "Start of Frame " error
。 (我使用 Ulink2 调试器)。现在阅读 CAN 规范,我知道 CAN 消息的起始帧应该以低(显性)位开始 CAN specs ; See page 3
我该如何解决这个错误?它不是一个可配置的寄存器,我可以将第一位设置为 0 或 1。我 运行 KEIL 附带的默认 LPC 1758 CAN 代码 C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN
我认为代码很好,因为当我 运行 KEIL 模拟模式下的代码我可以看到 CAN 通信工作正常。
这 "Start of Frame" 是我遗漏的一些其他配置的副产品吗?
Update Code :
我运行默认的LPC 1758 CAN代码是KEIL自带的C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN
我觉得代码没问题因为我运行KEIL仿真模式下的代码我可以看到CAN 通信运行良好。此外,除了波特率之外,我没有对代码进行任何更改。
CAN 设置:
/*----------------------------------------------------------------------------
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;
}
这是我发送和接收的代码:
/*----------------------------------------------------------------------------
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
}
}
接收码没问题但还在发帖
/*----------------------------------------------------------------------------
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;
}
}
波特率计算:
/*----------------------------------------------------------------------------
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 */
}
我终于能够摆脱困扰我的 "Start of Frame " 错误。我与其他一些 CAN 总线代码作者进行了讨论,他建议我使用相同的 CAN 控制器来发送和接收。简而言之:
** 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
作为新手,我可能犯了这个错误。但是 KEIL 提供的默认代码显示使用备用 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 传输器写入总线时。它得到一个总线错误。更具体地说 "Start of Frame " error
。 (我使用 Ulink2 调试器)。现在阅读 CAN 规范,我知道 CAN 消息的起始帧应该以低(显性)位开始 CAN specs ; See page 3
我该如何解决这个错误?它不是一个可配置的寄存器,我可以将第一位设置为 0 或 1。我 运行 KEIL 附带的默认 LPC 1758 CAN 代码 C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN
我认为代码很好,因为当我 运行 KEIL 模拟模式下的代码我可以看到 CAN 通信工作正常。
这 "Start of Frame" 是我遗漏的一些其他配置的副产品吗?
Update Code :
我运行默认的LPC 1758 CAN代码是KEIL自带的C:\Keil_v5\ARM\Boards\Keil\MCB1700\CAN
我觉得代码没问题因为我运行KEIL仿真模式下的代码我可以看到CAN 通信运行良好。此外,除了波特率之外,我没有对代码进行任何更改。
CAN 设置:
/*----------------------------------------------------------------------------
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;
}
这是我发送和接收的代码:
/*----------------------------------------------------------------------------
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
}
}
接收码没问题但还在发帖
/*----------------------------------------------------------------------------
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;
}
}
波特率计算:
/*----------------------------------------------------------------------------
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 */
}
我终于能够摆脱困扰我的 "Start of Frame " 错误。我与其他一些 CAN 总线代码作者进行了讨论,他建议我使用相同的 CAN 控制器来发送和接收。简而言之:
** 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
作为新手,我可能犯了这个错误。但是 KEIL 提供的默认代码显示使用备用 CAN 控制器进行发送和传输。我希望这可以帮助别人 。