OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6600|回复: 5

STM32H743的FDCAN1不能正常工作

[复制链接]

1

主题

6

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2019-5-17
在线时间
1 小时
发表于 2019-5-17 21:04:15 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 梅川酷子 于 2019-5-17 21:07 编辑

在使用FD CAN的时候,出现了一系列莫名其妙的问题.希望能得到大神们的帮助,非常感谢~

1.内环模式:
发送不成功,第2次发送会进入发送FIFO满的错误。
接收不到自发送的报文。

2.外环模式:
情况跟内环模式一样,但是实际上和H750相连的USB/CAN已经成功接收到报文,示波器上也有相应的波形出现。
H750在不断地重试,而实际上我代码只发送了一次。


0.png
3.正常模式:
外部USB/CAN会接收到重复的报文,也就是说,有时一次可发送成功,有时需要两三次重试。
下图我发了三次,间隔几秒,但是,你可以从时间戳看到,序号为3和4的报文是重试的。
1.png

接收也类似,USB/CAN每次都能发送成功,并没有提示发送失败,但是H750这边只能接收到很少的报文,丢失非常严重。

环回模式完全不正常,正常模式比环回模式正常一些,但也不完全正常。

以下是一些硬件和软件信息

收发器:MCP2561FD,支持CAN FD
编译器:IAR 8.32
HAL版本:1.3(最新)
帧模式:经典模式

波特率:1Mbps

FDCAN1_Handler.Init.NominalPrescaler = 10;//tq=25ns
FDCAN1_Handler.Init.NominalSyncJumpWidth = 8;//8;
FDCAN1_Handler.Init.NominalTimeSeg1 = 23+8;
FDCAN1_Handler.Init.NominalTimeSeg2 = 8;
FDCAN1_Handler.Init.DataPrescaler = FDCAN1_Handler.Init.NominalPrescaler;
FDCAN1_Handler.Init.DataSyncJumpWidth = FDCAN1_Handler.Init.NominalSyncJumpWidth;
FDCAN1_Handler.Init.DataTimeSeg1 = FDCAN1_Handler.Init.NominalTimeSeg1;
FDCAN1_Handler.Init.DataTimeSeg2 = FDCAN1_Handler.Init.NominalTimeSeg2;


初始化代码
uint8_t FDCAN1_Setup(void)
{
    FDCAN_FilterTypeDef FDCAN1_RXFilter;

    FDCAN1_INIT_LOCK();

    //复位FDCAN1
    HAL_FDCAN_DeInit(&FDCAN1_Handler);

    FDCAN1_Handler.Instance = FDCAN1;
    FDCAN1_Handler.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
    FDCAN1_Handler.Init.Mode = FDCAN_MODE_NORMAL;
    FDCAN1_Handler.Init.AutoRetransmission = DISABLE;
    FDCAN1_Handler.Init.TransmitPause = DISABLE;
    FDCAN1_Handler.Init.ProtocolException = DISABLE;

    FDCAN1_Handler.Init.NominalPrescaler = 10;//tq=25ns
    FDCAN1_Handler.Init.NominalSyncJumpWidth = 8;//8;
    FDCAN1_Handler.Init.NominalTimeSeg1 = 23+8;
    FDCAN1_Handler.Init.NominalTimeSeg2 = 8;
    FDCAN1_Handler.Init.DataPrescaler = FDCAN1_Handler.Init.NominalPrescaler;
    FDCAN1_Handler.Init.DataSyncJumpWidth = FDCAN1_Handler.Init.NominalSyncJumpWidth;
    FDCAN1_Handler.Init.DataTimeSeg1 = FDCAN1_Handler.Init.NominalTimeSeg1;
    FDCAN1_Handler.Init.DataTimeSeg2 = FDCAN1_Handler.Init.NominalTimeSeg2;

    FDCAN_Baudrate=(float)400000000/(FDCAN1_Handler.Init.NominalPrescaler)/(FDCAN1_Handler.Init.NominalTimeSeg1+FDCAN1_Handler.Init.NominalTimeSeg2+1);

    FDCAN1_Handler.Init.MessageRAMOffset = 0;

    FDCAN1_Handler.Init.StdFiltersNbr = 1;
    FDCAN1_Handler.Init.ExtFiltersNbr = 1;
    FDCAN1_Handler.Init.RxFifo0ElmtsNbr = 1;
    FDCAN1_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;

    FDCAN1_Handler.Init.RxFifo1ElmtsNbr = 1;
    FDCAN1_Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;

    FDCAN1_Handler.Init.RxBuffersNbr = 1;

    FDCAN1_Handler.Init.TxEventsNbr = 0;
    FDCAN1_Handler.Init.TxBuffersNbr = 1;
    FDCAN1_Handler.Init.TxFifoQueueElmtsNbr = 1;
    FDCAN1_Handler.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
    FDCAN1_Handler.Init.TxElmtSize = FDCAN_DATA_BYTES_8;

    HAL_FDCAN_Init(&FDCAN1_Handler);

    //配置RX滤波器   
    FDCAN1_RXFilter.IdType=FDCAN_EXTENDED_ID;                       //标准ID
    FDCAN1_RXFilter.FilterIndex=0;                                  //滤波器索引                  
    FDCAN1_RXFilter.FilterType=FDCAN_FILTER_MASK;                   //滤波器类型
    FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXBUFFER;//FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN1_RXFilter.FilterID1=0;                               //32位ID
    FDCAN1_RXFilter.FilterID2=0;                               //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK)
    {
        return 2;
    }

    HAL_FDCAN_Start(&FDCAN1_Handler);

    HAL_FDCAN_ActivateNotification(&FDCAN1_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);

    return 0;
}


发送代码
uint8_t FDCAN1_Send_Msg(uint8_t* msg,uint32_t len)
{   
    FDCAN1_TRANSMITION_ENTER_LOCK();

    FDCAN1_TxHeader.Identifier= 0;                     //32位ID
    FDCAN1_TxHeader.IdType=FDCAN_EXTENDED_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;                           

    #if(1)
    if(HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN1_Handler,&FDCAN1_TxHeader,msg)==HAL_OK)
    {
        FDCAN1_TRANSMITION_EXIT_LOCK();
        return 0;
    }
    #else
    if(HAL_FDCAN_AddMessageToTxBuffer(&FDCAN1_Handler,&FDCAN1_TxHeader,msg,1)==HAL_OK)
    {
        HAL_FDCAN_EnableTxBufferRequest(&FDCAN1_Handler,1);
        FDCAN1_TRANSMITION_EXIT_LOCK();
        return 0;
    }
    #endif
    else
    {
        FDCAN1_TRANSMITION_EXIT_LOCK();
        return 1;
    }
}


中断
uint8_t FDCAN1_Receive_Msg(uint8_t *buf)
{   
    if(HAL_FDCAN_GetRxMessage(&FDCAN1_Handler,FDCAN_RX_FIFO0,&FDCAN1_RxHeader,buf)!=HAL_OK)return 0;//接收数据
    return FDCAN1_RxHeader.DataLength>>16;  
}

void FDCAN1_IT0_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&FDCAN1_Handler);static uint32_t CAN1_RX0_Counter=0;CAN1_RX0_Counter++;
}

void FDCAN1_IT1_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&FDCAN1_Handler);static uint32_t CAN1_RX1_Counter=0;CAN1_RX1_Counter++;
}

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
    //uint8_t i=0;
    uint8_t rxdata[8];
    if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE)!=RESET)   //FIFO1新数据中断
    {
        //提取FIFO0中接收到的数据
        HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN1_RxHeader,rxdata);
        //printf("id:%#x\r\n",FDCAN1_RxHeader.Identifier);
        //printf("len:%d\r\n",FDCAN1_RxHeader.DataLength>>16);
        //for(i=0;i<8;i++)
        //printf("rxdata[%d]:%d\r\n",i,rxdata);
        HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
    }
}


void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs)
{
    //uint8_t i=0;
    uint8_t rxdata[8];
    if((RxFifo1ITs&FDCAN_IT_RX_FIFO1_NEW_MESSAGE)!=RESET)   //FIFO1新数据中断
    {
        //提取FIFO0中接收到的数据
        HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO1,&FDCAN1_RxHeader,rxdata);
        //printf("id:%#x\r\n",FDCAN1_RxHeader.Identifier);
        //printf("len:%d\r\n",FDCAN1_RxHeader.DataLength>>16);
        //for(i=0;i<8;i++)
        //printf("rxdata[%d]:%d\r\n",i,rxdata);
        HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO1_NEW_MESSAGE,0);
    }
}



IO初始化
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_SET);

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
    HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
    HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
}




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2019-11-27
在线时间
3 小时
发表于 2020-3-19 18:23:38 | 显示全部楼层
问题解决了吗?我也碰到了类似的问题,每次FDCAN都会对外发送两帧,!
回复

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2019-5-17
在线时间
4 小时
发表于 2020-4-22 20:40:12 | 显示全部楼层
速率降下来就行 了
回复

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2019-5-17
在线时间
4 小时
发表于 2020-4-22 20:41:11 | 显示全部楼层
时钟问题,主时钟降一下就可以 了
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
32
金钱
32
注册时间
2019-9-12
在线时间
6 小时
发表于 2020-6-10 16:28:00 | 显示全部楼层
时候可以提供一个源码看一下
回复

使用道具 举报

16

主题

98

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2012-7-29
在线时间
19 小时
发表于 2020-8-26 16:57:28 | 显示全部楼层
经典模式  FDCAN1_Handler.Init.StdFiltersNbr = 1;
    FDCAN1_Handler.Init.ExtFiltersNbr = 1;
    FDCAN1_Handler.Init.RxFifo0ElmtsNbr = 1;
    FDCAN1_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;   这个不对啊 最长是8
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-30 15:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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