【无标题】

void MX_TIM1_Init(void)
{
	long int Temp;
//==1、使能时钟===============
    PWM_GPIO_RCC_ENABLE();
PWM_TIMER_RCC_ENABLE();
//============================

//==2、配置GPIO引脚================================================
    gpio_init(GPIO_PORT_PWM_CH1, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH1_PIN);
    gpio_init(GPIO_PORT_PWM_CH2, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH2_PIN);
    gpio_init(GPIO_PORT_PWM_CH3, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH3_PIN);
    gpio_init(GPIO_PORT_PWM_CH1N, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH1N_PIN);
    gpio_init(GPIO_PORT_PWM_CH2N, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH2N_PIN);
    gpio_init(GPIO_PORT_PWM_CH3N, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
              PWM_CH3N_PIN);
//=====================================================================

//==3、复位寄存器================================================
    /*reset register*/
    TIMER_CTL0(PWM_TIMER) = 0;
    TIMER_CTL1(PWM_TIMER) = 0;
    TIMER_SMCFG(PWM_TIMER) = 0;
    TIMER_DMAINTEN(PWM_TIMER) = 0;
    TIMER_CHCTL0(PWM_TIMER) = 0;
TIMER_CHCTL1(PWM_TIMER) = 0;
//=================================================================

//==4、配置寄存器=======================================================
    TIMER_CTL0(PWM_TIMER) =
        (1 << 1) | (0 << 2) | (0 << 3) | (1 << 5) | (1 << 7) | (0 << 8);
    
    TIMER_CTL1(PWM_TIMER) =
            (0 << 0) | (0 << 2) | (0 << 3) | (7 << 4); // use O3CPRE trigger TRGO 

    TIMER_SMCFG(PWM_TIMER) = (1 << 4); // NO USE

    TIMER_PSC(PWM_TIMER) = 0; //预分频器设置
    TIMER_CAR(PWM_TIMER) =
        (PWM_DOMAIN_CLK_FRQ >> 1) /
        SYS_PWM_FREQ; //重载寄存器,设定计数器周期,根据PWM频率设置

        TIMER_CREP(PWM_TIMER) = 0; //重载同期计数器

    TIMER_CHCTL0(PWM_TIMER) = 0x6868;
TIMER_CHCTL1(PWM_TIMER) = 0x6868;//0x68代表
 
    TIMER_CHCTL2(PWM_TIMER) |= 0x555;//配置TIM0的三个通道0、1、2的输出极性

    /*configure deadtime*/
    {
        Temp = (int)(PWM_DEAD_TIME_VALUE * PWM_DOMAIN_CLK_FRQ *
                     0.000001); // 0.4us死区
        if (Temp > 1008)
            Temp = 1008;

        else if (Temp >= 504) //(32 + x)*16
        {
            Temp = (Temp >> 4) - 32;
            Temp |= 0x7 << 5;
        } else if (Temp >= 254) //(32 + x)*8
        {
            Temp = (Temp >> 3) - 32;
            Temp |= 0x6 << 5;
        } else if (Temp >= 127) //(64 + x)*2
        {
            Temp = (Temp >> 1) - 64;
            Temp |= 0x1 << 7;
            Temp |= 0x2 << 6;
        }
    }

    TIMER_CCHP(PWM_TIMER) =
        0x4c00 + Temp; //后面的数据为死区时间的周期数,注意这个寄存器只能写一次


    TIMER_CH0CV(PWM_TIMER) = TIMER_CAR(PWM_TIMER) >> 1;
    TIMER_CH1CV(PWM_TIMER) = TIMER_CAR(PWM_TIMER) >> 1;
    TIMER_CH2CV(PWM_TIMER) = TIMER_CAR(PWM_TIMER) >> 1;
    TIMER_CH3CV(PWM_TIMER) =
        (PWM_TRG_ADC_DELAY * PWM_DOMAIN_CLK_FRQ * 0.000001); 
    TIMER_CTL0(PWM_TIMER) &= ~(1 << 1);
    TIMER_SWEVG(PWM_TIMER) = (1 << 0) | (1 << 5);
    TIMER_INTF(PWM_TIMER) = 0; //清所有中断标志
    /*  TIMER_DMAINTEN(PWM_TIMER)= 1 << 0;            //使能更新中断*/

    TIMER_CHCTL0(PWM_TIMER) |= (1 << 11) | (1 << 3); // PWM预装载使能
    TIMER_CHCTL1(PWM_TIMER) |= (1 << 3);
}
/********************************************
PA1 <--> FB_CurrentB <-->ADC0 <--> Ch1
PA2 <--> FB_CurrentC <-->ADC1 <--> Ch2
PA3 <--> ADC_PWR  <--> ADC0 <--> Ch3
PA4 <--> ADC_BRK_FB  <--> ADC0 <--> Ch4 no use
PA5 <--> ADC_TEMP <--> ADC1 <--> Ch5
PA6 <--> ADC_TEMP2 <--> ADC1 <--> Ch6
PA7 <--> ADC_TEMP3 <--> ADC0 <--> Ch7 no use
PC4<-->ADC_BUS_I  <--> ADC0 <-->ch14
T(CONV) = (12.5(sample) + 7.5(hold))/30MHz = 0.666us
total time for inject = 4*T(CONV) = 2.666us

********************************************/
void HW_ADC_Init(void)
{
    // 时钟配置
    rcu_periph_clock_enable(RCU_ADC0);
    rcu_periph_clock_enable(RCU_ADC1);
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_10MHZ,
              GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3  | GPIO_PIN_5 |
                  GPIO_PIN_6 | GPIO_PIN_7);

    ADC_CTL0(ADC0) = (5UL << 16)   //注入并行模式
                     | (0UL << 13) //间断模式下的转换数目
                     | (0UL << 12) //注入组间断模式禁止
                     | (0UL << 11) //规则组间断模式禁止
                     | (0UL << 10) //注入组自动转换禁止
                     | (1UL << 8)  //扫描模式使能
                     | (1UL << 7); //EOIC中断使能

    ADC_CTL1(ADC0) = (1UL << 23) //ʹADC0的通道16和17使能
                     | (0UL << 20) //规则组外部触发禁止
                     | (7UL << 17) //规则组软件触发
                     | (1UL << 15) //注入组外部触发使能
                     | (0UL << 12) //注入组外部触发选择定时器0 TRGO
                     | (0UL << 11) //最低有效位对齐
                     | (0UL << 8)  //DMA请求禁止
                     | (0UL << 1)  //禁止连续模式
                     | (0UL << 0); //禁止ADC并掉电

    ADC_IOFF0(ADC0) = 0;
    ADC_IOFF1(ADC0) = 0;
    ADC_IOFF2(ADC0) = 0;
    ADC_IOFF3(ADC0) = 0;
    ADC_ISQ(ADC0) = (3UL << 20)             //转换长度
                    | (ADC_CHANNEL_1 << 15) //刹车电压-->ADC_BUS_I
                    | (ADC_CHANNEL_1 << 10) //母线电压
                    | (ADC_CHANNEL_1 << 5)  // B 相电流
                    | (ADC_CHANNEL_1 << 0); // B 相电流

    ADC_SAMPT1(ADC0) &= ~((7UL << 3) | (7UL << 9) | (7UL << 12)); // ch0,ch1,ch2
    ADC_SAMPT1(ADC0) |= ((MOTOR_PHASE_CURRENT_SAMPLE_TIME << 3) |
                         (MOTOR_PHASE_CURRENT_SAMPLE_TIME << 9) |
                         (MOTOR_PHASE_CURRENT_SAMPLE_TIME << 12));

    ADC_CTL0(ADC1) = (5UL << 16)   //注入并行模式
                     | (0UL << 13) //间断模式计数
                     | (0UL << 12) //注入通道上禁用间断模式
                     | (0UL << 11) //规则通道上禁用间断模式
                     | (0UL << 10) //关闭自动注入转换
                     | (1UL << 8)  //开启扫描模式
                     | (0UL << 7); //允许注入中断

    ADC_CTL1(ADC1) = (1UL << 23)   //使能温度和内部参考
                     | (0UL << 20) //规则通道不使用外部事件触发
                     | (7UL << 17) //规则通道使用软件触发
                     | (1UL << 15) //注入通道使用外部事件触发
                     | (0UL << 12) //注入通道使用TIM0_TGRO触发
                     | (0UL << 11) //数据右对齐
                     | (0UL << 8)  //不使用DMA
                     | (0UL << 1)  //单次转换
                     | (0UL << 0); //使能ADC

    ADC_IOFF0(ADC1) = 0;
    ADC_IOFF1(ADC1) = 0;
    ADC_IOFF2(ADC1) = 0;
    ADC_IOFF3(ADC1) = 0;
    ADC_ISQ(ADC1) = (3UL << 20)             //转换长度
                    | (ADC_CHANNEL_2 << 15) // ADC_TEMP2
                    | (ADC_CHANNEL_2 << 10) // ADC_TEMP
                    | (ADC_CHANNEL_2 << 5)  // C  相电流
                    | (ADC_CHANNEL_2 << 0); // C 相电流
    ADC_SAMPT1(ADC1) &= ~((7UL << 3) | (7UL << 21) | (7UL << 18));
    ADC_SAMPT1(ADC1) |= ((MOTOR_PHASE_CURRENT_SAMPLE_TIME << 3) |
                         (MOTOR_PHASE_CURRENT_SAMPLE_TIME << 21) |
                         (MOTOR_PHASE_CURRENT_SAMPLE_TIME << 18));

    ADC_CTL1(ADC1) |= 1; //使能ADC

    ADC_CTL1(ADC0) |= 1;
    nvic_irq_enable(ADC_IRQ, 0, 0);
    TIMER_CTL0(PWM_TIMER) |= 0x1; // enable PWM
}

一、计时器触发ADC采样

  1. 本工程ADC需要对六个通道进行采样。共用到ADC0和ADC1两个实例。除通道外,两个实例配置基本相同。
    接下来的解释中ADC配置相同的,仅选取ADC1作例解释。
ADC_ISQ(ADC0) = (3UL << 20)             //转换长度
                    | (ADC_CHANNEL_1 << 15) //选择通道 刹车电压-->ADC_BUS_I
                    | (ADC_CHANNEL_1 << 10) //母线电压
                    | (ADC_CHANNEL_1 << 5)  // B 相电流
                    | (ADC_CHANNEL_1 << 0); // B 相电流
ADC_ISQ(ADC1) = (3UL << 20)             //转换长度
                    | (ADC_CHANNEL_2 << 15) // ADC_TEMP2
                    | (ADC_CHANNEL_2 << 10) // ADC_TEMP
                    | (ADC_CHANNEL_2 << 5)  // C  相电流
                    | (ADC_CHANNEL_2 << 0); // C 相电流
  1. 选用注入并行模式,且在触发信号的下降沿开始采样
ADC_CTL0(ADC1) = (5UL << 16)   //注入并行模式

在这里插入图片描述
3. 注入通道选择TIM0_TGRO触发

ADC_CTL1(ADC1) =  (1UL << 15) //注入通道使用外部事件触发
                | (0UL << 12) //注入通道使用TIM0_TGRO触发
  1. TIMER0 (bit4)将TGRO触发源选择为O3CPRE(通道3的输出准备信号)
TIMER_CTL1(PWM_TIMER) =
            (0 << 0) | (0 << 2) | (0 << 3) | (7 << 4); // use O3CPRE trigger TRGO 

这里没有明确的描述,我认为意思就是:O3CPRE的形状和相位与TRGO完全相同,没有延迟。
5. OC3CPRE在CNT小于CH3CV时高电平,在达到CH3CV时变为低电平

TIMER_CHCTL0(PWM_TIMER) = 0x6868;
TIMER_CHCTL1(PWM_TIMER) = 0x6868;

TIMER_CHCTL0和TIMER_CHCTL1名为通道控制器。其中TIMER_CHCTL0负责配置通道0和通道1,TIMER_CHCTL1负责配置通道2和通道3。四个通道原理一致,下面配上通道2配置为0x6的含义解释。
在这里插入图片描述
截取图片
6. 综上所述我认为配置的含义如图所示。
6.通道3捕获比较寄存器CH3CV的值,设置为延时1us。

#define PWM_TRG_ADC_DELAY      (float)2.33f//2.33微秒
#define PWM_DOMAIN_CLK_FRQ    rcu_clock_freq_get(CK_APB2)
TIMER_CTL0(PWM_TIMER) =
        (1 << 1) | (0 << 2) | (0 << 3) | (1 << 5) | (1 << 7) | (0 << 8);//bit设置计数器对齐模式
TIMER_CH3CV(PWM_TIMER) = (PWM_TRG_ADC_DELAY * PWM_DOMAIN_CLK_FRQ * 0.000001); //通道3捕获比较寄存器

在这里插入图片描述
TIM0通过CTL0配置的计数方式为中央对齐向下计数置1模式。描述中涉及的比较中断标志位为CHxIF,与此例无关。
也就是说TIM0的CNT在从0开始延时2.33us以后触发ADC采样。
控制ADC采样时刻的意义在于避开PWM波形的上升沿或者下降沿,避免边沿电平抖动的影响。

  • 实测波形?
    待采集
TIMER_CHCTL2(PWM_TIMER) |= 0x555;//配置输出极性

在这里插入图片描述
在这里插入图片描述
0x5=0101B含义:
使能通道
高电平有效
使能互补输出
互补通道高电平有效

  • CH0、CH1、CH2三路通道的PWM互补输出波形如何产生的?以及其上升沿、下降沿与死区时间的关系?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
06-06
这是一个针对GD32F305芯片的定时器配置函数,主要是用于输入捕获模式。下面是代码的解释: 1. 开启TIMER0时钟 ``` rcu_periph_clock_enable(RCU_TIMER0); ``` 2. 复位TIMER0 ``` timer_deinit(TIMER0); ``` 3. 配置TIMER0的基本参数,包括计数器方向、计数器分频、计数器模式、计数器周期 ``` timer_parameter_struct timer_initpara; timer_initpara.prescaler = 119; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 65535; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER0,&timer_initpara); ``` 4. 配置TIMER0的输入捕获通道,包括极性、输入捕获选择、预分频和滤波器参数 ``` timer_ic_parameter_struct timer_icinitpara; timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0x0; timer_input_capture_config(TIMER0,TIMER_CH_1,&timer_icinitpara); ``` 5. 配置TIMER0的中断 ``` nvic_irq_enable(TIMER0_Channel_IRQn, 1, 1); timer_primary_output_config(TIMER0, ENABLE); /* auto-reload preload enable */ timer_auto_reload_shadow_enable(TIMER0); /* clear channel 0 interrupt bit */ timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH1); /* channel 0 interrupt enable */ timer_interrupt_enable(TIMER0,TIMER_INT_CH1); ``` 6. 开启TIMER0计数 ``` timer_enable(TIMER0); ``` 总体来说,这个函数的作用是配置TIMER0为输入捕获模式,其中TIMER0的计数器值会根据外部信号的变化而变化,以实现计时和计数等功能。其中的nvic_irq_enable函数是用于使能TIMER0的中断,timer_interrupt_enable函数是用于使能TIMER0的输入捕获通道中断。需要注意的是,这个函数只是一个配置函数,需要在调用时传入相应的参数才能实现具体的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值