该问题在发送can数据时,采用查询方式
那么就会进行一个等待超时:
此时那么应该考虑是不是该标志在检测之间已经被清除了,那么还会有什么东西可能这检查之前就去清标志呢?
答案中有一个:进入中断了。
那又是什么中断呢? can发送中断
好那我们看一下发送中断里边会清除这些标志吗?
此时can发送中断函数如果没有编写中断函数或者 中断函数没有相应的HAL_CAN_Transmit_IT()来开启相应中断, ,那么can发送中断相关中断的标志位不会再打开了,也就相当于关闭了can发送中断
好,到这儿应该也明白了为什么会出现标题所说的现象:
在调用HAL_CAN_Transmit()后,can将该消息发送出去了,产生中断清除了标志,然后我们还在那儿傻等标志变化为发送成功,等不到自然就会增生timeout,然后我们判断发送没成功,进行下一次发送,can发送中断此时相当于关闭状态,本次发送数据时不会再有人来清除发送标志了,所以can发送成功,不会再有timeout了。
解决方案: 要用中断发送就用中断发送就好,不用中断发送的话关闭/不开启can发送中断就好。
另外多说一嘴: 采用查询发送时,发送成功后应清除相应标志,否则那儿永远都是发送成功。
那么就会进行一个等待超时:
while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
{
hcan->State = HAL_CAN_STATE_TIMEOUT;
__HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);
/* Process unlocked */
__HAL_UNLOCK(hcan);
return HAL_TIMEOUT;
}
}
}
产生等待超时,返回hal_timeout;但是此时却发送成功了;
此时那么应该考虑是不是该标志在检测之间已经被清除了,那么还会有什么东西可能这检查之前就去清标志呢?
答案中有一个:进入中断了。
那又是什么中断呢? can发送中断
好那我们看一下发送中断里边会清除这些标志吗?
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
.........
if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
.........
/* Clear transmission status flags (RQCPx and TXOKx) */
SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2 | \
CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
......
我们可以看到,在邮箱都为空时会清除,我们由于采用查询方式自然只会占一个邮箱,那么它发送ok了自然会产生邮箱为空的中断请求。
此时can发送中断函数如果没有编写中断函数或者 中断函数没有相应的HAL_CAN_Transmit_IT()来开启相应中断, ,那么can发送中断相关中断的标志位不会再打开了,也就相当于关闭了can发送中断
好,到这儿应该也明白了为什么会出现标题所说的现象:
在调用HAL_CAN_Transmit()后,can将该消息发送出去了,产生中断清除了标志,然后我们还在那儿傻等标志变化为发送成功,等不到自然就会增生timeout,然后我们判断发送没成功,进行下一次发送,can发送中断此时相当于关闭状态,本次发送数据时不会再有人来清除发送标志了,所以can发送成功,不会再有timeout了。
解决方案: 要用中断发送就用中断发送就好,不用中断发送的话关闭/不开启can发送中断就好。
另外多说一嘴: 采用查询发送时,发送成功后应清除相应标志,否则那儿永远都是发送成功。
while( HAL_CAN_Transmit(&hcan1, 0x1) != HAL_OK) {
if(retry++ > 5) {
iSysDebug(0, "send can data failed\r\n");
SET_BIT(hcan1.Instance->TSR, CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2 | \
CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
return HAL_ERROR;
}
}
/* Clear transmission status flags (RQCPx and TXOKx) */
SET_BIT(hcan1.Instance->TSR, CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2 | \
CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);