简体   繁体   English

STM32F4发现系统时钟配置

[英]STM32F4 Discovery the system clock configuration

I have to configure system clock on my STM32F4 Discovery board and I cannot get it right. 我必须在STM32F4 Discovery板上配置系统时钟,但无法正确设置。 I used "System clock configuraction" program from STM website ( http://www.st.com/web/en/catalog/tools/PF257927# ). 我使用了STM网站( http://www.st.com/web/en/catalog/tools/PF257927# )上的“系统时钟配置”程序。 I've set HCKL to 168 and generated source file with PPL(HSI) option and pasted it to my project, calling generated SystemInit() function. 我已将HCKL设置为168,并使用PPL(HSI)选项生成了源文件,并将其粘贴到我的项目中,调用了生成的SystemInit()函数。 The generated source file in comments at its top indicates that ABP1 prescaler is set to 4. I've created a timer that should interrupt my program once a second: 生成的源文件在其顶部的注释中指示ABP1预分频器设置为4。我创建了一个计时器,该计时器应每秒中断我的程序一次:

NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

TIM_InitStructure.TIM_Period = 168000000 / 4; // clockspeed/prescaler
TIM_InitStructure.TIM_Prescaler = 0;
TIM_InitStructure.TIM_ClockDivision = 0;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_InitStructure);
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM5, ENABLE);

However my TIM5_IRQHandler seems to be called every 0,5 second. 但是,我的TIM5_IRQHandler似乎每0.5秒调用一次。 Why is that? 这是为什么? Am I doing something wrong or am I misunderstanding something? 我做错了什么还是误解了?

Here is some code I wrote for that board that uses the pll at 168Mhz and the timer and interrupt (blah). 这是我为使用168Mhz的pll以及计时器和中断(blah)的开发板编写的一些代码。 See if/how it compares to yours, I dont use their library 看看它是否与您的相比,我不使用他们的图书馆

I highly recommend you start by polling first, get the system clock and timer configured one at thing at a time then get the interrupt as close to the core, clearing correctly, etc and the last step is to do an interrupt and handler. 我强烈建议您首先轮询,一次配置一个系统时钟和计时器,然后使中断尽可能靠近内核,正确清除等,最后一步是执行中断和处理程序。

//-------------------------------------------------------------------
void PUT32 ( unsigned int, unsigned int );
void PUT16 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
unsigned int GET16 ( unsigned int );
//-------------------------------------------------------------------
#define RCCBASE   0x40023800
#define RCC_CR    (RCCBASE+0x00)
#define RCC_PLLCFGR (RCCBASE+0x04)
#define RCC_CFGR  (RCCBASE+0x08)
#define GPIODBASE 0x40020C00
#define TIM5BASE  0x40000C00
#define FLASH_ACR  0x40023C00
//-------------------------------------------------------------------
volatile unsigned int intcounter;
//-------------------------------------------------------------------
// CAREFUL, THIS IS AN INTERRUPT HANDLER
void tim5_handler ( void )
{
    intcounter++;
    PUT32(TIM5BASE+0x10,0x00000000);
}
// CAREFUL, THIS IS AN INTERRUPT HANDLER
//-------------------------------------------------------------------
void ClockInit ( void )
{
    unsigned int ra;

    //enable HSE
    ra=GET32(RCC_CR);
    ra&=~(0xF<<16);
    PUT32(RCC_CR,ra);
    ra|=1<<16;
    PUT32(RCC_CR,ra);
    while(1)
    {
        if(GET32(RCC_CR)&(1<<17)) break;
    }
    PUT32(RCC_CFGR,0x00009401); //PPRE2 /2 PPRE1 /4 sw=hse

    //slow flash accesses down otherwise it will crash
    PUT32(FLASH_ACR,0x00000105);

    //8MHz HSE, 168MHz pllgen 48MHz pll usb
    //Q 7 P 2 N 210 M 5 vcoin 1 pllvco 336 pllgen 168 pllusb 48
    ra=(7<<24)|(1<<22)|(((2>>1)-1)<<16)|(210<<6)|(5<<0);
    PUT32(RCC_PLLCFGR,ra);

    // enable pll
    ra=GET32(RCC_CR);
    ra|=(1<<24);
    PUT32(RCC_CR,ra);

    //wait for pll lock
    while(1)
    {
        if(GET32(RCC_CR)&(1<<25)) break;
    }

    //select pll
    PUT32(RCC_CFGR,0x00009402); //PPRE2 /2 PPRE1 /4 sw=pllclk

    //if you didnt set the flash wait states you may crash here

    //wait for it to use the pll
    while(1)
    {
        if((GET32(RCC_CFGR)&0xC)==0x8) break;
    }
}
//-------------------------------------------------------------------
int notmain ( void )
{
    unsigned int ra;
    unsigned int lastcount;
    unsigned int newcount;

    ClockInit();

    ra=GET32(RCCBASE+0x30);
    ra|=1<<3; //enable port D
    PUT32(RCCBASE+0x30,ra);

    ra=GET32(RCCBASE+0x40);
    ra|=1<<3; //enable TIM5
    PUT32(RCCBASE+0x40,ra);

    //d12 = d15 led outputs
    ra=GET32(GPIODBASE+0x00);
    ra&=0x00FFFFFF;
    ra|=0x55000000;
    PUT32(GPIODBASE+0x00,ra);
    //push pull
    ra=GET32(GPIODBASE+0x04);
    ra&=0xFFFF0FFF;
    PUT32(GPIODBASE+0x04,ra);

    //start with green led
    PUT32(GPIODBASE+0x18,0xE0001000);

    //setup timer
    PUT32(TIM5BASE+0x00,0x00000000);
    PUT32(TIM5BASE+0x2C,168000000/4); //auto reload
    PUT32(TIM5BASE+0x0C,0x00000001); //interrupt enable
    PUT32(TIM5BASE+0x10,0x00000000); //clear interrupt
    PUT32(TIM5BASE+0x00,0x00000001);

    intcounter = 0;
    //enable interrupt 50 TIM5
    PUT32(0xE000E104,0x00040000);

    lastcount = intcounter;
    while(1)
    {
        newcount=intcounter;
        if(lastcount!=newcount)
        {
            switch(lastcount&0x3)
            {
                case 0: PUT32(GPIODBASE+0x18,0xE0001000); break;
                case 1: PUT32(GPIODBASE+0x18,0xD0002000); break;
                case 2: PUT32(GPIODBASE+0x18,0xB0004000); break;
                case 3: PUT32(GPIODBASE+0x18,0x70008000); break;
            }
            lastcount=newcount;
        }
    }
    return(0);
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------

Some notes I wrote about what I saw at the time: 我写了一些关于当时所见内容的注释:

TIM5 is actually a 32 bit counter not 16 like many of the others. TIM5实际上是一个32位计数器,而不是其他许多计数器中的16位。 If we count to 168,000,000 * 4 ticks that should be 4 seconds right? 如果算上168,000,000 * 4个滴答,那应该是4秒吧? Well we get 8 seconds per led blink. 好吧,每LED闪烁我们会得到8秒。 I think what is going on is there are two AHB divisors PPRE1 and PPRE2 with different speed limits. 我认为这是怎么回事,有两个AHB除数PPRE1和PPRE2具有不同的速度限制。 To keep PPRE2 at or under 84Mhz it wants a divide by 2, to keep PPRE1 under 42MHz it wants a divide by 4. The clock tree diagram doesnt really show these two divisors (that I can see) but it has a thing for the timers where if divisor is non-zero then multiply by 2. I assume what this all means is PPRE1 which is a divide by 4 is multiplied by 2 to feed the timers. 为了将PPRE2保持在84Mhz或以下,它希望将其除以2,将PPRE1保持在42MHz以下,它希望将其除以4。其中,如果除数不为零,则乘以2。我假设这意味着PPRE1,即被4除的PPRE1乘以2以提供计时器。 And that appears to match, if you change PPRE1 to divide by 8 and the it takes 16 seconds for the led to change. 这似乎匹配,如果将PPRE1更改为8分频,则led更改需要16秒。

So I saw it being too long, you are seeing it be too short by a power of 2? 所以我看到它太长了,您看到它太短了2的幂吗? I am using the external source you are using internal? 我正在使用外部源,而您正在使用内部源?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM