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文件中添加这两个宏定义。

c 复制代码
#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文件中

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文件,取消注释

c 复制代码
#define HAL_CAN_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED

7.添加can发送和接收的应用代码到工程中

user_can.h

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
 */
#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

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()函数

c 复制代码
#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.csdn.net/download/qizhi321123/92460092

相关推荐
一韦以航.2 小时前
C【指针】详解(上)
c语言·数据结构·c++·算法
wangjialelele4 小时前
git工作原理、个人使用到多人协作开发与git FLOW模型
c语言·c++·git·团队开发·个人开发
君义_noip4 小时前
信息学奥赛一本通 1640:C Looooops
c语言·数论·信息学奥赛·csp-s
iCxhust4 小时前
__acrtused 是什么
c语言·c++·单片机·嵌入式硬件·微机原理
程序员zgh4 小时前
CMake 项目构建工具介绍
c语言·开发语言·c++·编辑器
量子炒饭大师4 小时前
一天一个计算机知识——【编程百度】向上取整
c语言·数据结构·c++·git·github
烛衔溟5 小时前
C语言图论:最短路径算法
c语言·算法·图论·dijkstra·bellman-ford·最短路径
烛衔溟5 小时前
C语言图论:最小生成树算法
c语言·算法·图论·最小生成树·kruskal·prim
喵了meme5 小时前
C语言实战3
c语言·开发语言