Мне нужно сгенерировать два противоположных сигнала ШИМ (когда один высокий, а другой низкий) с использованием таймеров в STM32. Я прочитал несколько примеров, и вот код, который я придумал:
void TM_PINS_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStruct);
}
void TM_TIMER_Init(void) {
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
/* Enable clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
uint16_t Period;
Period = 1000000 / 200000; // 200 KHz from 1MHz
TIM_BaseStruct.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1MHz
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Period = Period - 1;
TIM_BaseStruct.TIM_ClockDivision = 0;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
/* Initialize TIM4 */
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);
/* Start count on TIM4 */
TIM_Cmd(TIM4, ENABLE);
}
void TM_PWM_Init(void) {
TIM_OCInitTypeDef TIM_OCStruct;
/* PWM mode 2 = Clear on compare match */
/* PWM mode 1 = Set on compare match */
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OC1Init(TIM4, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OC2Init(TIM4, &TIM_OCStruct);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = Period/2; /* 50% duty cycle */
}
У меня есть несколько вопросов:
Поскольку мне нужны частоты в десятках кГц, нужно ли устанавливать частоту 100 МГц для скорости GPIO? Есть ли какая-нибудь выгода, чтобы сделать это медленнее?
Будет ли моя функция ШИМ генерировать то, что мне нужно? Я думаю, что противоположные ШИМ-сигналы на самом деле достигаются с использованием режимов ШИМ 1 и 2, но я боюсь, что я что-то там упускаю.
Я хочу иметь возможность останавливать таймеры и устанавливать состояние высокого / низкого уровня на те же контакты. Будет ли работать следующий код?
GPIOD-> MODER |= (5 << 24); //set pin 12 and 13 to GPIO, 5 gives us 101, shifted 23 bits so that '1's are in pos. 24 and 26
GPIOD->regs->BSRR = (3<<12); // 3 gives us 11 pattern, shifted 12 bits so that pins 12 and 13 are set to high
GPIOD-> MODER |= (5 << 24); //set pin 12 and 13 to AF, 5 gives us 101, shifted 24 bits so that '1's are in pos. 25 and 27
Когда АФ восстанавливается, предыдущие настройки ШИМ восстановлены или должны быть установлены заново.
Было бы лучше использовать MODER, как указано выше, чтобы изменить контакты на GPIO, а затем установить на высокий / низкий уровень, или я могу использовать 100% рабочий цикл для высокого и 0% рабочий цикл для низкого?