// A) vliv frekvence na odběr #include "stm32f0xx.h" // výstupy pro LEDku #define TEST_H GPIOA->BSRR = GPIO_Pin_5 #define TEST_L GPIOA->BRR = GPIO_Pin_5 void _delay_ms(uint32_t Delay); void init_test_output(void); void pull_unused_gpio(void); void init_exti(void); void clock_48(void); void clock_8(void); void clock_1(void); void clock_31k(void); volatile uint8_t irq_flag=0; // vlajka idnikující potřebu bliknout LEDkou int main(void){ //clock_48(); //clock_8(); clock_1(); // clock například 1MHz //clock_31k(); pull_unused_gpio(); // ošetřit nepoužité GPIO init_test_output(); // výstup na LEDku init_exti(); // přerušení od PA0 while (1){ if(irq_flag){ // pokud došlo ke stisku, blikni LEDkou TEST_H; _delay_ms(500); TEST_L; irq_flag=0; } } } // EXTI z PA0 bude sloužit k buzení z režimů spánku // Na PA0 připojeno tlačítko proti VCC (interní pull down) void init_exti(void){ EXTI_InitTypeDef exti; NVIC_InitTypeDef nvic; GPIO_InitTypeDef gp; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // kvůli PA0 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // kvůli EXTI // PA0 jako vstup s pull-down gp.GPIO_Pin = GPIO_Pin_0; gp.GPIO_Mode = GPIO_Mode_IN; gp.GPIO_OType = GPIO_OType_PP; gp.GPIO_PuPd = GPIO_PuPd_DOWN; gp.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(GPIOA, &gp); // Přiřadíme Lince 0 port GPIOA (tedy mapujeme pin PA0) SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0); // povolíme externí přerušení z Linky 0 na vzestupnou hranu exti.EXTI_Line = EXTI_Line0; exti.EXTI_Mode=EXTI_Mode_Interrupt; exti.EXTI_Trigger=EXTI_Trigger_Rising; exti.EXTI_LineCmd=ENABLE; EXTI_Init(&exti); // povolíme externí přerušení (Linky 0) v NVIC nvic.NVIC_IRQChannel=EXTI0_1_IRQn; nvic.NVIC_IRQChannelPriority=3; nvic.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&nvic); } // Rutina přerušení od EXTI jen nastaví "vlajku" podle které v mainu blikneme LEDkou void EXTI0_1_IRQHandler(void){ if(EXTI_GetITStatus(EXTI_Line0)){ EXTI_ClearITPendingBit(EXTI_Line0); irq_flag = 1; } } // PA5 je indikační výstup (k ověření že čip žije a pracuje) void init_test_output(void){ GPIO_InitTypeDef gp; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); gp.GPIO_Pin = GPIO_Pin_5; gp.GPIO_Mode = GPIO_Mode_OUT; gp.GPIO_OType = GPIO_OType_PP; gp.GPIO_PuPd = GPIO_PuPd_NOPULL; gp.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(GPIOA, &gp); } void pull_unused_gpio(void){ GPIO_InitTypeDef gp; // nastavíme všem pinům že jsou to vstupy s pull-down rezistorem // ponecháme si jen konfiguraci pinů SWD, které mají interní pullup/pulldown rezistory // na našem čipu jsou jen GPIOA,GPIOB a GPIOF RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOF, ENABLE); gp.GPIO_Pin = GPIO_Pin_All; gp.GPIO_Mode = GPIO_Mode_IN; gp.GPIO_OType = GPIO_OType_PP; gp.GPIO_PuPd = GPIO_PuPd_DOWN; gp.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(GPIOB, &gp); GPIO_Init(GPIOF, &gp); gp.GPIO_Pin = GPIO_Pin_All & (~(GPIO_Pin_13 | GPIO_Pin_14)); // vše krom PA13 a PA14 (SWD) GPIO_Init(GPIOA, &gp); // nezapomeneme vypnout clock ;) RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOF, DISABLE); } void clock_48(void){ RCC_PLLConfig(RCC_PLLSource_HSI,RCC_PLLMul_12); // nastavit PLL na násobení 12x (8MHz / 2 * 12 = 48MHz) RCC_PLLCmd(ENABLE); // spustit PLL while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET); // počkat na rozběh PLL RCC_HCLKConfig(RCC_SYSCLK_Div1); // SYSCLK z PLL nijak nedělit RCC_PCLKConfig(RCC_HCLK_Div1); // HCLK ze SYSCLK nijak nedělit (jedeme naplno) RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // přepnout SYSCLK na PLL (jedeme na 48MHz) //SystemCoreClockUpdate(); // 0.14kB zbytečně... SystemCoreClock = 48000000; // clock je 48MHz } void clock_8(void){ RCC_HCLKConfig(RCC_SYSCLK_Div1); // SYSCLK nijak nedělit RCC_PCLKConfig(RCC_HCLK_Div1); // HCLK ze SYSCLK nijak nedělit (periferiím stejný takt jako jádru) RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); // zdrojem clocku je 8MHz HSI SystemCoreClock = 8000000; // clock je 8MHz } void clock_1(void){ RCC_HCLKConfig(RCC_SYSCLK_Div8); // SYSCLK dělit 8 => jádro jede na 1MHz... RCC_PCLKConfig(RCC_HCLK_Div1); // ...periferiím stejný takt jako jádru RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); // zdrojem clocku je 8MHz HSI SystemCoreClock = 1000000; // clock je 1MHz } void clock_31k(void){ RCC_HCLKConfig(RCC_SYSCLK_Div256); // SYSCLK dělit 256 => jádro jede na 31.25kHz... RCC_PCLKConfig(RCC_HCLK_Div1); // ...periferiím stejný takt jako jádru RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); // zdrojem clocku je 8MHz HSI SystemCoreClock = 31250; // clock je 31.25kHz } // Delay na bázi systicku (vyžaduje korektní nastavení SystemCoreClock) void _delay_ms(uint32_t Delay){ __IO uint32_t tmp = SysTick->CTRL; // Clear the COUNTFLAG first ((void)tmp); // init systick to us delays ... SysTick->LOAD = (SystemCoreClock/1000)-1; // 1us time SysTick->VAL = 0UL; SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; if(Delay < 0xffffff){Delay++;} // Add a period to guaranty minimum wait while (Delay){ if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U){Delay--;} } }