简体   繁体   中英

STM32F4 Discovery the system clock configuration

I have to configure system clock on my STM32F4 Discovery board and I cannot get it right. I used "System clock configuraction" program from STM website ( 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. 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:

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. 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). 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. If we count to 168,000,000 * 4 ticks that should be 4 seconds right? Well we get 8 seconds per led blink. I think what is going on is there are two AHB divisors PPRE1 and PPRE2 with different speed limits. 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. And that appears to match, if you change PPRE1 to divide by 8 and the it takes 16 seconds for the led to change.

So I saw it being too long, you are seeing it be too short by a power of 2? I am using the external source you are using internal?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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