quatium Napisano Grudzień 9, 2017 Udostępnij Napisano Grudzień 9, 2017 Cześć. Chciałbym zrobić tak, żeby przerwanie generowane z RTC było co sekundę. O ile samo RTC działa (licznik cały czas się zwiększa), to o tyle ani procedura obsługi przerwania nie jest wywoływana, ani flaga SECF w rejestrze RTC_CRL nie jest ustawiana. Na testy w miejsca, które powinny być przetwarzane co sekundę, wstawiłem negację stanu diody na PA5. Do testów używam Nucleo-F103RB (STM32F103RBT6). Kod: #include "stm32f10x.h" uint32_t rtc_count = 0; uint8_t sec, min, hour; uint8_t day, month; uint16_t year; void RTC_IRQHandler(void) __attribute__ ((interrupt)); void RTC_IRQHandler(void) { GPIOA->ODR ^= GPIO_ODR_ODR5; if(RTC->CRL & RTC_CRL_SECF) { rtc_count = (RTC->CNTL | (RTC->CNTH << 16)); //zapisujemy wartosc licznika rtc calendar_update: if(rtc_count > 86399) //jesli minelo 86399 sekund, to uplynal juz conajmniej dzien (urzadzenie moglo lezec wylaczone dlugo) { if((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12)) //jesli miesiac ma 31 dni { if(day < 31) day++; //jesli minelo mniej niz 31 dni, to doliczamy dzien else if(month == 12) //a jesli to byl 31 dzien i grudzien { month = 1; //NOWY ROK! day = 1; year++; } else //a jesli to nie grudzien, ale minal 31 dzien { month++; //nastpeny miesiac day++; } } else if(month == 2) //a jesli to luty { if(day < 28) day++; //i jesli jest przed 28 lutego to dzien nastepny else if(day == 28) //a jesli jest 28 { if((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0))) day++; //jesli to rok przestepny to dzien zwiekszamy else { month++; //a jak nie to nastepny miesiac day = 1; } } else //a jesli to 29 lutego (rok przestepny) { month++; //to nastepny miesiac day = 1; } } else //a jak miesiac ma 30 dni { if(day < 31) //i jesli minal 30 dzien { month++; //nastepny miesiac day = 1; } else day++; //a jak nie minal 30 dzien } } rtc_count -= 86400; //odejmujemy ten dzien z licznika if(rtc_count > 86399) goto calendar_update; //i jesli mimo to w liczniku mamy jeszcze jeden dzien (urzadzenie lezalo dlugo bez uruchomienia), to przetwarzamy i jego hour = rtc_count / 3600; //zapisujemy godzine min = (rtc_count % 3600) / 60; //i minute sec = (rtc_count % 3600) % 60; //i sekunde RTC->CRL |= RTC_CRL_RTOFF; //wlaczamy mozliwosc zapisu do rejestrow RTC RTC->CRL &= ~RTC_CRL_RSF; RTC->CNTL = (rtc_count & 0xFFFF); //zapisujemy pozostale rtc_count while ((RTC->CRL & RTC_CRL_RSF) == 0);; RTC->CRL &= ~RTC_CRL_RSF; RTC->CNTH = (rtc_count & 0xFFFF0000); while ((RTC->CRL & RTC_CRL_RSF) == 0);; RTC->CRL &= ~RTC_CRL_RTOFF; //wylaczamy mozliwosc zapisu do rejestrow RTC PWR->CR |= PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP BKP->DR1 = day; //zapisujemy dzien, rok i miesiac BKP->DR2 = month; BKP->DR3 = year; PWR->CR &= ~PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP RTC->CRL &= ~RTC_CRL_SECF; } } int main(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //zegrad dla GPIOA RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //zegrad dla GPIOA RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //zegar dla GPIOC RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //zegar dla AFIO //RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //zegar dla timera2 //RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //zegar dla usarta2 //RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //zegar dla adc1 //RCC->AHBENR |= RCC_AHBENR_DMA1EN; //zegar dla dma RCC->APB1ENR |= RCC_APB1ENR_PWREN; //zegar dla PWR RCC->APB1ENR |= RCC_APB1ENR_BKPEN; //zegar dla BKP //RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //wlaczamy I2C1 GPIOA->CRL |= GPIO_CRL_MODE5_1; //ustawienie pinu PA5 jako wyjscia push pull 2mhz GPIOA->CRL &= ~GPIO_CRL_MODE5_0; GPIOA->CRL &= ~GPIO_CRL_CNF5; GPIOC->CRL |= GPIO_CRH_CNF13_1; //ustawienie pinu PC13 jako wejscia z podciagnieciem do zasilania GPIOA->CRL |= GPIO_CRL_MODE2_1; //usart2 wyjsce jako push pull GPIOA->CRL &= ~GPIO_CRL_CNF2_0; //usart2 wyjscie jako alternatywna funkcja GPIOA->CRL |= GPIO_CRL_CNF2_1; GPIOA->CRL |= GPIO_CRL_CNF3_0; //usart2 wejsce jako floating GPIOA->CRL &= ~GPIO_CRL_CNF3_1; PWR->CR |= PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP day = BKP->DR1; //odczytujemy ostanie dane kalendarza month = BKP->DR2; year = BKP->DR3; PWR->CR &= ~PWR_CR_DBP; //wylaczamy mozliwosc zapisu do rejestrow BKP if((day == 0) || (month == 0) || (year == 0)) //jesli ktoras z wartosci w kalendarzu jest zerowa to ustawiamy domyslna { day = 1; month = 1; year = 1970; } PWR->CR |= PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP RTC->CRL |= RTC_CRL_CNF; //wchodzimy w tryb konfiguracji RTC RTC->CRL &= ~RTC_CRL_RSF; RCC->BDCR = 0; RCC->BDCR |= RCC_BDCR_LSEON; //i wlaczamy kwarc 32768khz while((RCC->BDCR & RCC_BDCR_LSERDY) == 0);; //czekamy na zainicjowanie LSE 32768khz RCC->BDCR |= RCC_BDCR_RTCSEL_0; //ustwiamy zegar RTC z LSE RCC->BDCR &= ~RCC_BDCR_RTCSEL_1; RCC->BDCR |= RCC_BDCR_RTCEN; //wlaczamy RTC PWR->CR &= ~PWR_CR_DBP; //wylaczamy mozliwosc zapisu do rejestrow BKP while ((RTC->CRL & RTC_CRL_RSF) == 0);; while ((RTC->CRL & RTC_CRL_RTOFF) == 0);; //czekamy, az ostatnia operacja zapisu do RTC zostanie ukonczona RTC->PRLL = 32767; //ustawiamy preskaler zegara RTC while ((RTC->CRL & RTC_CRL_RTOFF) == 0);; //i czekamy, az ostatnia operacja zapisu do RTC zostanie ukonczona RTC->CRH |= RTC_CRH_SECIE; //wlaczamy przerwanie sekundowe while ((RTC->CRL & RTC_CRL_RTOFF) == 0);; //i czekamy, az ostatnia operacja zapisu do RTC zostanie ukonczona RTC->CRL &= ~RTC_CRL_CNF; //wychodzimy z trybu konfiguracji RTC NVIC_EnableIRQ(RTC_IRQn); while(1) { if(RTC->CRL & RTC_CRL_SECF) //tylko na testy, czy pojawia sie chociazby flaga, no i sie nie pojawia { GPIOA->ODR ^= GPIO_ODR_ODR5; RTC->CRL &= ~RTC_CRL_SECF; } } } Z góry dzięki za pomoc. Cytuj Link do komentarza Share on other sites More sharing options...
romkli Czerwiec 5, 2018 Udostępnij Czerwiec 5, 2018 Czesc. Dales rade z tym zegarem? Cytuj Link do komentarza Share on other sites More sharing options...
quatium Czerwiec 5, 2018 Autor tematu Udostępnij Czerwiec 5, 2018 Cześć. Tak, poradziłem sobie z tym w końcu. Problem jest prozaiczny - okazało się, że do edycji rejestrów RTC trzeba też włączyć edycję rejestrów BKP. Linię PWR->CR |= PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP należy przenieść nad linię RTC->CRL |= RTC_CRL_RTOFF; //wlaczamy mozliwosc zapisu do rejestrow RTC i zaczyna działać. Funkcja ma wyglądać tak: void RTC_IRQHandler(void) __attribute__ ((interrupt)); void RTC_IRQHandler(void) { GPIOA->ODR ^= GPIO_ODR_ODR5; if(RTC->CRL & RTC_CRL_SECF) { rtc_count = (RTC->CNTL | (RTC->CNTH << 16)); //zapisujemy wartosc licznika rtc calendar_update: if(rtc_count > 86399) //jesli minelo 86399 sekund, to uplynal juz conajmniej dzien (urzadzenie moglo lezec wylaczone dlugo) { if((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12)) //jesli miesiac ma 31 dni { if(day < 31) day++; //jesli minelo mniej niz 31 dni, to doliczamy dzien else if(month == 12) //a jesli to byl 31 dzien i grudzien { month = 1; //NOWY ROK! day = 1; year++; } else //a jesli to nie grudzien, ale minal 31 dzien { month++; //nastpeny miesiac day++; } } else if(month == 2) //a jesli to luty { if(day < 28) day++; //i jesli jest przed 28 lutego to dzien nastepny else if(day == 28) //a jesli jest 28 { if((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0))) day++; //jesli to rok przestepny to dzien zwiekszamy else { month++; //a jak nie to nastepny miesiac day = 1; } } else //a jesli to 29 lutego (rok przestepny) { month++; //to nastepny miesiac day = 1; } } else //a jak miesiac ma 30 dni { if(day < 31) //i jesli minal 30 dzien { month++; //nastepny miesiac day = 1; } else day++; //a jak nie minal 30 dzien } } rtc_count -= 86400; //odejmujemy ten dzien z licznika if(rtc_count > 86399) goto calendar_update; //i jesli mimo to w liczniku mamy jeszcze jeden dzien (urzadzenie lezalo dlugo bez uruchomienia), to przetwarzamy i jego hour = rtc_count / 3600; //zapisujemy godzine min = (rtc_count % 3600) / 60; //i minute sec = (rtc_count % 3600) % 60; //i sekunde PWR->CR |= PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP RTC->CRL |= RTC_CRL_RTOFF; //wlaczamy mozliwosc zapisu do rejestrow RTC RTC->CRL &= ~RTC_CRL_RSF; RTC->CNTL = (rtc_count & 0xFFFF); //zapisujemy pozostale rtc_count while ((RTC->CRL & RTC_CRL_RSF) == 0);; RTC->CRL &= ~RTC_CRL_RSF; RTC->CNTH = (rtc_count & 0xFFFF0000); while ((RTC->CRL & RTC_CRL_RSF) == 0);; RTC->CRL &= ~RTC_CRL_RTOFF; //wylaczamy mozliwosc zapisu do rejestrow RTC BKP->DR1 = day; //zapisujemy dzien, rok i miesiac BKP->DR2 = month; BKP->DR3 = year; PWR->CR &= ~PWR_CR_DBP; //wlaczamy mozliwosc zapisu do rejestrow BKP RTC->CRL &= ~RTC_CRL_SECF; } } Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!