近几天在调试RT的CAN,发现了一些问题,会导致CAN通讯异常,整理了一下分享给大家
1、针对于APB1总线为42M的时钟配置,会导致波特率异常
会有这样一种情况,比如使用了F429的芯片,但是外部配了个8M XTAL,所以过了锁相环之后一般是168M的sys_clock,这样会导致APB1总线为42M,而RT在做CAN的波特率的时候针对于APB1时钟42M和45M的配置是不一样的。
如下图
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\
defined(STM32F401xC) || defined(STM32F401xE) || 1 /* 42MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
{
{CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_4TQ | 3)},
{CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ | CAN_BS2_5TQ | 4)},
{CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_4TQ | 6)},
{CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 12)},
{CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 24)},
{CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 30)},
{CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 60)},
{CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 150)},
{CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 300)}
};
#else /* APB1 45MHz(max) */
static const struct stm32_baud_rate_tab can_baud_rate_tab[] =
{
{CAN1MBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 3)},
{CAN800kBaud, (CAN_SJW_2TQ | CAN_BS1_8TQ | CAN_BS2_5TQ | 4)},
{CAN500kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 6)},
{CAN250kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 12)},
{CAN125kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 24)},
{CAN100kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 30)},
{CAN50kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 60)},
{CAN20kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 150)},
{CAN10kBaud, (CAN_SJW_2TQ | CAN_BS1_9TQ | CAN_BS2_5TQ | 300)}
};
#endif
当然原来RT的42M的时钟配置不是这样的,(官方给的42M的时钟配置和45M的是完全一样的,我的RT是4.0.3)以上代码是改过后的42M的时钟配置
2、RT的CAN设备的使用会导致当前线程会被阻塞,CAN设备有时也会被阻塞
该问题主要是由于drv_can.c里的底层的错误状态导致进入无效循坏。当然这个问题在论坛里好多大神进行过讨论,亲测注释掉错误标志是最为有限的方法,其余的包括开启自动重发等等,皆试过,没有任何用,改后的代码在下方,仅供参考
static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
{
CAN_HandleTypeDef *hcan;
hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle;
struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
CAN_TxHeaderTypeDef txheader = {0};
HAL_CAN_StateTypeDef state = hcan->State;
RT_ASSERT(IS_CAN_DLC(pmsg->len));
if ((state == HAL_CAN_STATE_READY) ||
(state == HAL_CAN_STATE_LISTENING))
{
switch (1 << box_num)
{
case CAN_TX_MAILBOX0:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0) != SET)
{
// hcan->State = HAL_CAN_STATE_ERROR;
/* Return function status */
return -RT_ERROR;
}
break;
case CAN_TX_MAILBOX1:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1) != SET)
{
/* Change CAN state */
// hcan->State = HAL_CAN_STATE_ERROR;
/* Return function status */
return -RT_ERROR;
}
break;
case CAN_TX_MAILBOX2:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2) != SET)
{
/* Change CAN state */
// hcan->State = HAL_CAN_STATE_ERROR;
/* Return function status */
return -RT_ERROR;
}
break;
default:
RT_ASSERT(0);
break;
}
if (RT_CAN_STDID == pmsg->ide)
{
txheader.IDE = CAN_ID_STD;
RT_ASSERT(IS_CAN_STDID(pmsg->id));
txheader.StdId = pmsg->id;
}
else
{
txheader.IDE = CAN_ID_EXT;
RT_ASSERT(IS_CAN_EXTID(pmsg->id));
txheader.ExtId = pmsg->id;
}
if (RT_CAN_DTR == pmsg->rtr)
{
txheader.RTR = CAN_RTR_DATA;
}
else
{
txheader.RTR = CAN_RTR_REMOTE;
}
/* clear TIR */
hcan->Instance->sTxMailBox[box_num].TIR &= CAN_TI0R_TXRQ;
/* Set up the Id */
if (RT_CAN_STDID == pmsg->ide)
{
hcan->Instance->sTxMailBox[box_num].TIR |= (txheader.StdId << CAN_TI0R_STID_Pos) | txheader.RTR;
}
else
{
hcan->Instance->sTxMailBox[box_num].TIR |= (txheader.ExtId << CAN_TI0R_EXID_Pos) | txheader.IDE | txheader.RTR;
}
/* Set up the DLC */
hcan->Instance->sTxMailBox[box_num].TDTR = pmsg->len & 0x0FU;
/* Set up the data field */
WRITE_REG(hcan->Instance->sTxMailBox[box_num].TDHR,
((uint32_t)pmsg->data[7] << CAN_TDH0R_DATA7_Pos) |
((uint32_t)pmsg->data[6] << CAN_TDH0R_DATA6_Pos) |
((uint32_t)pmsg->data[5] << CAN_TDH0R_DATA5_Pos) |
((uint32_t)pmsg->data[4] << CAN_TDH0R_DATA4_Pos));
WRITE_REG(hcan->Instance->sTxMailBox[box_num].TDLR,
((uint32_t)pmsg->data[3] << CAN_TDL0R_DATA3_Pos) |
((uint32_t)pmsg->data[2] << CAN_TDL0R_DATA2_Pos) |
((uint32_t)pmsg->data[1] << CAN_TDL0R_DATA1_Pos) |
((uint32_t)pmsg->data[0] << CAN_TDL0R_DATA0_Pos));
/* Request transmission */
SET_BIT(hcan->Instance->sTxMailBox[box_num].TIR, CAN_TI0R_TXRQ);
return RT_EOK;
}
else
{
/* Update error code */
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
return -RT_ERROR;
}
}
原作者:jia868