pepsi_dl 2024-04-16 10:10 采纳率: 33.3%
浏览 15
已结题

stm32的can接口不能收发数据

SYS配置

img


RCC配置

img


时钟配置

img


CAN配置

img


img


img


can.c中的HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)函数添加了开启can外设的函数

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();

    /**CAN GPIO Configuration
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

    /* CAN1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
    HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */
    /*需要添加CAN外设开启函数,否则CAN无法正常工作*/
    HAL_CAN_Start(&hcan);//开启CAN
  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

main.c中添加了过滤器配置函数和发送接收函数

/* USER CODE BEGIN 0 */

/*
* @brief:CAN过滤器配置,接收模式采用的是列表模式
* @param:can_id1(筛选第一个ID号)
* @param:can_id2(筛选第二个ID号)
*
* @retval:none
*/
void CAN_Fliter_Config_IDLIST(uint32_t can_id1,uint32_t can_id2)
{
    CAN_FilterTypeDef hcan_filterconfig;
    
    hcan_filterconfig.FilterActivation = CAN_FILTER_ENABLE;//过滤器使能
    hcan_filterconfig.FilterBank = 0;  //使用过滤器0
    hcan_filterconfig.FilterMode = CAN_FILTERMODE_IDLIST;//采用列表模式
    hcan_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;//采用32位掩码模式
    hcan_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0;//使用FIFO0
    
    hcan_filterconfig.FilterIdHigh =     (((((uint32_t)can_id1)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff0000)>>16;//过滤器ID高16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    hcan_filterconfig.FilterIdLow =      (((((uint32_t)can_id1)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0x0000ffff);    //过滤器ID低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    hcan_filterconfig.FilterMaskIdHigh = (((((uint32_t)can_id1)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff0000)>>16;//过滤器掩码高16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    hcan_filterconfig.FilterMaskIdLow =  (((((uint32_t)can_id1)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0x0000ffff);    //过滤器掩码低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    
    hcan_filterconfig.SlaveStartFilterBank = 14; //过滤器数量14
    
    HAL_CAN_ConfigFilter(&hcan,&hcan_filterconfig); //初始化过滤器
    
    HAL_CAN_Start(&hcan);//开启CAN
    
    HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//开启CAN-FIFO0中断
}

/*
* @brief:CAN过滤器配置,接收模式采用的是掩码模式
* @param:id(筛选的ID号)
* @param:mask_if(掩码)
*
* @retval:none
*/
void CAN_Fliter_Config_IDMASK(uint32_t id,uint32_t mask_id)
{
    CAN_FilterTypeDef hcan_filterconfig;
    
    hcan_filterconfig.FilterActivation = CAN_FILTER_ENABLE;//过滤器使能
    hcan_filterconfig.FilterBank = 0;  //使用过滤器0
    hcan_filterconfig.FilterMode = CAN_FILTERMODE_IDMASK;//采用列表模式
    hcan_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;//采用32位掩码模式
    hcan_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0;//使用FIFO0
    
    hcan_filterconfig.FilterIdHigh =     (((((uint32_t)id)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff0000)>>16;//过滤器ID高16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    hcan_filterconfig.FilterIdLow =      (((((uint32_t)id)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0x0000ffff);    //过滤器ID低16位,CAN_ID_EXT(扩展ID)、CAN_RTR_DATA(帧类型为数据帧)
    hcan_filterconfig.FilterMaskIdHigh = (mask_id & 0xffff0000)>>16;//过滤器掩码高16位
    hcan_filterconfig.FilterMaskIdLow =  mask_id & 0x0000ffff;      //过滤器掩码低16位
    
    hcan_filterconfig.SlaveStartFilterBank = 14; //过滤器数量14
    
    HAL_CAN_ConfigFilter(&hcan,&hcan_filterconfig); //初始化过滤器
    
    HAL_CAN_Start(&hcan);//开启CAN
    
    HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//开启CAN-FIFO0中断
}


/*
* @brief:CAN发送函数
* @param:id(CAN发送的ID号)
* @param:ide(帧ID号类型选择)
          CAN_ID_STD:标准ID号
          CAN_ID_EXT:扩展ID号
* @param:*pMsg(要发送的数据)
* @param:len(发送的数据长度)
*
* @retval:返回0:正常
           返回1:异常
*/
uint8_t CAN_SendMsg(uint32_t id,uint8_t ide,uint8_t *pMsg,uint8_t len)
{
    CAN_TxHeaderTypeDef pHeader;
    uint32_t pTxmailbox;
    uint8_t result = 0;
    
    HAL_StatusTypeDef CanStatus;
    
    if(ide == CAN_ID_STD)
    {
        pHeader.StdId = id;   //标准ID号
        pHeader.IDE = CAN_ID_STD;//标准ID
    }
    else
    {
        pHeader.ExtId = id;//扩展ID号
        pHeader.IDE = CAN_ID_STD;//扩展ID
    }
    
    pHeader.RTR = CAN_RTR_DATA;//传输数据的帧类型为数据帧
    pHeader.DLC = len>8?8:len;//发送数据的字节长度,最大为8个字节
    pHeader.TransmitGlobalTime = DISABLE;//是否要发送时间戳
    
    CanStatus = HAL_CAN_AddTxMessage(&hcan, &pHeader, pMsg, &pTxmailbox);//CAN发送函数
    
    if(CanStatus != HAL_OK)
    {
        result = 1;
    }
    
    return result;
}

/*CAN-FIFO0中断回调函数*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    CAN_RxHeaderTypeDef Header;
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);//翻转电平
    if(hcan->Instance == CAN1)
    {
        if(Header.ExtId == 0x012345678) //如果CAN接收的扩展ID为x012345678,则执行以下
        {
            printf("接收到扩展ID为:0x01234567");
        }
        
        if(Header.StdId == 0x087654321) //如果CAN接收的扩展ID为0x07654321,则执行以下
        {
            printf("接收到扩展ID为:0x07654321");
        }
    }
}

/* USER CODE END 0 */

main函数中成功发送数据后执行HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13)实现了stm32上的led闪烁,但是电脑上并未收到数据,接收器的RXD灯也未闪烁(A11连接CANH,A12连接CANL,接收器上0R和120R都试过,双方波特率都是250k)。当注释掉main函数中的电平翻转函数HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13),写到can接收中断函数中时,电脑上发送数据给stm32并未出现led灯的亮灭,但是can接收上面的TXD灯会随着电脑给stm32发送数据出现闪烁。求指点,感谢感谢

img


img


img


img


img

int main(void)
{
  /* USER CODE BEGIN 1 */
  char CAN_Send_Data[8] = {1,2,3,4,5,6,7,8};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  /* USER CODE BEGIN 2 */
  CAN_Fliter_Config_IDLIST(0x012345678,0x07654321);//CAN过滤器配置
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    if(CAN_SendMsg(0x123,CAN_ID_STD,CAN_Send_Data,8)==0)//CAN发送函数
    {
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
    }
    HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  • 写回答

24条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-16 10:10
    关注
    获得0.45元问题酬金

    引自免费微信小程序:皆我百晓生

    针对您提供的信息,您遇到的问题是STM32的CAN接口无法正常收发数据。从您提供的配置截图、代码片段以及描述来看,可能存在以下几个方面的问题:

    1. 硬件连接与物理层问题

      • 确保CAN_H (PA11) 和 CAN_L (PA12) 的线路连接正确,无短路、断路或干扰情况。
      • 检查CAN收发器电源、地线连接,确保供电稳定,且CAN_H与CAN_L之间有合适的终端电阻(通常为120Ω)。
    2. CAN模块配置问题

      • 根据您提供的STM32CubeMX配置截图,确认CAN模块已正确激活并配置了相关参数,如波特率、滤波器等。您提供的时钟配置显示SYSCLK为72MHz,CAN预分频器设置为18,时间量子为500ns,这将导致总波特率为250kHz,与您提到的通信速率一致。
    3. 中断与GPIO配置问题

      • 您在HAL_CAN_MspDeInit函数中开启了CAN和相关的中断,但这应该是初始化函数HAL_CAN_MspInit中的操作。此外,HAL_CAN_Start应该在初始化时调用,而不是在HAL_CAN_MspDeInit中。
      • 您的HAL_CAN_RxFifo0MsgPendingCallback回调函数存在逻辑错误,应先通过HAL_CAN_GetRxMessage获取接收到的CAN消息,再根据消息内容进行处理。目前您直接访问Header变量,其并未被初始化,可能导致不可预期的行为。
    4. CAN滤波器配置问题

      • 您在CAN_Fliter_Config_IDLIST函数中配置了两个ID(0x012345678和0x07654321),但它们似乎被错误地同时用于FilterIdHighFilterIdLowFilterMaskIdHighFilterMaskIdLow。应根据您的实际需求(可能是仅接受这两个特定ID的消息)重新配置过滤器。
    5. CAN消息发送与接收问题

      • 在主函数中,您发送数据后立即触发LED闪烁,这可能导致LED闪烁与实际CAN消息发送成功与否关联不准确。应在HAL_CAN_AddTxMessage成功后才触发LED闪烁。
      • 接收端的处理逻辑需要修正,如前所述,应使用HAL_CAN_GetRxMessage正确获取接收到的消息,并根据消息内容进行相应处理。

    基于以上分析,以下是修改后的代码建议:

    main.c:

    #include "main.h"
    
    CAN_HandleTypeDef hcan;
    
    // ... 其他初始化函数和宏定义 ...
    
    void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
    {
      if (canHandle->Instance == CAN1)
      {
        __HAL_RCC_CAN1_CLK_ENABLE(); // Enable CAN clock
        HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0); // Set priority for CAN RX0 interrupt
        HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); // Enable CAN RX0 interrupt
    
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        hcan.Instance = CAN1;
        hcan.Init.Prescaler = 18;
        hcan.Init.Mode = CAN_MODE_NORMAL;
        hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
        hcan.Init.TimeSeg1 = CAN_BS1_2TQ;
        hcan.Init.TimeSeg2 = CAN_BS2_5TQ;
        hcan.Init.TimeTriggeredMode = DISABLE;
        hcan.Init.AutoBusOff = DISABLE;
        hcan.Init.AutoWakeUp = DISABLE;
        hcan.Init.AutoRetransmission = ENABLE;
        hcan.Init.ReceiveFifoLocked = DISABLE;
        hcan.Init.TransmitFifoPriority = DISABLE;
        if (HAL_CAN_Init(&hcan) != HAL_OK)
        {
          Error_Handler();
        }
    
        CAN_Fliter_Config_IDLIST(0x012345678, 0x07654321);
        HAL_CAN_Start(&hcan); // Start CAN module
        HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // Enable CAN RX0 FIFO0 pending interrupt
      }
    }
    
    void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
    {
      if (canHandle->Instance == CAN1)
      {
        HAL_CAN_Stop(&hcan); // Stop CAN module
        HAL_CAN_DeactivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // Disable CAN RX0 FIFO0 pending interrupt
        HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); // Disable CAN RX0 interrupt
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12); // Deinitialize GPIO pins
        __HAL_RCC_CAN1_CLK_DISABLE(); // Disable CAN clock
      }
    }
    
    // ... 其他CAN过滤器配置函数 ...
    
    void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
    {
      CAN_RxHeaderTypeDef rx_header;
      uint8_t rx_data[8];
    
      if (hcan->Instance == CAN1)
      {
        if (HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &rx_header, rx_data) == HAL_OK)
        {
          if ((rx_header.ExtId == 0x012345678) || (rx_header.StdId == 0x07654321))
          {
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // Toggle LED on valid message reception
            // ... Process received data ...
          }
        }
      }
    }
    
    int main(void)
    {
      /* ... Other initialization code ... */
    
      char CAN_Send_Data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    
      while (1)
      {
        if (CAN_SendMsg(0x123, CAN_ID_STD, CAN_Send_Data, 8) == 0)
        {
          HAL_Delay(10); // Short delay before checking transmission status
          if (HAL_IS_BIT_SET(hcan.Instance->TSR, CAN_TSR_TME0)) // Check if Tx mailbox 0 is free (message sent successfully)
          {
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // Toggle LED on successful message transmission
          }
        }
        HAL_Delay(1000); // Delay between transmissions
      }
    }
    

    请根据上述建议调整您的代码,并再次检查硬件连接。如有需要,可以使用示波器检查CAN_H和CAN_L信号线上的波形,确保它们符合CAN协议要求。同时,确保接收端设备(如PCAN-View)的配置(波特率、ID过滤等)与STM32端匹配。这样应该能够解决STM32 CAN接口无法收发数据的问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月24日
  • 赞助了问题酬金15元 4月16日
  • 创建了问题 4月16日

悬赏问题

  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上