主题中讨论的其他器件:TM4C123GH6PM
我一直在研究我们设计的 CCA 的新版本、该版本具有该板载微控制器、由于器件可用性、取代了 TM4C123GH6PM。 我们应用中的主要区别之一是、新的微控制器只有一条 CAN 总线 CAN0、而传统器件上有2条 CAN 总线。 我目前正在使用 TivaWare v2.2.0.295 -此版本支持新的 API 调用来解锁应用中所需的特殊引脚。
无论我如何尝试实例化和启用 CAN0、我都不会从示波器上的 Tx 引脚中获得任何值。 我每250ms 传输一次 CAN 消息。 中断处理也不起作用、因此我移除了收发器、以便可以直接从微控制器探测引脚。 起初、我怀疑在为端口 F 上的 CAN0所需的一个端口解锁特殊引脚时发生了某种错误。 但是、在检查 GPIO PORTF 的 SYSCTL 寄存器后、 我的结论是所有设置都确实正确-我只需在 Tx 引脚上获得3.3V 恒定输出。
也可以在端口 B 和端口 E 上设置 CAN0、因此我进行了设置。 这些端口上的两组引脚都不是特殊引脚、因此任务明显更简单、但毫无用处。 我从相应端口上的 Tx 引脚获得相同的响应、恒定3.3V 输出。
我尝试使用 API 调用和 DRM 调用来配置 CAN0、但结果相同。 我查找了微控制器的勘误表并读取了器件和芯片版本的 DID0寄存器、但没有看到任何迹象表明我的微处理器在 CAN0或 GPIO 配置方面存在任何问题(处理器是修订版 A1)。 我切换了示波器以确认结果、并检查了晶体振荡器配置。 由于在 Cortex CPU 上站立一条 CAN 总线从未如此具有挑战性、因此我有一点损失。 下面是一些备用端口(端口 F 和 B)上的 CAN0初始化代码:
针对我的 CCA 的常见初始化:
ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_20MHZ); ROM_SysCtlPWMClockSet(SYSCTL_PWMDIV_1); gSysTickPeriod = ROM_SysCtlClockGet(); // no idea what speed this will result in yet... // setup SysTick timer for 200 Hz interrupts ROM_SysTickPeriodSet(gSysTickPeriod / MAIN_LOOP_FREQ); // disable sleep mode on all peripherals being used ROM_SysCtlPeripheralClockGating(true);
端口 F 的实现
// Must unlock and configure PF0 since it defaults to GPIO and is a special config pin (NMI) ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // use nominal API for non-special CAN pin ROM_GPIOPinConfigure(GPIO_PF3_CAN0TX); ROM_GPIOPinTypeCAN(GPIO_PORTF_BASE, GPIO_PIN_3); // direct register programming required for special pin HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; // unlock pin HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = GPIO_PIN_0; HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; // unlock pin HWREG(GPIO_PORTF_BASE + GPIO_O_AFSEL) |= GPIO_PIN_0; #if 0 // using the ROM functions doesn't seem to be working for this ROM_GPIOPinConfigure(GPIO_PF0_CAN0RX); ROM_GPIOPinConfigure(GPIO_PF3_CAN0TX); ROM_GPIOPinTypeCAN(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_3); #else HWREG(GPIO_PORTF_BASE + GPIO_O_DEN) |= GPIO_PIN_0; HWREG(GPIO_PORTF_BASE + GPIO_O_PCTL) |= 3U; // bit 3 of GPIOFPCTL is CAN0Rx #endif // lock the registers HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x00; HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
请注意、我在使用 API 调用为 CAN 配置端口 F 时遇到了一些问题、因此改用 DRM。
端口 B 配置
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); ROM_GPIOPinConfigure(GPIO_PB4_CAN0RX); ROM_GPIOPinConfigure(GPIO_PB5_CAN0TX); ROM_GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
后续 CAN 总线初始化
gCANbase = CAN0_BASE; // 0x40040000 // Reset the state of the message objects and the CAN module. CANInit(gCANbase); // Configure the controller for 1 Mbit operation. #if 1 uint32_t temp = CANBitRateSet(gCANbase, gSysTickPeriod, 1000000); #else tCANBitClkParms CANBitClk; CANBitClk.ui32SyncPropPhase1Seg = 5; CANBitClk.ui32Phase2Seg = 2; CANBitClk.ui32QuantumPrescaler = 5; CANBitClk.ui32SJW = 2; CANBitTimingSet(gCANbase, &CANBitClk); #endif // Enable interrupts for the CAN in the NVIC. IntEnable(gCANbase == CAN0_BASE ? INT_CAN0 : INT_CAN1); // Enable interrups from CAN controller. CANIntEnable(gCANbase, CAN_INT_MASTER | CAN_INT_STATUS); InitCANMessages(); // enable automatic retransmission behavior CANRetrySet(gCANbase, TRUE); // Take the CAN0 device out of INIT state. CANEnable(gCANbase);
请注意、所有这些代码在 CAN1上的传统 TM4C123GH6PM 器件上都可以正常工作。
感谢您的观看。