我有一块 STM32F091RCT 板,我正试图强迫它充当临时 CAN 节点。为了有个起点,我查阅了一些代码示例。我从这个开始,但它引用了一些类型定义(例如CanTxMsgTypeDef
)和函数(HAL_CAN_Transmit
例如),它们似乎不存在于stm32f0xx_hal_can.h
标题中。因此,我选择了一个用于 F103 的示例,最后得到了这段代码(自动生成的注释和与 CAN 无关的东西被删除):
CAN_HandleTypeDef hcan;
// other peripheral configuration, etc.
static void MX_CAN_Init(void)
{
hcan.Instance = CAN;
hcan.Init.Prescaler = 16;
hcan.Init.Mode = CAN_MODE_LOOPBACK; // also tried normal mode, same deal
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_1TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
CAN_FilterTypeDef sf;
sf.FilterMaskIdHigh = 0x0000;
sf.FilterMaskIdLow = 0x0000;
sf.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sf.FilterBank = 0;
sf.FilterMode = CAN_FILTERMODE_IDMASK;
sf.FilterScale = CAN_FILTERSCALE_32BIT;
sf.FilterActivation = CAN_FILTER_ENABLE;
if (HAL_CAN_ConfigFilter(&hcan, &sf) != HAL_OK) {
Error_Handler();
}
if (HAL_CAN_ConfigFilter(&hcan, &sf) != HAL_OK)
Error_Handler();
// this didn't want to work
// if (HAL_CAN_RegisterCallback(&hcan, HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID, can_irq)) {
// Error_Handler();
// }
if (HAL_CAN_Start(&hcan) != HAL_OK) {
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
Error_Handler();
}
}
void can_irq(CAN_HandleTypeDef *pcan) {
CAN_RxHeaderTypeDef msg;
uint8_t data[8];
HAL_CAN_GetRxMessage(pcan, CAN_RX_FIFO0, &msg, data);
// do something
}
// ...
int main(void)
{
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
MX_TIM1_Init();
MX_CAN_Init();
while (1)
{
uint32_t mb;
CAN_TxHeaderTypeDef msg;
uint8_t data[] = "Hello!";
msg.StdId = 127;
msg.IDE = CAN_ID_STD;
msg.RTR = CAN_RTR_DATA;
msg.DLC = 6;
msg.TransmitGlobalTime = DISABLE;
if (HAL_CAN_AddTxMessage(&hcan, &msg, data, &mb) != HAL_OK) {
Error_Handler();
}
}
}
void send_CAN_test_message(void)
{
uint32_t mb;
CAN_TxHeaderTypeDef msg;
uint8_t data[] = "Hello!";
msg.StdId = 127;
msg.IDE = CAN_ID_STD;
msg.RTR = CAN_RTR_DATA;
msg.DLC = 6;
msg.TransmitGlobalTime = DISABLE;
if (HAL_CAN_AddTxMessage(&hcan, &msg, data, &mb) != HAL_OK) {
Error_Handler();
}
}
所以我希望这会在主循环的每次迭代中通过 CAN 总线传输一条消息。MX_CAN_Init()
不幸的是,情况似乎并非如此,因为连接到 CAN_TX 引脚的示波器(也尝试使用 RX 进行良好测量)仅显示执行时电压从 0 V 上升到 3.3 V。为了澄清起见,我在收发器 (MCP2551)之前直接测量来自 MCU 的信号。
我怀疑我在这里遗漏了一些非常明显的东西......有人会碰巧知道那个非常明显的东西是什么吗?也许是控制器引脚上的伪冲突(TX 和 RX 之间的差异),而控制器只是无限期地等待它?