CH32V307 CAN1收发数据问题

我使用EVT中的CAN/testdemo文件夹中的回环模式进行测试,能测试通过。我自己写的程序中只能发送数据,不能接收数据,是我的程序中对CAN的初始化哪里不正确还是我的接收程序不对,以及是否还有其它什么原因?使用CAN分析仪查看正确接收到来自单片机的数据,向单片机发送的数据也是成功了的image.png

以下是我的初始化代码

/*

*********************************************************************************************************

*   模块名称 : can驱动模块

*   文件名称 : bsp_can.c

*   说    明 : 驱动can接口

*   修改记录 :

*********************************************************************************************************

*/

#include "../bsp.h"



/*

*********************************************************************************************************

*                                           宏定义

*********************************************************************************************************

*/

/* CAN1时钟 */

#define CAN1_CLK         RCC_APB1Periph_CAN1

#define CAN1_MODE        CAN_Mode_Normal         /* 工作模式 */

/* CAN1_TX的引脚 */

#define CAN1_TX_RCC     RCC_APB2Periph_GPIOD

#define CAN1_TX_PIN     GPIO_Pin_1

#define CAN1_TX_PORT    GPIOD

/* CAN1_RX的引脚 */

#define CAN1_RX_RCC     RCC_APB2Periph_GPIOD

#define CAN1_RX_PIN     GPIO_Pin_0

#define CAN1_RX_PORT    GPIOD

/* CAN1 STB的引脚 */

#define CAN1_STB_RCC     RCC_APB2Periph_GPIOD

#define CAN1_STB_PIN     GPIO_Pin_11

#define CAN1_STB_PORT    GPIOD


/* 接收中断配置 */

#define CAN1_RX_IRQ_HANDLE  CAN1_RX1_IRQHandler

#define CAN1_RX_IRQ         CAN1_RX1_IRQn

#define CAN1_RX_IRQ_PRIO   10


/* CAN1 绑定FIFO的编号 */

#define CAN1_FIFIO_NUM      CAN_Filter_FIFO0


/*

*********************************************************************************************************

*                                           函数声明

*********************************************************************************************************

*/

int bsp_can_set_status(CAN_PORT_ENUM can, CAN_STATUS_ENUM status);



/*

*********************************************************************************************************

*                                           变量

*********************************************************************************************************

*/


/* can消息 */

CanRxMsg can_rx_msg[CAN_PORT_NUM];


const CAN_PIN_MNT can_pin_mnt[CAN_PORT_NUM] = {

    /* CAN0 */

    {

        {CAN1_RX_RCC, CAN1_RX_PIN, CAN1_RX_PORT},           /* rx */

        {CAN1_TX_RCC, CAN1_TX_PIN, CAN1_TX_PORT},           /* tx */

        {CAN1_STB_RCC, CAN1_STB_PIN, CAN1_STB_PORT}        /* stb */

    }

};


CAN_CFG_MNT_T can_cfg_mnt[CAN_PORT_NUM] = {

    /* CAN1 */

        {

            CAN1,                   /* 端口 */

            CAN1_CLK,               /* 时钟 */

            CAN_BAUDRATE_500K,      /* 波特率 */

            CAN1_RX_IRQ,          /* 中断号 */

            CAN1_RX_IRQ_PRIO,       /* 中断优先级 */

            0,                      /* 接收中断回调 */

            CAN_WORK_STATUS,        /* 工作状态 */

            CAN1_MODE,              /* 工作模式 */

            0,                      /* 标准ID */

        }

};



/*

*********************************************************************************************************

*   函 数 名: bsp_can_init_port

*   功能说明: 配置can指示灯相关的GPIO

*   形    参:  无

*   返 回 值: 无

*********************************************************************************************************

*/

int bsp_can_init_port(const CAN_PIN_MNT *can)

{

    GPIO_InitTypeDef GPIO_InitSturcture={0};


    /* 时钟初始化 */

    RCC_APB2PeriphClockCmd(can->rx.clk | RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB2PeriphClockCmd(can->tx.clk | RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB2PeriphClockCmd(can->stb.clk, ENABLE);


    /* 将CAN1重映射到 PD0和PD1引脚上 */

    GPIO_PinRemapConfig(GPIO_Remap2_CAN1, ENABLE);


    /* 初始化 tx pin */

    GPIO_InitSturcture.GPIO_Pin = can->tx.pin;

    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(can->tx.port, &GPIO_InitSturcture);


    /* 初始化 rx pin */

    GPIO_InitSturcture.GPIO_Pin = can->rx.pin;

    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;

    GPIO_Init(can->rx.port, &GPIO_InitSturcture);


    /* 初始化 STB pin */

    GPIO_InitSturcture.GPIO_Pin = can->stb.pin;

    GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init(can->stb.port, &GPIO_InitSturcture);


    return 0;

}


/*

*********************************************************************************************************

*   函 数 名: bsp_can_init_cfg

*   功能说明: 配置CAN总线相关参数

*   形    参:  can can配置结构体

*   返 回 值: 0 成功

*********************************************************************************************************

*/

int bsp_can_init_cfg(CAN_CFG_MNT_T *can, CAN_PORT_ENUM port)

{

    int result = 0;


    CAN_InitTypeDef CAN_InitSturcture = {0};

    CAN_FilterInitTypeDef CAN_FilterInitSturcture = {0};

    NVIC_InitTypeDef  NVIC_InitStructure = {0};


    /* 初始化CAN时钟 */

    RCC_APB1PeriphClockCmd(can->can_clk, ENABLE);


    /* initialize CAN parameters */

    CAN_InitSturcture.CAN_TTCM = DISABLE;               /* 禁止时间触发模式(不生成时间戳), T  */

    CAN_InitSturcture.CAN_ABOM = DISABLE;               /* 禁止自动总线关闭管理 */

    CAN_InitSturcture.CAN_AWUM = DISABLE;               /* 禁止自动唤醒模式 */

    CAN_InitSturcture.CAN_NART = ENABLE;                /* 使能仲裁丢失或出错后的自动重传功能 */

    CAN_InitSturcture.CAN_RFLM = DISABLE;               /* 禁止接收FIFO */

    CAN_InitSturcture.CAN_TXFP = DISABLE;               /* 禁止传输FIFO优先级 */

    CAN_InitSturcture.CAN_Mode = can->mode;       /* 设置CAN为正常工作模式 */


    /*

        CAN 波特率 = apb1 / Prescaler / (SJW + BS1 + BS2);

        SJW = synchronisation_jump_width

        BS = bit_segment

        本例中,设置CAN波特率为1000Kbps

        CAN 波特率 = 72000000 / 6 / (1 + 5 + 6) / = 1000kHz

    */

    CAN_InitSturcture.CAN_SJW = CAN_SJW_1tq;

    CAN_InitSturcture.CAN_BS1 = CAN_BS1_6tq;

    CAN_InitSturcture.CAN_BS2 = CAN_BS2_5tq;

    switch(can->baudrate){

    case CAN_BAUDRATE_1M:

        CAN_InitSturcture.CAN_Prescaler = 6;

    break;


    case CAN_BAUDRATE_500K:

        CAN_InitSturcture.CAN_Prescaler = 12;

    break;


    case CAN_BAUDRATE_250K:

        CAN_InitSturcture.CAN_Prescaler = 24;

    break;


    case CAN_BAUDRATE_125K:

        CAN_InitSturcture.CAN_Prescaler = 48;

    break;


    case CAN_BAUDRATE_100K:

        CAN_InitSturcture.CAN_Prescaler = 60;

    break;


    case CAN_BAUDRATE_50K:

        CAN_InitSturcture.CAN_Prescaler = 120;

    break;


    default:

        /* 默认500k */

        CAN_InitSturcture.CAN_Prescaler = 12;

        result = -1;

    break;

    }

    /* initialize CAN */

    if(CAN_Init(CAN1, &CAN_InitSturcture) == ERROR) {

        result = -1;

    }


    /* initialize filter */

    CAN_FilterInitSturcture.CAN_FilterNumber = 0;                      /* 滤波器序号,0-13,共14个滤波器 */

    CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList;    /* 滤波器模式,设置ID掩码模式 */

    CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;   /* 32位滤波 */

    CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x0000;                 /* 掩码后ID的高16bit */

    CAN_FilterInitSturcture.CAN_FilterIdLow = 0x0000;                  /* 掩码后ID的低16bit */

    CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x0000;             /* ID掩码值高16bit */

    CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x0006;              /* ID掩码值低16bit */

    CAN_FilterInitSturcture.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;      /* 滤波器绑定FIFO 0 */

    CAN_FilterInitSturcture.CAN_FilterScale = ENABLE;                  /* 使能滤波器 */

    CAN_FilterInit(&CAN_FilterInitSturcture);



    /* 配置工作模式 */

    bsp_can_set_status(port, can->status);


    return result;

}



/*

*********************************************************************************************************

*   函 数 名: bsp_init_can

*   功能说明: 配置can

*   形    参:  无

*   返 回 值: 无

*********************************************************************************************************

*/

int bsp_init_can(

    CAN_PORT_ENUM can,

    int (*rx_msg_irq_callback)(CanRxMsg *msg))

{

    int result = -1;


    if(can < CAN_PORT_NUM) {

        /* IO初始化 */

        bsp_can_init_port(&can_pin_mnt[can]);

        /* CAN初始化 */

        bsp_can_init_cfg(&can_cfg_mnt[can], can);

        /* 设置回到函数 */

        can_cfg_mnt[can].rx_irq_callback = rx_msg_irq_callback;

        result = 0;

    }


    return result;

}


/*

*********************************************************************************************************

*   函 数 名: bsp_can_set_status

*   功能说明: 设置CAN状态

*   形    参: port 端口

*               status 状态

*   返 回 值: 0 成功

*********************************************************************************************************

*/

int bsp_can_set_status(CAN_PORT_ENUM can, CAN_STATUS_ENUM status)

{

    int result = -1;


    if(can < CAN_PORT_NUM) {

        if(status == CAN_STANDBY_STATUS) {

            can_pin_mnt[can].stb.port->BSHR = can_pin_mnt[can].stb.pin;

        } else {

            can_pin_mnt[can].stb.port->BCR = can_pin_mnt[can].stb.pin;

        }


        result = 0;

    }


    return result;

}


/*

*********************************************************************************************************

*   函 数 名: bsp_can_tx_msg

*   功能说明: 发送数据

*   形    参:   msg  发送数据缓冲区

*               port CAN端口值

*   返 回 值:   0 发送成功

*              -1 发送失败

*********************************************************************************************************

*/

int bsp_can_tx_msg(CAN_PORT_ENUM port, CanTxMsg *msg)

{

    uint8_t mbox;

    uint16_t i = 0;

    int result = -1;


    if(port < CAN_PORT_NUM) {

        mbox = CAN_Transmit(can_cfg_mnt[port].com, msg);

        i = 0;


        while((CAN_TransmitStatus(can_cfg_mnt[port].com, mbox) != CAN_TxStatus_Ok) && (i < 0xFFF)){

            i++;

        }


        if( i != 0xFFF ){

            result = 0;

        }

    }


    return result;

}


/*

*********************************************************************************************************

*   函 数 名: bsp_can_receive_msg

*   功能说明: 接收数据

*   形    参:   buf  接收区数据缓冲区

*               port CAN端口值

*   返 回 值:   接收数据长度

*********************************************************************************************************

*/

uint8_t bsp_can_receive_msg( uint8_t *buf, CAN_PORT_ENUM port)

{

    uint8_t result = 0;

    CanRxMsg CanRxStructure;


    if( CAN_MessagePending(can_cfg_mnt[port].com, CAN_FIFO0) != 0){


        CAN_Receive(can_cfg_mnt[port].com, CAN_FIFO0, &CanRxStructure );


        memcpy(buf, CanRxStructure.Data, CanRxStructure.DLC);

        result = CanRxStructure.DLC;

    }

    return result;

}


/*

*********************************************************************************************************

*   函 数 名: bsp_can_get_cfg_info

*   功能说明: 获取can配置结构体

*   形    参: can 端口

*   返 回 值: 0 成功

*********************************************************************************************************

*/

CAN_CFG_MNT_T *bsp_can_get_cfg_info(CAN_PORT_ENUM port)

{

    return &can_cfg_mnt[port];

}




/*******************************************************************************************************/


您好,若程序中有用到中断接收,注意中断函数需要加中断声明。此外,在我们EVT中有CAN正常模式收发的例程,可以参考一下。后续若有问题,可通过邮箱(lzs@wch.cn)和我沟通,若方便可将工程发至我的邮箱,这边具体看一下


只有登录才能回复,可以选择微信账号登录