主控芯片: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
737

被折叠的 条评论
为什么被折叠?



