Witam
Niedawno zacząłem "zabawę" z zestawem Kamami ZL27ARM z procesorem STM32F103VB.
Mam problem z przerwaniem od timera SysTick. Jest ono generowane 4 razy za często - miało być 1 raz na sekundę, a jest 4.
Kwarc 8MHz, SYSCLK = 72MHz, SysTick_CLK= 72/8=9MHz czyli załądowanie do licznika wartości 9'000'000 powinno dać zgłoszenie przerwania co 1s, więc dioda powinna przez sekundę się świecić, i przez nastepną sekundę być zgaszona. Tymczasem dioda zmienia stan co 1/4s.
Program pisany w Keil uVsion 4. W symulatorze czas jest OK (z właczoną opcją "Limit Speed to Real-Time") i przerwanie generowane jest co 1s, ale po załadowaniu do procesora wszystko działa 4 szybciej. Dotyczy to także pętli opoźniających zapalających diody na pinach 8 i 9. Na procesorze zmieniają się mniej więcj co 0.5s, a w symulatorze co 2s.
Sprawdzalem, co jest w rejestrach SystTicka:
Pod adresem 0E000E010 jest wartosc 07 00 00 00 (po skonfigurowaniu) i 07 00 01 00 (po odliczeniu czasu) - czyli OK
Pod adresem 0E000E014 jest wartosc 3F 54 89 00 (czyli 9mln-1, tez OK)
Uzywam standardowego (bez modyfikacji) pliku startup z bibliotek \STM32F10x_StdPeriph_Lib_V3.3.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_md.s
Próbowałem też z niższymi częstotliwościami taktowania rdzenia i objawy są takie same.
Poniżej kod programu:
i jeszcze kod obsługi przerwania z pliku stm32f10x_it.c
Może ktoś ma pomysł o co chodzi? Czy czegoś brakuje?
Niedawno zacząłem "zabawę" z zestawem Kamami ZL27ARM z procesorem STM32F103VB.
Mam problem z przerwaniem od timera SysTick. Jest ono generowane 4 razy za często - miało być 1 raz na sekundę, a jest 4.
Kwarc 8MHz, SYSCLK = 72MHz, SysTick_CLK= 72/8=9MHz czyli załądowanie do licznika wartości 9'000'000 powinno dać zgłoszenie przerwania co 1s, więc dioda powinna przez sekundę się świecić, i przez nastepną sekundę być zgaszona. Tymczasem dioda zmienia stan co 1/4s.
Program pisany w Keil uVsion 4. W symulatorze czas jest OK (z właczoną opcją "Limit Speed to Real-Time") i przerwanie generowane jest co 1s, ale po załadowaniu do procesora wszystko działa 4 szybciej. Dotyczy to także pętli opoźniających zapalających diody na pinach 8 i 9. Na procesorze zmieniają się mniej więcj co 0.5s, a w symulatorze co 2s.
Sprawdzalem, co jest w rejestrach SystTicka:
Pod adresem 0E000E010 jest wartosc 07 00 00 00 (po skonfigurowaniu) i 07 00 01 00 (po odliczeniu czasu) - czyli OK
Pod adresem 0E000E014 jest wartosc 3F 54 89 00 (czyli 9mln-1, tez OK)
Uzywam standardowego (bez modyfikacji) pliku startup z bibliotek \STM32F10x_StdPeriph_Lib_V3.3.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_md.s
Próbowałem też z niższymi częstotliwościami taktowania rdzenia i objawy są takie same.
Poniżej kod programu:
#include "stm32f10x.h"
void GPIO_Configuration(void)
{
//konfigurowanie portow GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void RCC_Configuration(void)
{
//konfigurowanie sygnalow taktujacych
ErrorStatus HSEStartUpStatus;
RCC_DeInit(); //Reset ustawien RCC
RCC_HSEConfig(RCC_HSE_ON); //Wlaczenie HSE
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //Odczekaj az HSE bedzie gotowy
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//
FLASH_SetLatency(FLASH_Latency_2); //ustaw zwloke dla pamieci Flash; zaleznie od taktowania rdzenia
//0:<24MHz; 1:24~48MHz; 2:>48MHz
RCC_HCLKConfig(RCC_SYSCLK_Div1); //ustaw HCLK=SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //ustaw PCLK2=HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //ustaw PCLK1=HCLK/2
//RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9); //ustaw PLLCLK = HSI/2*9 czyli 8MHz/2*9 = 36 MHz
//RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9); //ustaw PLLCLK = HSE/2*9 czyli 8MHz/2*9 = 36 MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //ustaw PLLCLK = HSE*9 czyli 8MHz*9 = 72 MHz
RCC_PLLCmd(ENABLE); //wlacz PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//odczekaj na poprawne uruchomienie PLL
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //ustaw PLL jako zrodlo sygnalu zegarowego
while(RCC_GetSYSCLKSource() != 0x08); //odczekaj az PLL bedzie sygnalem zegarowym systemu
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//wlacz taktowanie portow GPIO A, B i C
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
}
else
{
}
}
void NVIC_Conf(void)
{
//Konfigurowanie kontrolera przerwan NVIC
#ifdef VECT_TAB_RAM
// Jezeli tablica wektorow w RAM, to ustaw jej adres na 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else // VECT_TAB_FLASH
// W przeciwnym wypadku ustaw na 0x08000000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}
int main(void)
{
volatile unsigned long int i;
RCC_Configuration();
NVIC_Conf();
GPIO_Configuration();
GPIO_ResetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
// SysTick bedzie taktowany z f = 72MHz/8 = 9MHz
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
// Przerwanie ma byc co 1s, f = 9MHz / 1, czyli powinno byc 9'000'000 cykli
if (SysTick_Config(9000000ul))
{
while(1); // W razie bledu petla nieskonczona
}
do{
GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);
for(i = 0; i < 0x5B8D80ul; i++); //okolo 0.5s przy 72MHz, na plytce
GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET);
GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_SET);
for(i = 0; i < 0x5B8D80ul; i++);
GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_RESET);
} while(1);
return 0;
}
i jeszcze kod obsługi przerwania z pliku stm32f10x_it.c
void SysTick_Handler(void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_10)));
}
Może ktoś ma pomysł o co chodzi? Czy czegoś brakuje?