用CAN总线对STM32微控制器编程的问题

Posted

技术标签:

【中文标题】用CAN总线对STM32微控制器编程的问题【英文标题】:Problem related to programing STM32 microcontroller with CAN bus 【发布时间】:2019-11-12 21:25:20 【问题描述】:

我是 STM32 微控制器和 CAN 总线通信协议的新手,我正在编写一个 STM32F103xx 微控制器。 我想使用 CAN 总线将数据传输到同系列的另一个微控制器。

我设置了所有必要的设置,但是在调试代码时,它卡在传输挂起函数中并且不传输。 我希望传输数据,但不是。

我认为我的硬件没有问题。

PS: 我已经尝试过 CAN 处理程序的正常模式和 LOOPBACK 模式,但它们都不起作用。

int main(void)

    HAL_Init();

    SystemClock_Config();

    uint32_t BUTTON_0;
    uint32_t BUTTON_1;

    uint8_t Data_0[5] = "aaaaa";
    uint8_t Data_1[5] = "ZZZZZ";

    MX_GPIO_Init();
    MX_CAN_Init();

    if(HAL_CAN_Init(&hcan) != HAL_OK)
        Error_Handler();
    

    if(HAL_CAN_Start(&hcan) != HAL_OK)
        Error_Handler();
    

    while (1)
           
        TxHeader.DLC   = 5;
        TxHeader.StdId = 0x65D;
        TxHeader.IDE   = CAN_ID_STD;
        TxHeader.RTR   = CAN_RTR_DATA;

        BUTTON_0 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

        BUTTON_1 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);

        if (BUTTON_0 == 0U)

            if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_0, &TxMailbox) != HAL_OK )
                Error_Handler();
            

        

        if (BUTTON_1 == 0U)

            if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_1, &TxMailbox) != HAL_OK)
                Error_Handler();
            

        

        while (HAL_CAN_IsTxMessagePending(&hcan, TxMailbox));

        if (BUTTON_0 && BUTTON_1 == 0U)
            printf("Please Press a Button");
        
    

【问题讨论】:

【参考方案1】:

您正在使用 STM32CubeF1 HAL 库(可能通过 STM32CubeMX)。 请检查对应的 User Manual - 第 9.2.1 节推荐以下程序:

    通过实现HAL_CAN_MspInit() 初始化 CAN 低级资源: 使用__HAL_RCC_CANx_CLK_ENABLE()启用CAN接口时钟 配置 CAN 引脚 为 CAN GPIO 启用时钟 将 CAN 引脚配置为备用功能开漏 如果使用中断 [...] 使用HAL_CAN_Init() 函数初始化CAN 外设。 该函数借助HAL_CAN_MspInit() 进行低级初始化。 使用以下配置函数配置接收过滤器: HAL_CAN_ConfigFilter() 使用HAL_CAN_Start()函数启动CAN模块。 在此级别,节点在总线上处于活动状态: 它接收消息,并且可以发送消息。 要管理消息传输,可以使用以下 Tx 控制功能: HAL_CAN_AddTxMessage() 请求传输新消息。 [...] HAL_CAN_IsTxMessagePending() 检查 Tx 邮箱中是否有消息待处理。 [...] 当 CAN Rx FIFO 接收到消息时, 可以使用HAL_CAN_GetRxMessage() 函数检索它。 函数 HAL_CAN_GetRxFifoFillLevel() 允许知道有多少 Rx 消息 存储在 Rx FIFO 中。 调用HAL_CAN_Stop() 函数会停止CAN 模块。 通过HAL_CAN_DeInit()函数实现去初始化。

[...]

轮询模式操作/传输:

监控 Tx 邮箱的可用性,直到至少有一个 Tx 邮箱空闲, 使用HAL_CAN_GetTxMailboxesFreeLevel()。 然后使用HAL_CAN_AddTxMessage() 请求传输消息。

您的代码示例未显示从 main() 调用的子函数,因此您必须自己检查 :-)

CAN/GPIO 时钟在分配相应的寄存器之前已启用。 GPIO 引脚按照建议配置。

另一个想法 - 是不是你必须在启动 CAN 之后检查HAL_CAN_GetTxMailboxesFreeLevel(),甚至在添加第一条消息进行传输之前?

步骤 (2.)、(4.)、(5.) 已由您的代码处理,并且 步骤 (3.)、(6.)、(7.)、(8.) 与您的问题无关(但仅与接收 / deinit 相关)。


如果您不想自己完成所有手动工作,也可以使用以下工具之一作为起点。 这两种工具都远非完美(我们的一些 *** 同行根本不同意推荐它们),但它们通常已经提供了包含您需要的大部分相关步骤的基本结构:

固件示例集合(参见他们的 Application Note 详情)。

代码生成器 STM32CubeMX

【讨论】:

以上是关于用CAN总线对STM32微控制器编程的问题的主要内容,如果未能解决你的问题,请参考以下文章

将 VL53L0X 与 STM32 微控制器一起使用

如何在 STM32 微控制器上的两个程序之间共享单段闪存

如何使用 JTAG 链接调试两个或多个微控制器?

如何为 STM32F4 微控制器的 flash bank 实现 OTA 更新故障转移场景?

我应该从哪里获得 STM32 微控制器的头文件?

STM32F103C8T6微控制器 功能怎么样? 这个型号芯片解密成功率高吗?