Перейти к содержанию
    

STM32F4::Discovery -> Помогите с таймером

Здравствуйте.

Хочу заставить светодиод мигать с тактом 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: ).

 

ИМХО, кварц может глючит? (но проверить нечем, нет никаких девайсов) :wacko:

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не вижу установки делителей для тактов периферийных шин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В SystemInit() - вроде какие-то предделители устанавливаются... (я, если честно, не встречал таких, как вы говорите, при поисках всяких исходников для установки таймеров).

То, что я нарыл (по-быстрому) в инете, я и накидал в своем коде, НИКАКИХ доп. установок не встречал.

 

Можете по-подробнее объяснить мою недоработку. (если можно, то с кодом)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 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 вывожу какую-нибудь системную частоту, для проверки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 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МГц.

 

Но вот, почему-то, это не работает.

Изменено пользователем billidean
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получается, на периферийной шине у вас 168 / 4 = 42 MHz. Если HSE запустился.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При установке base_timer.TIM_Prescaler = (42-1) и (21-1) получаю тоже неверный результат, светодиод разбегается с часами(секундомером) уже за 10-15 тиков (морганий).

Вы работали с подобной задачей/кодом? или все теория?

(Просто я уже много где потыкался, а результат пока один - тактовая на таймере непонятно-какая и чем определена)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На кварце нагрузочные конденсаторы имеются? Емкость правильная для используемого кварца?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а где вы включаете внешний генератор, подключаете ПЛЛ, ждете стабильного сигнала, и переходите на него?

 

и если мне не изменяет память то в STM надо правильно определить тип вашего устройства, чтобы в огромном могучем файле правильно сработали дефайны, и задалась правильная частота.

 

в свое время надоело с этим убиваться, взял по мануалу правильно настроил клок, шин, проца, и всего. Там 3 флажка, 4 регистра, куда понятнее чем разбираться в 3 экранах дефайнов- передефайнов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно вывести на светодиод бит SWS1 из RCC_CFGR, чтобы удостовериться, что PLL used as the system clock.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а еще не забыть настроить выходную ножку на максимальную частоту, а то на нее хоть клок подавай, а из нее еле еле лезет:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а еще не забыть настроить выходную ножку на максимальную частоту, а то на нее хоть клок подавай, а из нее еле еле лезет:)

Если просто статус выводить, а не частоту, то не надо. :rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в STM надо правильно определить тип вашего устройства, чтобы в огромном могучем файле правильно сработали дефайны, и задалась правильная частота.

- что вы имеете в виду?

При создании проекта я выбирал кристалл, и это, как я предполагаю, и определяет всякие там дефайны.

 

По поводу контроля регистров (RCC_CFGR) - нашел какую-то реализацию printf'a, люди пишут, что работает, вечером попробую запустить. И если все пойдет нормально, то можно будет контролировать все регистры настройки системы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ага добро пожаловать в мир СТМ, не хрена это не определяет.

Посмотрите огромный хедер, там куча ветвей для одного итого же проца в зависимости от серии, того какой плотности это устройство (вроде так это у СТМ) называется. И проверьте правильные ли дефайны у вас стоят. Ставлю на то что стоят по умолчанию, на какой-то массовый проц из серии.... я так пару недель бился об этот файл...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы про stm32f4xx.h-файл?

Там всякие определения/размещения регистров, маски, макросы управления битами.

Так-то по всей линейке (F4) вроде по регистрам должно быть полное соответствие (помнится где-то встречал такую фразу по СТМ).

Изменено пользователем billidean

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...