billidean 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 (изменено) · Жалоба Здравствуйте. Хочу заставить светодиод мигать с тактом 1с. Казалось бы - задача тривиальней некуда. Но я зашел в тупик. Пишу простейший код: #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 сек, но "ПОЧТИ"=чуть-чуть быстрее. В чем может быть моя неправда? Ткните носом, ПЛЗ. Или объясните матчасть (может все так и должно быть :05: ). ИМХО, кварц может глючит? (но проверить нечем, нет никаких девайсов) Изменено 12 февраля, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба Не вижу установки делителей для тактов периферийных шин. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба В SystemInit() - вроде какие-то предделители устанавливаются... (я, если честно, не встречал таких, как вы говорите, при поисках всяких исходников для установки таймеров). То, что я нарыл (по-быстрому) в инете, я и накидал в своем коде, НИКАКИХ доп. установок не встречал. Можете по-подробнее объяснить мою недоработку. (если можно, то с кодом) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба В SystemInit() - вроде какие-то предделители устанавливаются... (я, если честно, не встречал таких, как вы говорите, при поисках всяких исходников для установки таймеров). То, что я нарыл (по-быстрому) в инете, я и накидал в своем коде, НИКАКИХ доп. установок не встречал. Можете по-подробнее объяснить мою недоработку. (если можно, то с кодом) Наверное, устанавливаются... только во что? Типа такого (это для другого процессора): RCC->CFGR = RCC_CFGR_HPRE_0 * 0 | // HPRE[3:0] bits (AHB prescaler): SYSCLK / 1 = 24 MHz (max) RCC_CFGR_PPRE1_0 * 0 | // PRE1[2:0] bits (APB1 prescaler): HCLK / 1 = 24 MHz (max) RCC_CFGR_PPRE2_0 * 0 | // PRE2[2:0] bits (APB2 prescaler): HCLK / 1 = 24 MHz А еще я на MCO вывожу какую-нибудь системную частоту, для проверки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 (изменено) · Жалоба В systemInit() dspsdftncz SetSysClock(), код которой: static void SetSysClock(void) { /******************************************************************************/ /* PLL (clocked by HSE) used as System clock source */ /******************************************************************************/ __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01) { /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS; /* HCLK = SYSCLK / 1*/ RCC->CFGR |= RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK / 2*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK / 4*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; /* Configure the main PLL */ RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); /* Enable the main PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till the main PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; /* Select the main PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= RCC_CFGR_SW_PLL; /* Wait till the main PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); { } } else { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ } } А строка /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */ - вообще внушает уверенность и оптимизм в 168МГц. Но вот, почему-то, это не работает. Изменено 12 февраля, 2014 пользователем billidean [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба Получается, на периферийной шине у вас 168 / 4 = 42 MHz. Если HSE запустился. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба При установке base_timer.TIM_Prescaler = (42-1) и (21-1) получаю тоже неверный результат, светодиод разбегается с часами(секундомером) уже за 10-15 тиков (морганий). Вы работали с подобной задачей/кодом? или все теория? (Просто я уже много где потыкался, а результат пока один - тактовая на таймере непонятно-какая и чем определена) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Thorn 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба На кварце нагрузочные конденсаторы имеются? Емкость правильная для используемого кварца? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба а где вы включаете внешний генератор, подключаете ПЛЛ, ждете стабильного сигнала, и переходите на него? и если мне не изменяет память то в STM надо правильно определить тип вашего устройства, чтобы в огромном могучем файле правильно сработали дефайны, и задалась правильная частота. в свое время надоело с этим убиваться, взял по мануалу правильно настроил клок, шин, проца, и всего. Там 3 флажка, 4 регистра, куда понятнее чем разбираться в 3 экранах дефайнов- передефайнов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба Можно вывести на светодиод бит SWS1 из RCC_CFGR, чтобы удостовериться, что PLL used as the system clock. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба а еще не забыть настроить выходную ножку на максимальную частоту, а то на нее хоть клок подавай, а из нее еле еле лезет:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2014 Опубликовано 12 февраля, 2014 · Жалоба а еще не забыть настроить выходную ножку на максимальную частоту, а то на нее хоть клок подавай, а из нее еле еле лезет:) Если просто статус выводить, а не частоту, то не надо. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 13 февраля, 2014 Опубликовано 13 февраля, 2014 · Жалоба в STM надо правильно определить тип вашего устройства, чтобы в огромном могучем файле правильно сработали дефайны, и задалась правильная частота. - что вы имеете в виду? При создании проекта я выбирал кристалл, и это, как я предполагаю, и определяет всякие там дефайны. По поводу контроля регистров (RCC_CFGR) - нашел какую-то реализацию printf'a, люди пишут, что работает, вечером попробую запустить. И если все пойдет нормально, то можно будет контролировать все регистры настройки системы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 февраля, 2014 Опубликовано 13 февраля, 2014 · Жалоба ага добро пожаловать в мир СТМ, не хрена это не определяет. Посмотрите огромный хедер, там куча ветвей для одного итого же проца в зависимости от серии, того какой плотности это устройство (вроде так это у СТМ) называется. И проверьте правильные ли дефайны у вас стоят. Ставлю на то что стоят по умолчанию, на какой-то массовый проц из серии.... я так пару недель бился об этот файл... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
billidean 0 13 февраля, 2014 Опубликовано 13 февраля, 2014 (изменено) · Жалоба Вы про stm32f4xx.h-файл? Там всякие определения/размещения регистров, маски, макросы управления битами. Так-то по всей линейке (F4) вроде по регистрам должно быть полное соответствие (помнится где-то встречал такую фразу по СТМ). Изменено 13 февраля, 2014 пользователем billidean Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться