1й (в этой ветке) вопрос - конфигурирую таймеры TIM3 и TIM4 для режима ШИМ (пишу в CooCox-e).
Ну и, в-общем, ШИМ-то идёт, но частота получается раз в ~5 МЕНЬШЕ заявленной (а период, соответственно, больше). Вместо импульса длиной 1,5 мс получается ~8 мс.
- Код: Выделить всё • Развернуть
GPIO_InitTypeDef LED,servo;
TIM_TimeBaseInitTypeDef timer3,timer4;
TIM_OCInitTypeDef timer3_oc_init,timer4_oc_init;
TIM_TimeBaseStructInit(&timer3); // Инициализация структуры TIM_TimeBaseInitTypeDef
timer3.TIM_Prescaler=83; // 1000000 Hz
timer3.TIM_Period=19999; // 50 Hz (для серво)
timer3.TIM_ClockDivision=0;
timer3.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&timer3);
TIM_OCStructInit(&timer3_oc_init); // Инициализация структуры TIM_OCInitTypeDef
timer3_oc_init.TIM_OCMode = TIM_OCMode_PWM1; // работаем в режиме ШИМ (PWM)
timer3_oc_init.TIM_OutputState = TIM_OutputState_Enable;
timer3_oc_init.TIM_Pulse = 1500; // Коэф. заполнения?
timer3_oc_init.TIM_OCPolarity = TIM_OCPolarity_High; // положительная полярность
TIM_OC1Init(TIM3,&timer3_oc_init); /// заносим данные в первый канал
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3,ENABLE);
TIM_Cmd(TIM3,ENABLE); // запускаем счёт
TIM_CtrlPWMOutputs(TIM3,ENABLE); //Пуск PWM выходов
Конфигурирование GPIO для ноги, сидящей на TIM3:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); // Timer3
servo.GPIO_Pin=GPIO_Pin_6;
servo.GPIO_Mode=GPIO_Mode_AF;
servo.GPIO_OType=GPIO_OType_PP;
servo.GPIO_Speed=GPIO_Speed_100MHz;
servo.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Init(GPIOA,&servo);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3);
На TIM4 родные (для STM32F4DISCOVERY) светодиоды посажены, штоб моргали раз в секунду - моргают раз в ~5 секунд.
Его настройки:
- Код: Выделить всё • Развернуть
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); // Timer4
LED.GPIO_Pin=GPIO_Pin_12 | GPIO_Pin_13; // Только два светодиода - зелёный и оранж.
LED.GPIO_Speed=GPIO_Speed_100MHz;
LED.GPIO_Mode=GPIO_Mode_AF;
LED.GPIO_OType=GPIO_OType_PP;
GPIO_Init(GPIOD,&LED);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);
TIM_TimeBaseStructInit(&timer4); // Инициализация структуры TIM_TimeBaseInitTypeDef
timer4.TIM_Prescaler=8399; // 10000 Hz
timer4.TIM_Period=9999; // 1 Hz
timer4.TIM_ClockDivision=0;
timer4.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4,&timer4);
TIM_OCStructInit(&timer4_oc_init); // Инициализация структуры TIM_OCInitTypeDef
timer4_oc_init.TIM_OCMode = TIM_OCMode_PWM1; // работаем в режиме ШИМ
timer4_oc_init.TIM_OutputState = TIM_OutputState_Enable;
timer4_oc_init.TIM_Pulse = 5000; // частота ШИМ??? (Коэф. заполнения?)
timer4_oc_init.TIM_OCPolarity = TIM_OCPolarity_High; // положительная полярность
TIM_OC1Init(TIM4,&timer4_oc_init); /// заносим данные в первый канал - порт D12
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
timer4_oc_init.TIM_Pulse = 2500;
TIM_OC2Init(TIM4,&timer4_oc_init);
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4,ENABLE);
TIM_Cmd(TIM4,ENABLE); // запускаем счёт
TIM_CtrlPWMOutputs(TIM4,ENABLE); //Пуск PWM выходов
Все настройки взяты из примеров для STM32F4_DISCOVERY, (Demonstration):
- Код: Выделить всё • Развернуть
/* -----------------------------------------------------------------------
TIM4 Configuration: Output Compare Timing Mode:
In this example TIM4 input clock (TIM4CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1 (APB1 Prescaler = 4, see system_stm32f4xx.c file).
TIM4CLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIM4CLK = 2*(HCLK / 4) = HCLK/2 = SystemCoreClock/2
To get TIM4 counter clock at 2 KHz, the prescaler is computed as follows:
Prescaler = (TIM4CLK / TIM1 counter clock) - 1
Prescaler = (168 MHz/(2 * 2 KHz)) - 1 = 41999
To get TIM4 output clock at 1 Hz, the period (ARR)) is computed as follows:
ARR = (TIM4 counter clock / TIM4 output clock) - 1
= 1999
TIM4 Channel1 duty cycle = (TIM4_CCR1/ TIM4_ARR)* 100 = 50%
TIM4 Channel2 duty cycle = (TIM4_CCR2/ TIM4_ARR)* 100 = 50%
TIM4 Channel3 duty cycle = (TIM4_CCR3/ TIM4_ARR)* 100 = 50%
TIM4 Channel4 duty cycle = (TIM4_CCR4/ TIM4_ARR)* 100 = 50%
==> TIM4_CCRx = TIM4_ARR/2 = 1000 (where x = 1, 2, 3 and 4).
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
function to update SystemCoreClock variable value. Otherwise, any configuration
based on this variable will be incorrect.
----------------------------------------------------------------------- */
Что я делаю не так? (УжЕ весь моск сломал.) Может, какой-нить PCLK1 неправильно установлен?
Даташиты читал, и отдельный про таймеры тоже (ничё там толком конкретно по проблеме не вЫчитал).
Насколько я понял, функция TIM_CtrlPWMOutputs() - необязательна (в примерах её нигде нет, это я её в инете нарыл, но тот код вроде как был для STM32F10x). Что без неё неправильно работает, что с ней.
Про TIM1 будет отдельная пестня.