[英]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.