Здравствуйте.
Хочу заставить светодиод мигать с тактом 1с.
Казалось бы - задача тривиальней некуда. Но я зашел в тупик.
Пишу простейший код:
CODE
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
int counter = 0;
int flag = 0;
void TIM6_DAC_IRQHandler(void)
{
/* Так как этот обработчик вызывается и для ЦАП, нужно проверять,
* произошло ли прерывание по "переполнению" счётчика таймера TIM6.
*/
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
{
/* Очищаем бит обрабатываемого прерывания */
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
flag = 1;
}
}
int main(void)
{
// SystemInit();
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD , ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//**********************************************
// Настроим таймер TIM
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // включаем тактирование таймера
TIM_TimeBaseInitTypeDef base_timer;
TIM_TimeBaseStructInit(&base_timer);
/* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */
base_timer.TIM_Prescaler = 16 - 1;
base_timer.TIM_Period = 1000-1;
base_timer.TIM_ClockDivision = TIM_CKD_DIV1;
base_timer.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6, &base_timer);
TIM_ARRPreloadConfig(TIM6, ENABLE);
/* Разрешаем прерывание по обновлению (в данном случае -
* по переполнению) счётчика таймера TIM6.
*/
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM6, ENABLE); // Включаем таймер
/* Разрешаем обработку прерывания по переполнению счётчика
* таймера TIM6. это же прерывание
* отвечает и за опустошение ЦАП.
*/
NVIC_SetPriority(TIM6_DAC_IRQn, 15);
NVIC_EnableIRQ(TIM6_DAC_IRQn);
//**********************************************
while(1)
{
// отсчитываем каждые 1000 тактов таймера и переключаем светодиод
if( flag == 1 )
{
if(counter == 0)
{
GPIO_SetBits(GPIOD, GPIO_Pin_12);
}
counter++;
if(counter == 1000)
{
GPIO_ResetBits(GPIOD, GPIO_Pin_12);
}
if(counter == 2000)
{
counter = 0;
}
flag = 0;
}
}
}
- мигает как надо. Но здесь параметры:
base_timer.TIM_Prescaler = 16 - 1; и
base_timer.TIM_Period = 1000-1;, т.е. получается, что частота тактирования = 16МГц. Это можно объяснить тем, что идет тактирование от внутреннего генератора (8МГц), но с удвоенной частотой (это, типа, из-за использования предделителей, не равных 1 на шине АРВ1). Но так-то я раситывал на 168МГц.
Пробовал с разными коэффициентами - полная ерунда.
Если я раскомментирую строчку
Код
// SystemInit();
, то светик мигает почти с тактом в 1 сек, но "ПОЧТИ"=чуть-чуть быстрее.
В чем может быть моя неправда? Ткните носом, ПЛЗ. Или объясните матчасть (может все так и должно быть

).
ИМХО, кварц может глючит? (но проверить нечем, нет никаких девайсов)
Сообщение отредактировал IgorKossak - Feb 12 2014, 14:29
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!