GD32 CAN1和TIMER0同时开启问题

背景:今天在一个项目调试的时候发现了一些问题,由此贴记录一下问题解决的过程。

使用的芯片是GD32F305VE。使用到了CAN1和TIMER0。在使用这连个外设的时候发送了一些问题。

单独使用CAN1。功能正常。

单独使用TIMER0。配置为输出模式。功能正常。

但是当两个功能同时使用,初始化的时候,就出问题了。


1、引脚配置

cpp 复制代码
//TIMER0 引脚定义
#define   TIMER0_CH2_GPIO_PIN              GPIO_PIN_10
#define   TIMER0_CH1_GPIO_PIN              GPIO_PIN_9
#define   TIMER0_CH2N_GPIO_PIN             GPIO_PIN_15
#define   TIMER0_CH1N_GPIO_PIN             GPIO_PIN_14
cpp 复制代码
//CAN1引脚定义
#define   CAN1_CLOCK                    RCU_GPIOB
#define   CAN1_GPIO                     GPIOB
#define   CAN1_TX_GPIO_PIN              GPIO_PIN_13
#define   CAN1_RX_GPIO_PIN              GPIO_PIN_12

从引脚上看,每个是没有用到重复的引脚的。都是单独分开。

2、发现问题

但是这时候,会导致一个问题。

CAN1的初始化失败了。

cpp 复制代码
//这是底层的库函数,CAN初始化
ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init)
{
    uint32_t timeout = CAN_TIMEOUT;
    ErrStatus flag = ERROR;
    
    /* disable sleep mode */
    CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
    /* enable initialize mode */
    CAN_CTL(can_periph) |= CAN_CTL_IWMOD;
    /* wait ACK */
    while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
        timeout--;
    }
    /* check initialize working success */
    if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
        flag = ERROR;
    }else{
        /* set the bit timing register */
        CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \
                              BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \
                              BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \
                              BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \
                              BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U)));

        /* time trigger communication mode */
        if(ENABLE == can_parameter_init->time_triggered){
            CAN_CTL(can_periph) |= CAN_CTL_TTC;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_TTC;
        }
        /* automatic bus-off managment */
        if(ENABLE == can_parameter_init->auto_bus_off_recovery){
            CAN_CTL(can_periph) |= CAN_CTL_ABOR;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_ABOR;
        }
        /* automatic wakeup mode */
        if(ENABLE == can_parameter_init->auto_wake_up){
            CAN_CTL(can_periph) |= CAN_CTL_AWU;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_AWU;
        }
        /* automatic retransmission mode disable */
        if(ENABLE == can_parameter_init->no_auto_retrans){
            CAN_CTL(can_periph) |= CAN_CTL_ARD;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_ARD;
        }
        /* receive fifo overwrite mode */        
        if(ENABLE == can_parameter_init->rec_fifo_overwrite){
            CAN_CTL(can_periph) |= CAN_CTL_RFOD;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_RFOD;
        } 
        /* transmit fifo order */
        if(ENABLE == can_parameter_init->trans_fifo_order){
            CAN_CTL(can_periph) |= CAN_CTL_TFO;
        }else{
            CAN_CTL(can_periph) &= ~CAN_CTL_TFO;
        }  
        /* disable initialize mode */
        CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD;
        timeout = CAN_TIMEOUT;
        /* wait the ACK */
        while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
            timeout--;
        }
        /* check exit initialize mode */
        if(0U != timeout){
            flag = SUCCESS;
        }
    }  
    return flag;
}

进入这个函数后,会进入使能初始化工作工作模式。这个查看用户手册可以查到。

下图是进入函数运行中的寄存器状态。这是是出于初始化工作状态的

但退出函数之前,发现并没有退出初始化工作模式。导致初始化失败了。

3、定位问题

在定位问题的过程中,试了一下把TIMER0的初始化先屏蔽掉。结果就又正常了。

因此定位问题发生在TIMER0的初始化。

但是很奇怪,TIMER0的初始化,只初始化了通道1,和通道2,没有初始化通道0,按理说是不应该有影响的。

查看了寄存器

这个地方导致,这个脚被初始化为输出。再看下一个寄存器。

这里导致输出为高电平,和示波器抓到的波形一样。

所以这就是导致CAN1初始化失败的原因。

4、原理

5、解决方法

把通道0配置初始化为输入模式。就能解决问题了。

相关推荐
azwsm15 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu18 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客19 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭19 小时前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽20 小时前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊21 小时前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
进击的小头1 天前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭1 天前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
项目題供诗1 天前
STM32-AD单通道&AD多通道(十九)
stm32·单片机·嵌入式硬件
南岸的水1 天前
BMS国标充电解析
单片机·嵌入式硬件·mcu