主题中讨论的其他器件:LAUNCHXL-F28379D、 C2000WARE
标题: 如何正确设置两个 CAN 线路以处理中断
器件:TMS320F28379DZWTT
问题:
我一直在使用 launchpad LAUNCHXL-F28379D,并尝试在项目上使用两个 CAN 线路。
CANB 与 GPIO 17和12正确设置、CANA 连接到外部收发器。
我按照 C2000Ware 示例将 ISR 设置为在收到 CAN 消息时关闭。
CANB 工作正常。
Cana 的问题是我能够正确地发送邮件,但它不会消失。
借助 CAN 监听器、我可以向 F28379D 发送消息、但我猜 ISR 永远不会启动。
我认为中断线有问题、但我不知道是什么。
以下是我的代码:
#include "CAN_management.h"
void canSetup()
{
//
//为 CANTX/CANRX 配置 GPIO 引脚
//
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANRXB);
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANTXB);
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANRXA);
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANTXA);
//
//初始化 CAN 控制器
//
CAN_initModule (CANB_BASE);
CAN_initModule (CANA_base);
//
//为每个模块将 CAN 总线位速率设置为500kHz
//有关如何设置的信息,请参阅驱动程序库用户指南
//更严格的计时控制。 此外、请参阅器件数据表
//了解有关 CAN 模块计时的更多信息。
//
CAN_setBitRate (CANB_BASE、DEVICE_SYSCLK_FREQ、1000000、10);
CAN_setBitRate (CANA_base、DEVICE_SYSCLK_FREQ、1000000、10);
//
//from CAN_ex2_loopback_interrupts.c example ----------------------
//
//
//
//在 CAN 外设上启用中断。
//启用 CAN_CTL 中的中断线路0、错误和状态更改中断
//寄存器。
//
CAN_enableInterrupt (CANB_BASE、CAN_INT_IE0 | CAN_INT_ERROR |
CAN_INT_STATUS);
CAN_enableInterrupt (CANA_base、CAN_INT_IE1 | CAN_INT_ERROR |
CAN_INT_STATUS);
//
//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
//这在 PIE 矢量表中注册中断处理程序。
//
INTERRUPT_REGTER (INT_CANB0、&CANISR_B);
INTERRUPT_REGTER (INT_CANA1、&CANISR_A);
//
//启用 CAN 中断信号
//
INTERRUPT_ENABLE (INT_CANB0);
CAN_enableGlobalInterrupt (CANB_BASE、CAN_GLOBAL_INT_CANINT0);
INTERRUPT_ENABLE (INT_CANA1);
CAN_enableGlobalInterrupt (CANA_base、CAN_GLOBAL_INT_CANINT1);
//
//初始化用于接收 CAN 消息的接收消息对象。
int i;
对于(I = 0;I<4;I++)
{
CAN_setupMessageObject (CANB_BASE、obj_ID_fin_AMK、AMK_VAL_1_IDS[i]、 //AMK 实际值1.
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_RX、0x1FFFFFF0、
CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER、MSG_DATA_LENGTH);
CAN_setupMessageObject (CANB_BASE、obj_ID_fin_AMK、AMK_VAL_2_IDS[i]、 //AMK 实际值2.
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_RX、0x1FFFFFF0、
CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER、MSG_DATA_LENGTH);
CAN_setupMessageObject (CANB_BASE、(14 + I)、AMK_setpoints_IDS[i]、 //AMK 设置点
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_TX、0、
CAN_MSG_OBJ_NO_FLAGS、sizeof (CAN_AMK_SET_POIN[i]);
}
CAN_setupMessageObject (CANB_BASE、obj_ID_fin_SENDYNE、SENDYNE_ID、 //SENDYNE
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_RX、0x0、
CAN_MSG_OBJ_RX_INT_ENABLE、MSG_DATA_LENGTH);
CAN_setupMessageObject (CANA_base、1、0x120、
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_RX、0x0、
CAN_MSG_OBJ_RX_INT_ENABLE、MSG_DATA_LENGTH);
CAN_setupMessageObject (CANA_base、2、0x100、
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_TX、0、
CAN_MSG_OBJ_NO_FLAGS、8);
//
//启动 CAN 模块操作
//
CAN_startModule (CANB_BASE);
CAN_startModule (CANA_base);
}
//
// CAN ISR -当 CAN 中断为时调用的中断服务例程
// 触发。 它会检查中断的原因、和
// 保留已发送的所有消息的计数。
//
_interrupt void
CANISR_B (空)
{
uint32_t status;
//
//读取 CAN 中断状态以查找中断原因
//
状态= CAN_getInterruptCase (CANB_BASE);
//
//如果原因是控制器状态中断,则获取状态
//
if (status =CAN_INT_INT0ID_STATUS)
{
//
//读取控制器状态。 这将返回状态字段
//可以指示各种错误的错误位。 错误处理
//本示例中不是为了简单起见。 请参阅
// API 文档,了解有关错误状态位的详细信息。
//读取此状态的操作将清除中断。
//
状态= CAN_getStatus (CANB_BASE);
//
//检查是否发生错误。
//
if (((status &~(CAN_STATUS_TXOK | CAN_STATUS_RXOK))!= 7)&&
((STATUS &μ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK))!= 0))
{
//
//设置一个标志来指示可能发生的某些错误。
//
errorFlag = 1;
}
}
//
//检查原因是否是接收消息对象2
//
否则、如果(status =obj_ID_f发 件人_amk)
{
//
//获取收到的消息
//
CAN_readMessage (CANB_BASE、obj_ID_fin_AMK、AMK_values_temp);
ID = getMessageID (CANB_BASE、obj_ID_f发 件人_AMK);
if (getAMKValNumber (id)= 1)
{
GPIO_togglePin (DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
READ_AMK_Values1 (AMK_values_temp、getMotorIndex (id));
}
否则、如果(getAMKValNumber (id)== 2)
{
GPIO_togglePin (DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
READ_AMK_Values2 (AMK_values_temp、getMotorIndex (id));
}
//
//到达这一点意味着 RX 中断发生在上
//报文对象2、报文 RX 完成。 清除
//消息目标中断。
//
CAN_clearInterruptStatus (CANB_BASE、OBJ_ID_FOR_AMK);
//
//递增计数器以跟踪已有多少消息
//已收到。 在实际应用中、这可用于将标志设置为
//指示何时接收到消息。
//
//
//由于接收到消息,请清除所有错误标志。
//
错误标志= 0;
}否则、如果(状态= obj_ID_fin_SENDYNE)
{
//
//获取收到的消息
//
CAN_readMessage (CANB_BASE、obj_ID_fin_SENDYNE、(uint16_t *) CAN_SENDYNE_ACT_VALUES);
ID = getMessageID (CANB_BASE、obj_ID_fin_SENDYNE);
READ_SENDYNE_Message (CAN_SENDYNE_ACT_VALUES);
GPIO_togglePin (DEVICE_GPIO_PIN_LED2);
rxBMsgCount++;
CAN_clearInterruptStatus (CANB_BASE、OBJ_ID_FOR_SENDYNE);
}
//
//如果发生意外导致中断的情况,这将对中断进行处理。
//
其他
{
//
//可以在此处执行伪中断处理。
//
}
//
//清除 CAN 中断线的全局中断标志
//
CAN_clearGlobalInterruptStatus (CANB_BASE、CAN_GLOBAL_INT_CANINT0);
//
//确认位于组9中的此中断
//
INTERRUPT_clearACKGROUP (INTERRUPT_ACK_group9);
}
_interrupt void
CANISR_A (空)
{
uint32_t status;
//
//读取 CAN 中断状态以查找中断原因
//
状态= CAN_getInterruptCus层(CANA_base);
//
//如果原因是控制器状态中断,则获取状态
//
if (status =CAN_INT_INT0ID_STATUS)
{
//
//读取控制器状态。 这将返回状态字段
//可以指示各种错误的错误位。 错误处理
//本示例中不是为了简单起见。 请参阅
// API 文档,了解有关错误状态位的详细信息。
//读取此状态的操作将清除中断。
//
状态= CAN_getStatus (CANA_base);
//
//检查是否发生错误。
//
if (((status &~(CAN_STATUS_TXOK | CAN_STATUS_RXOK))!= 7)&&
((STATUS &μ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK))!= 0))
{
//
//设置一个标志来指示可能发生的某些错误。
//
errorFlag = 1;
}
}
//
//检查原因是否是接收消息对象2
//
否则、如果(status = 1)
{
//
//获取收到的消息
//
CAN_readMessage (CANA_base、1、RX_A_temp);
GPIO_togglePin (DEVICE_GPIO_PIN_LED2);
//
//到达这一点意味着 RX 中断发生在上
//报文对象2、报文 RX 完成。 清除
//消息目标中断。
//
CAN_clearInterruptStatus (CANA_base、1);
//
//递增计数器以跟踪已有多少消息
//已收到。 在实际应用中、这可用于将标志设置为
//指示何时接收到消息。
//
rxAMsgCount++;
//
//由于接收到消息,请清除所有错误标志。
//
错误标志= 0;
}
//
//如果发生意外导致中断的情况,这将对中断进行处理。
//
其他
{
//
//可以在此处执行伪中断处理。
//
}
//
//清除 CAN 中断线的全局中断标志
//
CAN_clearGlobalInterruptStatus (CANA_base、CAN_GLOBAL_INT_CANINT1);
//
//确认位于组9中的此中断
//
INTERRUPT_clearACKGROUP (INTERRUPT_ACK_group9);
}
uint32_t getMessageID (uint32_t base、uint32_t Objid)
{
uint32_t msgid = 0;
CAN_transferMessage (base、2、Objid、false);
msgid = HWREG (base + CAN_O_IF2ARB);
msgid &= CAN_IF2ARB_STD_ID_M;
msgid = msgid >> CAN_IF2ARB_STD_ID_S;
返回 msgid;
}
请注意、在我的项目中、我还在使用 CPU 定时器中断0、1和2。
感谢您的任何帮助。
Alessandro Fano