реклама на сайте
подробности

 
 
> STM32F4::Discovery -> Помогите с таймером, Что-то с тактовой для TIM6
billidean
сообщение Feb 12 2014, 13:45
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



Здравствуйте.
Хочу заставить светодиод мигать с тактом 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 сек, но "ПОЧТИ"=чуть-чуть быстрее.

В чем может быть моя неправда? Ткните носом, ПЛЗ. Или объясните матчасть (может все так и должно быть 05.gif ).

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

Сообщение отредактировал IgorKossak - Feb 12 2014, 14:29
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3 >  
Start new topic
Ответов (15 - 29)
Golikov A.
сообщение Feb 13 2014, 06:50
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ага про него. Посмотрите какой проц в итоге определен, посмотрите сходиться ли это с вашим процом (смотрите все, там участвует и размер флэши и все), а заодно чем равны делители выставляющие частоту.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 13 2014, 06:53
Сообщение #17


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Да, есть полное соответствие. Ничего больше определять не надо. Разве что частоту резонатора.
А что, на светодиод вывести, что я предложил, не катит? printf - это здорово, но сложнее, чем таймер запустить.
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 07:10
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



Цитата(ViKo @ Feb 13 2014, 10:53) *
Да, есть полное соответствие. Ничего больше определять не надо. Разве что частоту резонатора.
А что, на светодиод вывести, что я предложил, не катит? printf - это здорово, но сложнее, чем таймер запустить.

И светодиод задействую, по-необходимости, но это всё все-равно будет только вечером, дома. А пока на работе есть время поразбирать/подготовить какие-либо коды, в том числе и использование printf'a (он потом все-таки пригодится, и чем быстрее я его зпущу, тем проще будет дальнейшая жизнь и отладка).

По настройкам:
Код
#if !defined  (HSE_VALUE)
/**
* @brief In the following line adjust the value of External High Speed oscillator (HSE)
   used in your application
  
   Tip: To avoid modifying this file each time you need to use different HSE, you
        can define the HSE value in your toolchain compiler preprocessor.
  */          

  #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

/**
* @brief In the following line adjust the External High Speed oscillator (HSE) Startup
   Timeout value
   */
#if !defined  (HSE_STARTUP_TIMEOUT)
  #define HSE_STARTUP_TIMEOUT    ((uint16_t)0x0500)   /*!< Time out for HSE start up */
#endif /* HSE_STARTUP_TIMEOUT */  

#if !defined  (HSI_VALUE)  
  #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */

Здесь 25000000 нужно заменить на 8000000 (внешний кварц 8МГц вроде стоит).
HSE_STARTUP_TIMEOUT - менять думаю не стоит.
А вот почему на "заводе" HSI_VALUE 16000000 поставили, это мне не понятно, вроде для этих кристаллов должна быть внутренняя частота 8МГц, или я ошибаюсь??
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 13 2014, 07:30
Сообщение #19


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(billidean @ Feb 13 2014, 10:10) *
А вот почему на "заводе" HSI_VALUE 16000000 поставили, это мне не понятно, вроде для этих кристаллов должна быть внутренняя частота 8МГц, или я ошибаюсь??

В руководстве на F40x показана частота 16000000 MHz.
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 08:06
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



Цитата(ViKo @ Feb 13 2014, 11:30) *
В руководстве на F40x показана частота 16000000 MHz.

Да, нашел это место, спасибо. Тогда получается, что при НЕвызове функции SystemInit() таймер_6 тактируется просто внутренней частотой, а не удвоенной (где-то это вычитал в инете и оказалось, что это обман).
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 13 2014, 08:35
Сообщение #21


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(billidean @ Feb 13 2014, 11:06) *
Да, нашел это место, спасибо. Тогда получается, что при НЕвызове функции SystemInit() таймер_6 тактируется просто внутренней частотой, а не удвоенной (где-то это вычитал в инете и оказалось, что это обман).

Не совсем...
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 08:59
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



Кстати, нашел еще один параметр, который надо поменять под свой внешний кварц:
#define PLL_M 25, нужно сделать 8.

Цитата(ViKo @ Feb 13 2014, 12:35) *
Не совсем...

Так, немного подсоберу все в одну картину:
1. В функции SystemInit() происходит настройка частот системы и PLL на 168МГц(при работе с внешним кварцем), при условии установки правильных дефайнов (HSE_VALUE, PLL_M, и может еще каких..).
2. Если в настройках PLL параметр prescaler не равен 1, то таймеры (на шинах APBx) тактируются удвоенной частотой, иначе НЕудвоенной(прямой).
3. В случае, если мы не используем функцию SystemInit(), то мы не запускаем PLL (если, конечно, отдельно не прописали этот запуск), и следовательно: частота у нас используется внутренняя (16МГц), а таймеры тактируются тоже этой же частотой 16МГц (не удвоенной, т.к. PLL-prescaler в коде не был установлен).

Я правильно рассуждаю?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 13 2014, 09:09
Сообщение #23


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(billidean @ Feb 13 2014, 11:59) *
Я правильно рассуждаю?

К PLL прескалеры периферийных шин не имеют отношения. В остальном - правильно.

Хороший пример того, что использование библиотечных функций не дает понимания работы узлов микроконтроллера.
Нужно открыть Руководство, и медленно водя мышой по битам регистров, осознать их магическое влияние на то или иное... rolleyes.gif
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 09:27
Сообщение #24


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



...да... вместо PLL-prescaler нужно понимать prescaler для шин (АРВ1 и АРВ2), которые задаются в RCC->CFGR.

UPD: спасибо за помощь.

Сейчас занимаюсь переводом главы USB on-the-go full-speed (OTG_FS) из Референса, Никто не встречал уже переведенной версии(?), иначе жалко будет потраченного времени.
Если перевод не найдется, то постараюсь аккуратно оформить и выложить в сеть.

Сообщение отредактировал billidean - Feb 13 2014, 09:25
Go to the top of the page
 
+Quote Post
topkin
сообщение Feb 13 2014, 10:17
Сообщение #25


Частый гость
**

Группа: Свой
Сообщений: 152
Регистрация: 21-12-05
Из: Москва
Пользователь №: 12 476



Конфигурация тактовой частоты и первоначальных настроек происходит в файле system_stm32f4xx.c, функция SystemInit().
Поищите на сайте такую тулзу STM32F4xx_Clock_Configuration_V1.0.1.xls. Это эксель файл, где вы набором галочек конфигурируйте схему тактирования и вам автоматически генерируется файл system_stm32f4xx.c. Добавляете его в свой проект и все будет работать.

P.S. Ссылку дать не могу, поищите на сайте ST
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 13 2014, 10:32
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



а откуда берется двойная частота без PLL? это скорее единичная и половинная...

и второй вопрос, а нафига переводить? Вы что ее со словарем переводите? Читать сразу на английском не катит? Не конечно здорово когда она есть в русском варианте, все вам спасибо скажут, но столько времени терять....
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 10:46
Сообщение #27


Местный
***

Группа: Свой
Сообщений: 247
Регистрация: 4-10-10
Из: г. Екатеринбург
Пользователь №: 59 925



Цитата(Golikov A. @ Feb 13 2014, 13:32) *
а откуда берется двойная частота без PLL? это скорее единичная и половинная...

см.:
Цитата
3. В случае, если мы не используем функцию SystemInit(), то мы не запускаем PLL (если, конечно, отдельно не прописали этот запуск), и следовательно: частота у нас используется внутренняя (16МГц), а таймеры тактируются тоже этой же частотой 16МГц (не удвоенной, т.к. PLL-prescaler в коде не был установлен).

Цитата(Golikov A. @ Feb 13 2014, 13:32) *
и второй вопрос, а нафига переводить? Вы что ее со словарем переводите? Читать сразу на английском не катит? Не конечно здорово когда она есть в русском варианте, все вам спасибо скажут, но столько времени терять....
- дабы иметь под рукой русскую версию при начальной работе над USB (я еще не реализовывал этот интерфейс на СТМ), да и помочь другим начинающим.

Сообщение отредактировал billidean - Feb 13 2014, 10:49
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 13 2014, 11:08
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



я просто пытался обратить ваше внимание на то что x1 x2 - это значение prescaller, то есть пред делителя, это разделить на 1 или на 2 частоту, а не умножить...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 13 2014, 11:59
Сообщение #29


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Golikov A. @ Feb 13 2014, 14:08) *
я просто пытался обратить ваше внимание на то что x1 x2 - это значение prescaller, то есть пред делителя, это разделить на 1 или на 2 частоту, а не умножить...

Нет, это "умножить". Это для простоты показано. На самом деле, надо думать, при x2 подается удвоенная частота, с PLL (которая работает, для максимальной рабочей, на удвоенной 168 MHz, а не на 168 MHz). Может, я нафантазировал... может, просто не делится на 2, 4, 8 после прескалера, а делится на 1, 2, 4.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 13 2014, 12:15
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



ну типа того, в общем периферия системную частоту не обгонитsm.gif
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 2nd September 2025 - 05:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.02389 секунд с 7
ELECTRONIX ©2004-2016