pepsi_dl 2024-10-28 17:59 采纳率: 71.4%
浏览 12
已结题

stm32f105rbt6的CAN通讯失败

以下为main.c


#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "MyCAN.h"

uint32_t TxID = 0x555;
uint8_t TxLength = 4;
uint8_t TxData[8] = {0x11, 0x22, 0x33, 0x44};

uint32_t RxID;
uint8_t RxLength;
uint8_t RxData[8];

int main(void)
{
    OLED_Init();
    MyCAN_Init();
    
    OLED_ShowString(1, 1, "TxID:");
    OLED_ShowHexNum(1, 6, TxID, 3);
    OLED_ShowString(2, 1, "RxID:");
    OLED_ShowString(3, 1, "Leng:");
    OLED_ShowString(4, 1, "Data:");

    MyCAN_Transmit(TxID, TxLength, TxData);
    while (1)
    {    
        if (MyCAN_ReceiveFlag())
        {
            MyCAN_Receive(&RxID, &RxLength, RxData);
            
            OLED_ShowHexNum(2, 6, RxID, 3);
            OLED_ShowHexNum(3, 6, RxLength, 1);
            OLED_ShowHexNum(4, 6, RxData[0], 2);
            OLED_ShowHexNum(4, 9, RxData[1], 2);
            OLED_ShowHexNum(4, 12, RxData[2], 2);
            OLED_ShowHexNum(4, 15, RxData[3], 2);
        }
    }
}

以下为MyCAN.c

#include "stm32f10x.h"                  // Device header

void MyCAN_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    CAN_InitTypeDef CAN_InitStructure;
    CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;
    CAN_InitStructure.CAN_Prescaler = 48;        //波特率 = 36M / 48 / (1 + 2 + 3) = 125K
    CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
    CAN_InitStructure.CAN_SJW = CAN_SJW_2tq;
    CAN_InitStructure.CAN_NART = DISABLE;
    CAN_InitStructure.CAN_TXFP = DISABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_Init(CAN1, &CAN_InitStructure);
    
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
}

void MyCAN_Transmit(uint32_t ID, uint8_t Length, uint8_t *Data)
{
    CanTxMsg TxMessage;
    TxMessage.StdId = ID;
    TxMessage.ExtId = ID;
    TxMessage.IDE = CAN_Id_Standard;        //CAN_ID_STD
    TxMessage.RTR = CAN_RTR_Data;
    TxMessage.DLC = Length;
    for (uint8_t i = 0; i < Length; i ++)
    {
        TxMessage.Data[i] = Data[i];
    }
    
    uint8_t TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);
    
    uint32_t Timeout = 0;
    while (CAN_TransmitStatus(CAN1, TransmitMailbox) != CAN_TxStatus_Ok)
    {
        Timeout ++;
        if (Timeout > 100000)
        {
            break;
        }
    }
}

uint8_t MyCAN_ReceiveFlag(void)
{
    if (CAN_MessagePending(CAN1, CAN_FIFO0) > 0)
    {
        return 1;
    }
    return 0;
}

void MyCAN_Receive(uint32_t *ID, uint8_t *Length, uint8_t *Data)
{
    CanRxMsg RxMessage;
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
    
    if (RxMessage.IDE == CAN_Id_Standard)
    {
        *ID = RxMessage.StdId;
    }
    else
    {
        *ID = RxMessage.ExtId;
    }
    
    if (RxMessage.RTR == CAN_RTR_Data)
    {
        *Length = RxMessage.DLC;
        for (uint8_t i = 0; i < *Length; i ++)
        {
            Data[i] = RxMessage.Data[i];
        }
    }
    else
    {
        //...
    }
}

当CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;时,按下按键OLED有显示数据,可以实现自发自收,但是改为CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;时,接收设备接收不到stm32f105rbt6发出来的数据,stm32f105rbt6也接收不到接收设备发出来的数据

  • 写回答

1条回答 默认 最新

  • 无疆76 2024-10-28 18:00
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    当你在使用CAN通讯时,出现自发自收可以工作但在正常模式下无法与其他设备通讯的问题,这通常是由于以下几个原因造成的:

    1. 硬件配置和连接问题:确保CAN高和CAN低正确地连接到了CAN网络的两侧。如果你在CAN通讯过程中使用了转换器或隔离器,确保它们正确配置并正常工作。此外,检查CAN总线的终端电阻是否已正确设置(通常是120欧姆)。
    2. 波特率设置:虽然你在代码中设置了波特率为125K,但确保发送和接收设备都使用相同的波特率设置。不同设备的默认设置可能不同,因此请检查并确保它们匹配。
    3. 配置和初始化检查:确保所有相关的CAN初始化设置都正确无误。这包括模式设置(LoopBack或Normal)、过滤器设置等。另外,请仔细检查是否所有的引脚连接都是正确的,包括时钟设置和使能的相关外设。
    4. 发送和接收代码检查:检查发送和接收的代码逻辑是否正确。确保发送的数据格式(标准ID或扩展ID)与接收设备的期望匹配。同时,确保接收设备的接收标志位和接收处理函数正确无误。
    5. 中断服务程序(ISR)配置:如果你使用了中断来处理CAN消息,确保相关的中断服务程序已正确配置并启用。中断的优先级也可能影响到消息的接收和发送。
    6. 错误处理和指示:查看CAN的错误标志位,以确定是否发生了错误(如超载、被动错误等)。如果发生了错误,你需要进行相应的处理。
    7. 工具和网络诊断:使用示波器或CAN分析仪来查看CAN总线上的实际数据。这可以帮助你确认是否真的是发送设备没有发送数据,或者接收设备没有正确地接收到数据。此外,检查网络中的其他设备是否有可能干扰通讯。
    8. 固件和库版本:确保你使用的STM32 HAL库或其他相关固件是最新的版本,因为某些早期版本可能存在已知的缺陷或不兼容性问题。

    为了进一步调试这个问题,你可以尝试以下步骤:

    • 使用CAN分析器捕获总线上的数据,以确认数据是否被发送出去。
    • 检查并确认所有的硬件连接都是正确的。
    • 重新检查并调试你的代码逻辑,确保发送和接收逻辑无误。
    • 检查固件版本并考虑更新到最新版本。

    如果问题仍然存在,你可能需要联系硬件供应商或参考他们的技术支持资源来解决这个问题。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月6日
  • 创建了问题 10月28日