I'm trying to generate a phase shift PWM signal using three timers.
To Sum up: TIM1 --- triggers --> TIM3 --- triggers ---> TIM4
The signal should look like:
Reference: TIM1 (1 MHz)
___ ___ ___ ___
___| |___| |___| |___| |___|
TIM Count 0 84 168
Update Event ^ ^ ^ ^ ^
Trigger signal: TIM 3 triggered by TIM1 ((SINGLE PULSE MODE!!) 1MHz
/| /| /| /| /|
/ | / | / | / | / |
TIM Count 0 20
Update Event ^ ^ ^ ^ ^
Phase shift signal TIM4 (1MHZ) same duty cycle as TIM1 triggered by TIM3
___ ___ ___ ___ ___
___| |___| |___| |___| |___| |_
Here is my current code. The Reference is running correctly at 1MHz. But the trigger signal is not working by now. The error should be anywhere in initReferenceTimer() or initReferencePWM() function. Up to now it's not working to generate the trigger signal like mentioned above. So I was not able to test, if the phased shift signal will be triggered correctly.
Does anybody have an good idea about it?
For debugging I also bind the trigger signal to an output pin.
#define TIMER_CLOCK 84
#define TIM1_TIMER_CLOCK 168
#define FREQU 1 //MHz
#define SHIFT 20
#define MasterPeriod (TIM1_TIMER_CLOCK/FREQU)-1
#define MasterPulse ((TIM1_TIMER_CLOCK/FREQU)-1)/2
#define ReferencePeriod SHIFT
#define ReferencePulse (SHIFT/2)
#define SlavePeriod (TIM1_TIMER_CLOCK/FREQU)-1
#define SlavePulse ((TIM1_TIMER_CLOCK/FREQU)-1)/2
//TIM1 Channel1: PA7 N
void initMasterPin()
{
GPIO_InitTypeDef GPIO_InitStructureTimer;
// Port clock enable
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
// Set PWM Port, Pin and method
GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructureTimer);
// Connect TIM pin to AF
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM1);
}
//TIM3 Channel1 PC6
void initReferencePin()
{
GPIO_InitTypeDef GPIO_InitStructureTimer;
// Port clock enable
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
// Set PWM Port, Pin and method
GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOC, &GPIO_InitStructureTimer);
// Connect TIM pin to AF
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
}
//TIM4 Channel1: PB6
void initSlavePin()
{
GPIO_InitTypeDef GPIO_InitStructureTimer;
// Port clock enable
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// Set PWM Port, Pin and method
GPIO_InitStructureTimer.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOB, &GPIO_InitStructureTimer);
// Connect TIM pin to AF
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_TIM4);
}
//Tim1 Channel1: PA7
void initMasterTimer()
{
// set timer frequencies
TIM_TimeBaseInitTypeDef TIM_Config;
// 1.Enable TIM clock
RCC_APB2PeriphClockCmd (RCC_APB2Periph_TIM1, ENABLE);
// 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
// Time Base configuration
TIM_TimeBaseStructInit (&TIM_Config);
TIM_Config.TIM_Period = MasterPeriod;
TIM_Config.TIM_Prescaler = 0;
TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Config.TIM_RepetitionCounter = 0;
//configure the Time Base unit with the corresponding configuration
TIM_TimeBaseInit (TIM1, &TIM_Config);
// Enable the NVIC if you need to generate the update interrupt.
// Enable the corresponding interrupt
}
//TIM3 Channel1 PC6
void initReferenceTimer()
{
// set timer frequencies
TIM_TimeBaseInitTypeDef TIM_Config;
// 1.Enable TIM clock
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3, ENABLE);
// 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
// Time Base configuration
TIM_TimeBaseStructInit (&TIM_Config);
TIM_Config.TIM_Period = ReferencePeriod;//One Step Phase Shift
TIM_Config.TIM_Prescaler = 0;
TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Config.TIM_RepetitionCounter = 0;
//configure the Time Base unit with the corresponding configuration
TIM_TimeBaseInit (TIM3, &TIM_Config);
// Enable the NVIC if you need to generate the update interrupt.
// Enable the corresponding interrupt
}
//TIM4 Channel1: PB6
void initSlaveTimer()
{
// set timer frequencies
TIM_TimeBaseInitTypeDef TIM_Config;
// 1.Enable TIM clock
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM4, ENABLE);
// 2.Fill the TIM_TimeBaseInitStruct with the desired parameters.
// Time Base configuration
TIM_TimeBaseStructInit (&TIM_Config);
TIM_Config.TIM_Period = SlavePeriod;
TIM_Config.TIM_Prescaler = 0;
TIM_Config.TIM_CounterMode = TIM_CounterMode_Up;
TIM_Config.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_Config.TIM_RepetitionCounter = 0;
//configure the Time Base unit with the corresponding configuration
TIM_TimeBaseInit (TIM4, &TIM_Config);
// Enable the NVIC if you need to generate the update interrupt.
// Enable the corresponding interrupt
}
//Tim1 Channel1: PA7
void initMasterPWM(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = MasterPulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
/* Master Mode selection */
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
/* Select the Master Slave Mode */
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
}
//TIM3 Channel1 PC6
void initReferencePWM(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = ReferencePulse; // set the duty cycle / pulse here!
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_SelectOnePulseMode(TIM3, TIM_OPMode_Single);
/* Slave Mode selection: TIM3 */
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
/* Select the Master Slave Mode */
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
}
//TIM4 Channel1: PB6
void initSlavePWM(void)
{
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = SlavePulse;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2);
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
TIM_SelectOnePulseMode(TIM4, TIM_OPMode_Single);
}
int main(void)
{
initMasterPin();
initReferencePin(); //FOR DEBUGGING ONLY
initSlavePin();
initMasterTimer();
initReferenceTimer();
initSlaveTimer();
initMasterPWM();
initReferencePWM();
initSlavePWM();
// enable timer / counter
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM4, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM3, ENABLE);
TIM_CtrlPWMOutputs(TIM4, ENABLE);
/* Busy loop */
int i;
while (1)
{
i++;
}
}
Are you sure you don't have a typo in your initReferencePWM?
void initReferencePWM(void)
{
...
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
...
}
Why TIM2 all the sudden?