RT Thread Studio创建CAN工程代码

主控芯片:STM32F429IGT6
开发环境:RT Thread Stdio

一.配置串口

1.RT Thread Studio创建STM32F429IGT6的工程
在这里插入图片描述
2.由于开发板上使用的是25Mhz的晶振,修改外部晶振为25Mhz,点击CubeMX_Settings设置
在这里插入图片描述
在这里插入图片描述
配置外部晶振
在这里插入图片描述
在这里插入图片描述
按照图示选择即可
在这里插入图片描述
在这里插入图片描述
点击GENERATE CODE生成代码
在这里插入图片描述
点击Close
在这里插入图片描述
3.查看drv_clk.c文件中的clk_init()函数可查看系统时钟已经配置成功。
在这里插入图片描述
4.烧录到电路板中,查看打印信息。
在这里插入图片描述

二.配置CAN驱动

1.由于新生成的工程文件中没有drv_can.c文件,所以手动将drv_can.c文件加载到工程中,
在这里插入图片描述
在这里插入图片描述
2.使能CAN设备驱动程序,点击RT -Thread Settings选项,勾选使能CAN设备驱动程序,使能CAN硬件过滤器。
在这里插入图片描述
3.在board.h文件中添加这两个宏定义。

#define BSP_USING_CAN
#define BSP_USING_CAN1

在这里插入图片描述
4.点击CubeMx_Settings选项配置CAN驱动
在这里插入图片描述
5.由于生成的CAN驱动文件已被默认排除构建,所以需要打开导航器查看排除构建的文件。
在这里插入图片描述
在这里插入图片描述
复制can.c文件中的void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)和void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)代码段到stm32f4xx_hal_msp.c文件中

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**CAN1 GPIO Configuration
    PB8     ------> CAN1_RX
    PB9     ------> CAN1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();

    /**CAN1 GPIO Configuration
    PB8     ------> CAN1_RX
    PB9     ------> CAN1_TX
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);

  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

6.打开cubemx文件夹下的Inc文件夹中的stm32f4xx_hal_conf.h文件,取消注释

#define HAL_CAN_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED

在这里插入图片描述
7.添加can发送和接收的应用代码到工程中
user_can.h

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-11-26     LENOVO       the first version
 */
#ifndef APPLICATIONS_USER_CAN_H_
#define APPLICATIONS_USER_CAN_H_

#include <board.h>
#include <rtdevice.h>

int can_init(void);
rt_err_t can_rx_call(rt_device_t dev,rt_size_t size);
void can_tx_entry(void *parameter);
void can_rx_entry(void *parameter);
void can_sample(int argc,char **argv);
void can_txd_msg(void);
#endif /* APPLICATIONS_USER_CAN_H_ */

user_can.c

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-11-26     LENOVO       the first version
 */
#include "user_can.h"
#define DBG_TAG "ads_can"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define     CAN_name    "can1"

static rt_device_t can_dev;
static rt_sem_t can_sem;

int can_init(void)
{
    can_dev = rt_device_find(CAN_name);
    if(can_dev == RT_NULL){
        LOG_D("failed to fine %s device\n",CAN_name);
        return -1;
    }

    rt_err_t can_dev_flag;
    can_dev_flag = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
    RT_ASSERT(can_dev_flag == RT_EOK);

#ifdef RT_CAN_USING_HDR
    rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD,(void *)CAN500kBaud);//波特率设置为500K
    struct rt_can_filter_item items[1] =
    {
        RT_CAN_FILTER_ITEM_INIT(0x00f8,0,0,0,0x0030,RT_NULL,RT_NULL),
    };
    struct rt_can_filter_config cfg = {1,1,items};
    rt_err_t res;
//    res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
//    RT_ASSERT(res == RT_EOK);
#endif
    rt_device_control(can_dev, RT_CAN_CMD_SET_MODE,(void *)RT_CAN_MODE_NORMAL);

    can_sem = rt_sem_create("can_sem", 0, RT_IPC_FLAG_FIFO);
    if(can_sem == RT_NULL){
        LOG_D("failed to create can sem\n");
        return -1;
    }

    rt_thread_t can_tx_thread;
    can_tx_thread = rt_thread_create("can_tx", can_tx_entry, RT_NULL, 2048, 1, 1);
    if(can_tx_thread != RT_NULL){
        rt_thread_startup(can_tx_thread);
    }
    rt_thread_t can_rx_thread;
    can_rx_thread = rt_thread_create("can_rx", can_rx_entry, RT_NULL, 2048, 1, 1);
    if(can_rx_thread != RT_NULL){
        rt_thread_startup(can_rx_thread);
    }

    rt_device_set_rx_indicate(can_dev,can_rx_call);
    return 0;
}
rt_err_t can_rx_call(rt_device_t dev,rt_size_t size)
{
    rt_sem_release(can_sem);
    return 0;
}

void can_tx_entry(void *parameter)
{
    while(1)
    {
        can_txd_msg();
        rt_thread_mdelay(1000);
    }
}

void can_rx_entry(void *parameter)
{
    struct rt_can_msg rxmsg = {0};

    while(1)
    {
        rxmsg.hdr = -1;
        rt_sem_take(can_sem, RT_WAITING_FOREVER);
        rt_thread_mdelay(10);
        rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
        rt_kprintf("ID:%x\n",rxmsg.id);
        for (int var = 0; var < 8; ++var) {
            rt_kprintf("%x ",rxmsg.data[var]);
        }
        rt_kprintf("\n");
    }
}
void can_sample(int argc,char **argv)
{
    struct rt_can_msg txmsg = {0};
    txmsg.id = strtol(argv[1], 0, 16);
    txmsg.ide = 0;
    txmsg.rtr = 0;
    txmsg.len = 8;
    txmsg.data[0] = 0x01;
    txmsg.data[1] = 0x02;
    txmsg.data[2] = 0x04;
    txmsg.data[3] = 0x08;
    int size;
    size = rt_device_write(can_dev, 0, &txmsg, sizeof(txmsg));
    if(size == sizeof(txmsg)){
        rt_kprintf("can dev write data success\n");
    }
    else
    {
        rt_kprintf("can dev write data error\n");
    }
}
MSH_CMD_EXPORT(can_sample,can device sample);

void can_txd_msg(void)
{
    struct rt_can_msg txmsg = {0};
    static uint8_t b_cnt=0;

    txmsg.id = 0x823;
    txmsg.ide = 1;
    txmsg.rtr = 0;
    txmsg.len = 8;
    txmsg.data[0] = b_cnt++;
    txmsg.data[1] = 0x02;
    txmsg.data[2] = 0x04;
    txmsg.data[3] = 0x08;
    int size;
    size = rt_device_write(can_dev, 0, &txmsg, sizeof(txmsg));
    if(size == sizeof(txmsg)){
        rt_kprintf("can dev write data success\n");
    }
    else
    {
        rt_kprintf("can dev write data error\n");
    }
}

8.在main.c中添加can_init()函数

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "user_can.h"

int main(void)
{
    int count = 1;
    can_init();
    while (count++)
    {
        LOG_D("Hello RT-Thread!");
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

9.查看原理图,电路板中已接120欧姆的电阻,所以CAN分析仪应该关闭掉120欧姆的电阻。
在这里插入图片描述
在这里插入图片描述

10.烧录到电路板中,可查看can数据收发数据正常
在这里插入图片描述
在这里插入图片描述
工程代码:https://download.youkuaiyun.com/download/qizhi321123/92460092

### 如何在 RT-Thread Studio 创建 CanFestival CANopen 工程 #### 准备环境 确保安装并配置好RT-Thread Studio集成开发环境。此IDE提供了图形化界面来管理项目依赖项和配置文件。 #### 配置硬件支持 对于CAN通信的支持,在`drv_can.c`中可能存在拼写错误,需修正如下: - `RT_CAN_MODE_LISEN` 修改为 `RT_CAN_MODE_LISTEN` - `RT_CAN_MODE_LOOPBACKANLISEN` 修改为 `RT_CAN_MODE_LOOPBACKANLISTEN`[^1] #### 添加CanFestival库 通过RT-Thread包管理系统添加CanFestival库到当前工程CanFestival是一个实现CANopen协议栈的开源软件包,适用于多种操作系统平台。 ```bash pkg install canfestival ``` #### 初始化项目结构 创建一个新的C/C++项目,并选择适合的目标板卡型号。设置项目的编译选项以适应所选MCU架构特性。 #### 编写应用逻辑 编写应用程序代码初始化CAN接口以及调用CanFestival API完成节点配置与数据交换处理流程: ```c #include "canfestival.h" int main(void) { // Initialize hardware and CAN interface here // Initialize the CANOpen stack with specific node ID. CO_Data data; init_CO_data(&data, NODE_ID); while (1) { process_CAN_message(&data); // Process incoming messages from bus send_heartbeat(&data); // Send heartbeat message periodically osDelay(10); } } ``` #### 测试验证 构建整个工程项目并下载固件至目标设备运行测试。注意观察串口打印日志确认各功能模块正常运作情况。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值