硬汉嵌入式论坛

 找回密码
 立即注册
查看: 605|回复: 6
收起左侧

[CAN/FDCAN] STM32H743的CAN发送引脚无信号

[复制链接]

5

主题

11

回帖

26

积分

新手上路

积分
26
发表于 2025-3-6 20:20:43 | 显示全部楼层 |阅读模式
STM32H743can配置成经典CAN,正常模式发送数据,TX引脚无信号,外部回环模式发送数据,TX引脚有信号。代码如下:


#include "bsp_debug.h"
#include "bsp_can.h"
/******************************************************************************/
#define FDCAN1_RX_PIN                       GPIO_PIN_8
#define FDCAN1_RX_GPIO_PORT                 GPIOB
#define FDCAN1_RX_AF                        GPIO_AF9_FDCAN1
#define FDCAN1_RX_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOB_CLK_ENABLE()

#define FDCAN1_TX_PIN                       GPIO_PIN_9
#define FDCAN1_TX_GPIO_PORT                 GPIOB
#define FDCAN1_TX_AF                        GPIO_AF9_FDCAN1
#define FDCAN1_TX_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOB_CLK_ENABLE()
/******************************* 全局变量声明 *********************************/
/******************************* 内部变量声明 *********************************/
static FDCAN_HandleTypeDef s_Fdcan1Handler;
static FDCAN_TxHeaderTypeDef FDCAN1_TxHeader;
static FDCAN_RxHeaderTypeDef FDCAN1_RxHeader;
static uint8_t FDCAN1_TxData[8]={1,2,3,4,5,6,7,189};
static uint8_t FDCAN1_RxData[16];
/******************************* 内部函数声明 *********************************/
static void FDCAN1_Mode_Init(void);
/******************************************************************************/
/**
  * @brief  FDCAN1底层驱动,时钟使能,HAL_FDCAN_Init()调用
  * @param  None
  * @retval None
  */
void Can1Config(void)
{
    FDCAN1_Mode_Init();
    HAL_FDCAN_Start(&s_Fdcan1Handler);
}

HAL_StatusTypeDef FdcanSend(void)
{
    HAL_StatusTypeDef res = HAL_ERROR;

    FDCAN1_TxHeader.Identifier = 0x222;             // 32位ID
    FDCAN1_TxHeader.IdType = FDCAN_STANDARD_ID;     // 标准ID
    FDCAN1_TxHeader.TxFrameType = FDCAN_DATA_FRAME; // 帧类型
    FDCAN1_TxHeader.DataLength = FDCAN_DLC_BYTES_8; // 数据长度
    FDCAN1_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    FDCAN1_TxHeader.BitRateSwitch = FDCAN_BRS_OFF;           // 关闭速率切换
    FDCAN1_TxHeader.FDFormat = FDCAN_CLASSIC_CAN;            // 传统的CAN模式
    FDCAN1_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; // 无发送事件
    FDCAN1_TxHeader.MessageMarker = 0;

    res = HAL_FDCAN_AddMessageToTxFifoQ(&s_Fdcan1Handler, &FDCAN1_TxHeader, FDCAN1_TxData);

    return res;
}

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
  if (hfdcan == &s_Fdcan1Handler)
  {
    if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    {
      /* 从 RX FIFO0 读取数据 */
      HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &FDCAN1_RxHeader, FDCAN1_RxData);

      /* 激活 Rx FIFO0 watermark notification */
      HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);

      if (FDCAN1_RxHeader.Identifier == 0x111 && FDCAN1_RxHeader.IdType == FDCAN_STANDARD_ID)
      {
        // DEBUG_PRINTF("Rx FIFO0: %d %d %d %d %d %d %d %d\r\n",
        //     FDCAN1_RxData[0],FDCAN1_RxData[1],FDCAN1_RxData[2],FDCAN1_RxData[3],
        //     FDCAN1_RxData[4],FDCAN1_RxData[5],FDCAN1_RxData[6],FDCAN1_RxData[7]);
      }
    }
  }
}

/**
  * @brief 获取FDCAN1句柄
  * @param FdcanHandler fdcan句柄的指针
  * @retval None
  */
void GetFdcan1Handler(FDCAN_HandleTypeDef **FdcanHandler)
{
    *FdcanHandler = &s_Fdcan1Handler;
}

/**
  * @brief  DCAN1底层驱动,引脚配置,时钟使能,HAL_FDCAN_Init()调用
  * @note   FDCAN1 时钟配置
  *         选择PPL2为时钟源
  *         FDCAN1时钟频率 = HSE /PLL2M * PLL2N / PLL2Q
  *         HSE = 8MHz
  *         20MHz = 8 / 1 * 20 / 8
  * @param  hfdcan:  FDCAN1句柄
  * @retval None
  */
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *hfdcan)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

    switch ((uint32_t)(hfdcan->Instance))
    {
        case (uint32_t)FDCAN1:
            /* 使能时钟 */
            __HAL_RCC_FDCAN_CLK_ENABLE();
            FDCAN1_TX_GPIO_CLK_ENABLE();
            FDCAN1_RX_GPIO_CLK_ENABLE();

            /* 选择PLL2Q作为FDCANx时钟 */
            PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;    /* 为FDCAN配置时钟 */
            PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL2; /* 选择PLL2Q作为FDCANx时钟 */
            PeriphClkInitStruct.PLL2.PLL2M = 1;
            PeriphClkInitStruct.PLL2.PLL2N = 20;
            PeriphClkInitStruct.PLL2.PLL2P = 2;
            PeriphClkInitStruct.PLL2.PLL2Q = 8;
            PeriphClkInitStruct.PLL2.PLL2R = 2;
            PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2; /* 时钟频率输入范围 */
            PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE; /* 时钟频率输出范围*/
            PeriphClkInitStruct.PLL2.PLL2FRACN = 0;                /* 指定乘法因子的小数部分 */
            if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
            {
            }

            GPIO_InitStruct.Pin = FDCAN1_TX_PIN;
            GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
            GPIO_InitStruct.Pull = GPIO_PULLUP;
            GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
            GPIO_InitStruct.Alternate = FDCAN1_TX_AF;
            HAL_GPIO_Init(FDCAN1_TX_GPIO_PORT, &GPIO_InitStruct);

            GPIO_InitStruct.Pin = FDCAN1_RX_PIN;
            GPIO_InitStruct.Alternate = FDCAN1_RX_AF;
            HAL_GPIO_Init(FDCAN1_RX_GPIO_PORT, &GPIO_InitStruct);

            HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 3, 0);
            HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 3, 0);
            HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 3, 0);
            HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
            HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
            HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
            break;

        default:
            break;
    }
}

/**
  * @brief  FDCAN配置复位,此函数会被HAL_FDCAN_DeInit调用
  * @param  hfdcan:  FDCAN句柄
  * @retval None
  */
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *hfdcan)
{
    switch ((uint32_t)(hfdcan->Instance))
    {
        case (uint32_t)FDCAN1:
            __HAL_RCC_FDCAN_FORCE_RESET();   /* 复位FDCAN1 */
            __HAL_RCC_FDCAN_RELEASE_RESET(); /* 解除复位FDCAN1 */

            HAL_GPIO_DeInit(FDCAN1_TX_GPIO_PORT, FDCAN1_TX_PIN);
            HAL_GPIO_DeInit(FDCAN1_RX_GPIO_PORT, FDCAN1_RX_PIN);

            HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
            HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn);
            HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn);
            break;

        case (uint32_t)FDCAN2:
            break;

        default:
            break;
    }
}

/**
  * @brief  FDCAN1中断0服务函数
  * @param  None
  * @retval None
  */
void FDCAN1_IT0_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}

/**
  * @brief  FDCAN1中断1服务函数
  * @param  None
  * @retval None
  */
void FDCAN1_IT1_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}

/**
  * @brief  FDCAN1校准中断服务函数
  * @param  None
  * @retval None
  */
void FDCAN_CAL_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}
/***************************** 内部功能函数 -- start **************************/
/**
  * @brief  FDCAN模式初始化配置
  * @param  None
  * @retval None
  */
static void FDCAN1_Mode_Init(void)
{
    /*                    位时间特性配置
               Bit time parameter         | Nominal      |  Data
               ---------------------------|--------------|----------------
               fdcan_ker_ck               | 20 MHz       | 20 MHz
               Time_quantum (tq)          | 50 ns        | 50 ns
               Synchronization_segment    | 1 tq         | 1 tq
               Propagation_segment        | 23 tq        | 1 tq
               Phase_segment_1            | 8 tq         | 4 tq
               Phase_segment_2            | 8 tq         | 4 tq
               Synchronization_Jump_width | 8 tq         | 4 tq
               Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
               Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
    */

    /************************ 初始化FDCAN1 ************************/
    HAL_FDCAN_DeInit(&s_Fdcan1Handler); /* 先清除以前的设置 */

    /************************ 基础配置 ************************/
    s_Fdcan1Handler.Instance = FDCAN1;                      /* 设置FDCAN1 */
    s_Fdcan1Handler.Init.FrameFormat = FDCAN_FRAME_CLASSIC; /* 经典模式 */
    s_Fdcan1Handler.Init.Mode = FDCAN_MODE_NORMAL;          /* 正常模式 */
    s_Fdcan1Handler.Init.AutoRetransmission = ENABLE;       /* 自动重传 */
    s_Fdcan1Handler.Init.TransmitPause = DISABLE;           /* 禁止暂停传输 */
    s_Fdcan1Handler.Init.ProtocolException = ENABLE;        /* 启用协议异常处理 */

    /************************ 波特率设置 ************************/
    /*
        配置仲裁阶段波特率
        CAN时钟20MHz时,仲裁阶段的波特率就是
        CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / 2 / (1+5+ 4) = 1Mbps

        其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    */
    s_Fdcan1Handler.Init.NominalPrescaler = 0x02;     /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    s_Fdcan1Handler.Init.NominalSyncJumpWidth = 0x04; /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
    s_Fdcan1Handler.Init.NominalTimeSeg1 = 0x05;      /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
    s_Fdcan1Handler.Init.NominalTimeSeg2 = 0x04;      /* 对应位时间特性图的 Phase_Seg2 */

    /************************ RAM管理器配置 ************************/
    s_Fdcan1Handler.Init.MessageRAMOffset = 0;                 /* 信息RAM偏移 */
    s_Fdcan1Handler.Init.StdFiltersNbr = 4;                    /* 标准信息ID滤波器数量 */
    s_Fdcan1Handler.Init.ExtFiltersNbr = 4;                    /* 扩展信息ID滤波器数量 */
    s_Fdcan1Handler.Init.RxFifo0ElmtsNbr = 64;                 /* 接收FIFO0元素数量 */
    s_Fdcan1Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; /* 接收FIFO0元素大小:8字节 */
    s_Fdcan1Handler.Init.RxFifo1ElmtsNbr = 16;                 /* 接收FIFO1元素数量 */
    s_Fdcan1Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; /* 接收FIFO1元素大小:8字节 */
    s_Fdcan1Handler.Init.RxBuffersNbr = 16;                    /* 接收缓冲数量*/
    s_Fdcan1Handler.Init.RxBufferSize = FDCAN_DATA_BYTES_8;    /* 接收缓冲元素大小:8字节 */

    s_Fdcan1Handler.Init.TxEventsNbr = 16;                          /* 发送事件数量 */
    s_Fdcan1Handler.Init.TxBuffersNbr = 8;                          /* 发送缓冲数量 */
    s_Fdcan1Handler.Init.TxFifoQueueElmtsNbr = 32;                  /* 发送FIFO序列元素数量 */
    s_Fdcan1Handler.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 发送FIFO序列模式 */
    s_Fdcan1Handler.Init.TxElmtSize = FDCAN_DATA_BYTES_8;           /* 发送大小:8字节 */

    if (HAL_FDCAN_Init(&s_Fdcan1Handler) != HAL_OK) /* 初始化FDCAN1*/
    {
    }
}
/**************************** 内部功能函数 -- end *****************************/




回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-7 06:49:59 | 显示全部楼层
HAL_FDCAN_DeInit(&s_Fdcan1Handler); /* 先清除以前的设置 */

前面加上 函数s_Fdcan1Handler.Instance = FDCAN1;  否则不知道Deinit那个。

别的地方看着没什么问题了。



回复

使用道具 举报

5

主题

11

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-3-7 09:52:58 | 显示全部楼层
eric2013 发表于 2025-3-7 06:49
HAL_FDCAN_DeInit(&s_Fdcan1Handler); /* 先清除以前的设置 */

前面加上 函数s_Fdcan1Handler.Instance ...

检查过了,和这个没关系,不知道还有什么问题
回复

使用道具 举报

5

主题

11

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-3-7 10:53:59 | 显示全部楼层
eric2013 发表于 2025-3-7 06:49
HAL_FDCAN_DeInit(&s_Fdcan1Handler); /* 先清除以前的设置 */

前面加上 函数s_Fdcan1Handler.Instance ...

原因好像和FDCAN_TXBRP寄存器有关,每一次发送的数据都没有发送成功都被挂起了
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-8 08:52:57 | 显示全部楼层
ANG 发表于 2025-3-7 10:53
原因好像和FDCAN_TXBRP寄存器有关,每一次发送的数据都没有发送成功都被挂起了

你测试的时候怎么测试的,是不是没有接目标设备,直接示波器测试的。
回复

使用道具 举报

5

主题

11

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-3-11 09:46:38 | 显示全部楼层
eric2013 发表于 2025-3-8 08:52
你测试的时候怎么测试的,是不是没有接目标设备,直接示波器测试的。

找到原因了,连接的端子用的是带变压器的RJ45,导致MCU的检测不到其他节点,不发生数据,但是CAN盒子可以发送数据和代码没有关系。感谢硬汉哥指导
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-3-12 08:39:58 | 显示全部楼层
ANG 发表于 2025-3-11 09:46
找到原因了,连接的端子用的是带变压器的RJ45,导致MCU的检测不到其他节点,不发生数据,但是CAN盒子可以 ...

谢谢告知最终原因。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 20:43 , Processed in 0.042366 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表