/**
|
* @file pwm.c
|
* @author Ethan.Tao (tzj0429@163.com)
|
* @brief
|
* @version 0.1
|
* @date 2020-12-12
|
*
|
* @copyright Copyright (c)
|
*
|
*/
|
#include "pwm.h"
|
static volatile uint32_t timer_outcnt = 0;
|
/*****************************************************************************************************
|
Timer2 is used to speed cal
|
APB1 is 64M ,so Timer2 clock is 64M,after prescaler 480 is 0.1M(10us)
|
input pin:
|
PA15-CO
|
PB4-AO
|
PB5-BO
|
*****************************************************************************************************/
|
static void Timer2Init(void)
|
{
|
timer_parameter_struct timercontralcfg;
|
|
timer_deinit(TIMER2);
|
|
timercontralcfg.prescaler = 4799; //48Mhz /4800 =0.01Mhz = 100us
|
timercontralcfg.alignedmode = TIMER_COUNTER_EDGE;
|
timercontralcfg.counterdirection = TIMER_COUNTER_UP;
|
timercontralcfg.period = PERIOD_CAP; //100us*10000=1s
|
|
timer_init(TIMER2, &timercontralcfg);
|
timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
|
timer_interrupt_enable(TIMER2, TIMER_INT_UP);
|
nvic_irq_enable(TIMER2_IRQn, 1);
|
}
|
|
/*****************************************************************************************************
|
Timer0 is used to generente PWM
|
APB2 is 48M and prescaler is 1,so Timer0 clock is 48M
|
output pin:
|
PA10-HIN1-TIME0_CH2
|
PA9 -HIN2-TIME0_CH1
|
PA8 -HIN3-TIME0_CH0
|
PB1-LIN1-TIME0_CH2_N
|
PB0-LIN2-TIME0_CH0_N
|
PA7-LIN3-TIME0_CH0_N
|
*****************************************************************************************************/
|
static void Timer0Init(void)
|
{
|
uint16_t Duty = PERIOD_CMP / 10;
|
timer_parameter_struct timercontralcfg;
|
timer_oc_parameter_struct timeroutcfg[3];
|
timer_break_parameter_struct timer_breakpara;
|
|
//config timer0
|
timercontralcfg.prescaler = 0; //counter prescaler is 0
|
timercontralcfg.alignedmode = TIMER_COUNTER_EDGE; //center align and counter style depend on dir set
|
timercontralcfg.counterdirection = TIMER_COUNTER_UP; //counter style is up
|
timercontralcfg.clockdivision = TIMER_CKDIV_DIV1; //Timer0 is 64M
|
timercontralcfg.period = PERIOD_CMP; // set period(counter value 0~2^15)
|
timer_init(TIMER0, &timercontralcfg);
|
|
timeroutcfg[0].ocpolarity = TIMER_OC_POLARITY_HIGH; //channel output polarity is high
|
timeroutcfg[0].ocnpolarity = TIMER_OCN_POLARITY_HIGH;
|
timeroutcfg[0].outputstate = TIMER_CCX_ENABLE; //channel enable
|
timeroutcfg[0].outputnstate = TIMER_CCXN_DISABLE; //channel complementary DISABLE
|
timeroutcfg[0].ocidlestate = TIMER_OC_IDLE_STATE_LOW;
|
timeroutcfg[0].ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
|
|
timeroutcfg[1].ocpolarity = TIMER_OC_POLARITY_HIGH; //channel output polarity is high
|
timeroutcfg[1].ocnpolarity = TIMER_OCN_POLARITY_HIGH;
|
timeroutcfg[1].outputstate = TIMER_CCX_ENABLE; //channel enable
|
timeroutcfg[1].outputnstate = TIMER_CCXN_DISABLE; //channel complementary DISABLE
|
timeroutcfg[1].ocidlestate = TIMER_OC_IDLE_STATE_LOW;
|
timeroutcfg[1].ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
|
|
timeroutcfg[2].ocpolarity = TIMER_OC_POLARITY_HIGH; //channel output polarity is high
|
timeroutcfg[2].ocnpolarity = TIMER_OCN_POLARITY_HIGH;
|
timeroutcfg[2].outputstate = TIMER_CCX_ENABLE; //channel enable
|
timeroutcfg[2].outputnstate = TIMER_CCXN_DISABLE; //channel complementary DISABLE
|
timeroutcfg[2].ocidlestate = TIMER_OC_IDLE_STATE_LOW;
|
timeroutcfg[2].ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
|
|
timer_channel_output_config(TIMER0, TIMER_CH_0, &timeroutcfg[0]);
|
timer_channel_output_config(TIMER0, TIMER_CH_1, &timeroutcfg[1]);
|
timer_channel_output_config(TIMER0, TIMER_CH_2, &timeroutcfg[2]);
|
|
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, Duty); //set duty
|
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, Duty);
|
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, Duty);
|
|
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1); //set pwm1 mode first low then high
|
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM1);
|
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM1);
|
|
timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_ENABLE); //shadow ENable
|
timer_channel_output_shadow_config(TIMER0, TIMER_CH_1, TIMER_OC_SHADOW_ENABLE);
|
timer_channel_output_shadow_config(TIMER0, TIMER_CH_2, TIMER_OC_SHADOW_ENABLE);
|
|
/* configure TIMER break function */
|
timer_break_struct_para_init(&timer_breakpara);
|
/* automatic output enable, break, dead time and lock configuration*/
|
timer_breakpara.runoffstate = TIMER_ROS_STATE_DISABLE;
|
timer_breakpara.ideloffstate = TIMER_IOS_STATE_DISABLE;
|
timer_breakpara.deadtime = 255;
|
timer_breakpara.breakpolarity = TIMER_BREAK_POLARITY_LOW;
|
timer_breakpara.outputautostate = TIMER_OUTAUTO_ENABLE;
|
timer_breakpara.protectmode = TIMER_CCHP_PROT_0;
|
timer_breakpara.breakstate = TIMER_BREAK_ENABLE;
|
timer_break_config(TIMER0, &timer_breakpara);
|
|
timer_primary_output_config(TIMER0, ENABLE);
|
timer_auto_reload_shadow_enable(TIMER0);
|
}
|
|
void TimerInit(void)
|
{
|
rcu_periph_clock_enable(RCU_TIMER2);
|
rcu_periph_clock_enable(RCU_TIMER0);
|
Timer0Init();
|
Timer2Init();
|
timer_enable(TIMER0);
|
}
|
|
void SetPwmDuty(uint16_t ch, uint32_t duty)
|
{
|
uint32_t duty_temp = (PERIOD_CMP >= duty) ? (PERIOD_CMP - duty) : 0;
|
timer_channel_output_pulse_value_config(TIMER0, ch, duty);
|
}
|
|
void SetPwmPeriod(uint32_t period)
|
{
|
TIMER_CAR(TIMER0) = period;
|
}
|
|
extern void StartSpeedTime(void)
|
{
|
timer_enable(TIMER2);
|
}
|
|
extern void StopSpeedTime(void)
|
{
|
timer_disable(TIMER2);
|
}
|
extern void TIMER2_IRQHandler_CallBack(void)
|
{
|
timer_outcnt++;
|
}
|
|
extern uint32_t GetSpeedTimerOutcnt(void)
|
{
|
uint32_t rtn = timer_outcnt;
|
timer_outcnt = 0;
|
return rtn;
|
}
|