主题中讨论的其他器件:C2000WARE
您好!
我正在尝试在嵌入式系统上开发 CANopen 库、但我遇到了 CAN 控制器的一些问题。
我将 CCS 6.1.00022与 C 编译器 TI v15.12.4.LTS 搭配使用。
我从 C2000Ware_1_00_01_00示例项目(C2000Ware_1_00_01_00\driverlib\f2807x\examples\cpu1\can_ex3_external_transmit)和驱动程序(C2000Ware_1_00_01_driverlib\f2807x\driver\can\ex3_ex3_transmit)构建了项目"CAN"。
我稍微修改了主函数、以初始化我的硬件并通过 CAN B 模块接收和发送消息(CAN A 模块未使用)。 您可以在该帖子的底部看到我的代码。 我没有更改 CAN 驱动程序函数和 cannbISR 中断例程。
我使用邮箱2接收消息(RX 邮箱)、使用邮箱1发送消息(TX 邮箱)。
我用500kHz 的波特率将我的系统连接到 CANopen 主器件、并插入 CAN 分析器来监听消息。
当程序运行时、我看到两个问题。
问题1 -邮箱配置问题
如果我在初始化步骤后暂停程序(例如在行 CycleCounter++上)、我会找到以下值
CAN_mvL_21 = 0x800003.
这意味着邮箱1、2和32被启用。
但是我从未启用邮箱32。
此外、如果我观察从地址0x4B000开始的 RAM 区域、我会看到范围0x4B000-0x4B01F (RAM 消息对象32)中的字和范围0x4B040-0x4B05F (RAM 消息对象2)中的字具有相同的配置。
这意味着邮箱2和邮箱32具有相同的配置。
但我从未初始化邮箱32。
问题2 -发送消息
每次我通过 CAN_sendMessage 发送一条消息时、CAN 分析仪都会检测到两条消息:
- ID 为0x581且数据为0x11223344的消息(正确);
- ID 为0x345的 RTR 消息(不正确);
不应发送 RTR 消息。
发送到 TX 邮箱1的命令似乎也会触发邮箱2或32上的传输。 因为它们都是 RX 邮箱、所以会发送一条 RTR 消息、而不是一条数据消息。
但是、我从未在邮箱2或32上触发过传输。
权变措施(可能...)
我注意到、C2000Ware CAN 驱动程序对 CAN 控制器寄存器进行32位和16位访问、但在此问题中(e2e.ti.com/.../2133415 Hareesh 报告了以下注意事项:
' CAN 模块使用一个特殊的寻址方案来支持字节访问。 建议使用 HWREG_BP ()宏(使用__byte_peripheral_32 ()内在函数)仅使用对 CAN 寄存器的32位访问。 如果要使用16位访问、低16位应写入寄存器的地址、高16位应写入寄存器的地址加2。" (另一个相关问题是以下 e2e.ti.com/.../2141528
因此、我修改了驱动程序函数 CAN_setupMessageObject、替换了这些行
//
//写出寄存器以编程报文对象。
//
HWREG_BP (base + CAN_O_IF1CMD)= cmdMaskReg;
HWREG_BP (base + CAN_O_IF1MSK)= maskReg;
HWREG_BP (base + CAN_O_IF1ARB)= arbReg;
HWREG_BP (base + CAN_O_IF1MCTL)= msgCtrl;
//
//将数据传输到消息对象 RAM
//
HWREGH (base + CAN_O_IF1CMD)= Objid & CAN_IF1CMD_MSG_NUM_M;
进行通信
//
//写出寄存器以编程报文对象。
//
HWREG_BP (base + CAN_O_IF1MSK)= maskReg;
HWREG_BP (base + CAN_O_IF1ARB)= arbReg;
HWREG_BP (base + CAN_O_IF1MCTL)= msgCtrl;
//
//将数据传输到消息对象 RAM
//
HWREG_BP (base + CAN_O_IF1CMD)= cmdMaskReg |(Objid & CAN_IF1CMD_MSG_NUM_M);
我发现这两个问题都消失了。
换言之、我已经用一个32位写入访问替换了对 IF1CMD 寄存器的两个16位写入访问、并且所有访问似乎都正常工作:邮箱32 SI 被禁用、其 RAM 区域为空白(全部为零)并且只发送 ID = 0x581的数据消息。
那么、我问:这种变通办法是否是解决问题的正确方法?
我是否应该用 C2000Ware CAN 驱动程序文件中的32位访问替换对 IF 寄存器的任何16位访问?
是否有其他方法可以解决这些问题?
谢谢、
演示
--------------------------------------------------
我的代码
//常量
#define MSG_DATA_LENGTH 8.
#define TX_MSG_OBJ_ID 1.
#define RX_MSG_OBJ_ID 2.
//主函数
void main (void)
{
/*硬件初始化*/
BootInit (true);
/* CAN B 时钟启用*/
SYSCTL_enablePeripheral (SYSCTL_Periph_CLK_CANB);
//
//初始化 GPIO 并为 CANTX/CANRX 配置 GPIO 引脚
//在模块 B 上
//
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANRXB);
GPIO_setPinConfig (DEVICE_GPIO_CFG_CANTXB);
//
//初始化 CAN 控制器 B
//
CAN_initModule (CANB_BASE);
//
//将 CAN 总线位速率设置为500kHz
//
CAN_setBitRate (CANB_BASE、SYSTEM_CLOCK、50000、16);
//
//在 CAN B 外设上接收报文时启用中断。
//
CAN_enableInterrupt (CANB_BASE、CAN_INT_IE0);
//
//初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
//
interrupt_initModule();
//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//
interrupt_initVectorTable();
//
//启用全局中断(INTM)和实时中断(DBGM)
//
EINT;
ERTM;
//
//此示例中使用的中断被重新映射到
//此文件中的 ISR 函数。
//这在 PIE 矢量表中注册中断处理程序。
//
INTERRUPT_REGTER (INT_CANB_1、&CANbISR);
//
//启用 CAN-B 中断信号
//
INTERRUPT_ENABLE (INT_CANB_1);
CAN_enableGlobalInterrupt (CANB_BASE、CAN_GLOBAL_INT_CANINT0);
//
//初始化用于接收 CAN 消息的接收消息对象。
//消息对象参数:
// CAN 模块:b.
// 消息对象 ID 号:2.
// 消息标识符:0x345
// 消息帧:标准
// 消息类型:接收
// 消息 ID 掩码:0x0
// 消息对象标志:接收中断和使用 ID 过滤器
// 消息数据长度:8字节
//
CAN_setupMessageObject (CANB_BASE、RX_MSG_OBJ_ID、0x345、
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_RX、0、
CAN_MSG_OBJ_RX_INT_ENABLE | CAN_MSG_OBJ_USE_ID_FILTER、MSG_DATA_LENGTH);
//
//初始化用于发送 CAN 消息的发送消息对象。
//消息对象参数:
// CAN 模块:A
// 消息对象 ID 号:1.
// 消息标识符:0x581
// 消息帧:标准
// 消息类型:发送
// 消息 ID 掩码:0x0
// 消息对象标志:无
// 消息数据长度:8字节
//
CAN_setupMessageObject (CANB_BASE、TX_MSG_OBJ_ID、0x581、
CAN_MSG_FRAME_STD、CAN_MSG_OBJ_TYPE_TX、0、
CAN_MSG_OBJ_NO_FLAGS、MSG_DATA_LENGTH);
//
//初始化要发送的发送消息对象数据缓冲区
//
txMsgData[0]= 0x43;
txMsgData[1]= 0x00;
txMsgData[2]= 0x10;
txMsgData[3]= 0x00;
txMsgData[4]= 0x44;
txMsgData[5]= 0x33;
txMsgData[6]= 0x22;
txMsgData[7]= 0x11;
//
//启动 CAN 模块 B 操作
//
CAN_startModule (CANB_BASE);
while (1)
{
//
//用于调试的计数器
//
CycleCounter++;
//
//在继续前延迟1秒
//
DEVICE_DELAY_US (1000000);
//
//发送消息
//
CAN_sendMessage (CANB_BASE、TX_MSG_OBJ_ID、MSG_DATA_LENGTH、txMsgData);
}
}/* 结束 main */