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

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> STM32F4::Discovery -> Помогите с таймером, Что-то с тактовой для TIM6
billidean
сообщение Feb 13 2014, 14:00
Сообщение #31


Местный
***

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



Тут нарыл в даташите:
Прикрепленное изображение

- это к вопросу удвоения частоты тактирования таймеров.
А в Референсе нашел следующее:
Прикрепленное изображение

, но это только для STM32F42/43хх.
Значит в моем случае (STM32F407) на таймеры поступает прямая частота с PLL (не умноженная).

Здесь еще один "прикол": при установках "RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;" и "RCC->CFGR |= RCC_CFGR_PPRE1_DIV1;" таймеры тикают с одинаковой частотой. В описании регистра RCC->CFGR сказано:
Прикрепленное изображение

При:
#define RCC_CFGR_PPRE1_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */
#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00001000) /*!< HCLK divided by 2 */

тиканье должно отличаться в два раза.

Чота с этими таймерами/тактовыми ваще х.. какая-то. И эту хрень нужно постоянно таскать с собой в голове при написании кода wacko.gif .

Сообщение отредактировал billidean - Feb 13 2014, 14:02
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 13 2014, 15:46
Сообщение #32


Гуру
******

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



забудьте вы про умножение частоты)... нет его там, есть недоделение, то есть если вы на шину перифирии подадите клок с плл/2, то на таймеры придет просто клок с ПЛЛ, если клок/4, то на таймерах будет клок/2, а если подадите просто клок с плл, то так и будет, умножить там ничто частоту не может.


а вы уверены что от того таймера и от того домена флаги крутитеsm.gif?
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 13 2014, 15:52
Сообщение #33


Местный
***

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



Цитата(Golikov A. @ Feb 13 2014, 18:46) *
забудьте вы про умножение частоты)... нет его там, есть недоделение, то есть если вы на шину перифирии подадите клок с плл/2, то на таймеры придет просто клок с ПЛЛ, если клок/4, то на таймерах будет клок/2, а если подадите просто клок с плл, то так и будет, умножить там ничто частоту не может.

я об этом и говорю, что без деления и при делении на 2 - получаем тактовую на таймер одинаковую.

Цитата(Golikov A. @ Feb 13 2014, 18:46) *
а вы уверены что от того таймера и от того домена флаги крутитеsm.gif?

- конечно. Если я поставлю "RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;", то частота падает вдвое.

З.Ы.: Блин.. хоть немного понятно стало.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 13 2014, 16:10
Сообщение #34


Гуру
******

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



не очень понятно падает она теперь или нет, но если стало немного понятно, то хорошо....

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


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

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



Мне кажется с самого начала, что кварцевый генератор не включился.
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 14 2014, 04:30
Сообщение #36


Местный
***

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



Цитата(Golikov A. @ Feb 13 2014, 19:10) *
не очень понятно падает она теперь или нет, но если стало немного понятно, то хорошо....
- здесь я опечатался:
Цитата
Если я поставлю "RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;", то частота падает вдвое.
- здесь вместо RCC_CFGR_PPRE1_DIV2 следует писать RCC_CFGR_PPRE1_DIV4.
Т.е. если устанавливаем RCC_CFGR_PPRE1_DIV1 или RCC_CFGR_PPRE1_DIV2, то частота, поступающая на таймер, не делится, а при RCC_CFGR_PPRE1_DIV4 - частота делится на 2, при RCC_CFGR_PPRE1_DIV8 - на 4, при RCC_CFGR_PPRE1_DIV16 - на 8.
Т.е. высказывание:
Цитата(Golikov A. @ Feb 13 2014, 18:46) *
забудьте вы про умножение частоты)... нет его там, есть недоделение, то есть если вы на шину перифирии подадите клок с плл/2, то на таймеры придет просто клок с ПЛЛ, если клок/4, то на таймерах будет клок/2, а если подадите просто клок с плл, то так и будет, умножить там ничто частоту не может.
- считаю точным описанием поведения определения частот тактирования таймеров.

По поводу максимальных частот таймеров нашел таблицу:
Прикрепленное изображение


Цитата(Golikov A. @ Feb 13 2014, 19:10) *
еще хорошим тоном перед |= является снять все прошлые флаги, ибо если какие то уже стоят может ничего и не произойти или произойти не то что хотели. А в вашем случае я так понимаю у вас много инициализаций что делают библиотечные функции, которые вы просматривать не стали.
- сброс всех установочных регистров выполняется в функции SystemInit() - сначала все сбросы, а затем вызов функции SetSysClock(), которая уже и устанавливает частоты.
Пока я не пишу свою функцию инициализации, а пытаюсь разобрать библиотечные, чтобы потом уже составить свою.

Сообщение отредактировал billidean - Feb 14 2014, 06:43
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 14 2014, 06:58
Сообщение #37


Местный
***

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



А теперь самое ИНТЕРЕСНОЕ:
Вот код моей программки:
Код
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"

#include "xprintf/xprintf.h"

#define TimerTick      (SystemCoreClock/1000-1)    // Получим 1 килогерц

int counter = 0;
int flag = 0;

// SysTick Interrupt Handler
//void SysTick_Handler(void)
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
   * не имеют смысла для базовых таймеров.
   */

    TIM_TimeBaseInitTypeDef base_timer;
//    TIM_TimeBaseStructInit(&base_timer);
  /* Делитель учитывается как TIM_Prescaler + 1, поэтому отнимаем 1 */
//    base_timer.TIM_Prescaler = 16 - 1; // 16MHz/16 = 1000KHz
//    base_timer.TIM_Prescaler = 168 - 1; // (168)MHz/168 = 1000KHz (168/RCC_CFGR_PPRE1_DIV1-freq from PLL (1/1) for APB1)
//    base_timer.TIM_Prescaler = 84 - 1; // (84)MHz/84 = 1000KHz (168/RCC_CFGR_PPRE1_DIV4-freq from PLL (1/2) for APB1)
    base_timer.TIM_Prescaler = 42 - 1; // (42)MHz/42 = 1000KHz (168/RCC_CFGR_PPRE1_DIV8-freq from PLL (1/4) for APB1)
    base_timer.TIM_Period = 1000-1; //период 1000 тактов == получим прерывания через 1мс (1KHz)
    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);
    //**********************************************

    xprintf("dv\n");

    while(1)
    {
        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;
        }
    }
}

Вот настройки моей системы:
Код
#if !defined  (HSE_VALUE)
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
...
/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8
#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2


Система каждую 1 секунду переключает состояние светодиода (горит/НЕгорит) (проверялось на плате STM32F4-Discovery).
Обратим внимание на строки:
Код
//    base_timer.TIM_Prescaler = 16 - 1; // (16)MHz/16 = 1000KHz (16MHz - internal clock without SystemInit()-function)
//    base_timer.TIM_Prescaler = 168 - 1; // (168)MHz/168 = 1000KHz (168/RCC_CFGR_PPRE1_DIV1-freq from PLL (1/1) for APB1)
//    base_timer.TIM_Prescaler = 84 - 1; // (84)MHz/84 = 1000KHz (168/RCC_CFGR_PPRE1_DIV4-freq from PLL (1/2) for APB1)
    base_timer.TIM_Prescaler = 42 - 1; // (42)MHz/42 = 1000KHz (168/RCC_CFGR_PPRE1_DIV8-freq from PLL (1/4) for APB1)
    base_timer.TIM_Period = 1000-1; //период 1000 тактов == получим прерывания через 1мс (1KHz)

Т.е. при использовании параметра для PLL - prescale=RCC_CFGR_PPRE1_DIV1, таймер (TIM6) тактируется частотой 168МГц, что СОВСЕМ НЕ СООТВЕТСТВУЕТ приведенной выше таблице (из официального документа-DataSheet на кристалл).

Как эту всю байду с тактированием таймеров (конкретно - для TIM6) понять??? wacko.gif

Сообщение отредактировал billidean - Feb 14 2014, 06:59
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 14 2014, 07:18
Сообщение #38


Гуру
******

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



тут есть хитрость в мануале написано что типа вас никто не будет контролировать чтобы вы не подали больше чем можно.
Таймер 6 может работать максимум от частоты 84, и вы обязаны так задать делители чтобы эту частоты не превысить. Подавая на него 168 вы получаете не стабильную работу, иногда это не заметно, иногда будет сбоить. За 84 они отвечают, а за 168 нет.


Вот и настраивайте правильно! как то так...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 14 2014, 07:40
Сообщение #39


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

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



Назовем, bb-offtopic.gif
Из жизни. Женщина установила спираль, чтобы не беременеть. Практика распространенная, интимная... Муж недоволен:
- Что-то колется!
- Никому не колется, а тебе колется!

Это я к тому, что случай ТС выглядит уникальным явлением природы на фоне всеобщей благодати. Что же никому другому "не колется"?
Go to the top of the page
 
+Quote Post
billidean
сообщение Feb 14 2014, 07:49
Сообщение #40


Местный
***

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



Цитата
тут есть хитрость..

Вы вот это имеете в виду (выделенная строчка):
Прикрепленное изображение

из настроек регистра RCC_CFGR?

Цитата
Что же никому другому "не колется"?

просто я решил раскопать и расставить все точки над этими мутными "и". А все может быть просто потыкались/понастраивали_как-то свои девайсы да и проглотили эту непонятку, успокоив себя: "не знаю почему, но тактовая у меня вот такая..".
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Feb 14 2014, 08:00
Сообщение #41


Гуру
******

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



ну да.
все вам и написали
на домен не может быть больше 42, как мы помним из других картинок что таймер может работать от двойной тактовой домена, то есть 84. Вот и все загадки - отгадки.


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

После этого проверил осцилом что все частоты заработали как надо, и дальше все таймеры автоматом по расчетным значениям затикали.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 14 2014, 08:00
Сообщение #42


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

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



Цитата(billidean @ Feb 14 2014, 10:49) *
просто я решил раскопать и расставить все точки над этими мутными "и".

Вот это правильный путь! Уверен, что докопавшись, вы убедитесь, что в STM32F4 все логично. Чего не могу сказать о библиотечных функциях. Но и они работают.
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 Текстовая версия Сейчас: 18th July 2025 - 12:44
Рейтинг@Mail.ru


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