ЛеонидК 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Нужно добавить часы в проект на STM32. Использую библиотеки ST и пример RTCCalendar. При инициализации на RTC_WaitForLastTask() программа виснет. В пошаговом режиме чаще проходит. Может кто подскажет в чем может быть проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ashr 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Делал часы реального времени на основе примеров от ST. Все четко работает. Так что код в студию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ЛеонидК 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 (изменено) · Жалоба void RTC_Config(void) { u16 WaitForOscSource; if (BKP_ReadBackupRegister(BKP_DR1) != CONF_DONE) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_DeInit(); RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); DateVar.Month = DEFAULT_MOUNT; DateVar.Day = DEFAULT_DAY; DateVar.Year = DEFAULT_YEAR; TimeVar.Sec = DEFAULT_SEC; TimeVar.Min = DEFAULT_MIN; TimeVar.Hour = DEFAULT_HOUR; SummerTimeCorrect =OCTOBER_FLAG_SET; BKP_WriteBackupRegister(BKP_DR1,CONF_DONE); RTC_DataWrite(); } else { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); } } Изменено 13 октября, 2011 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба А кварц часовой имеется? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ЛеонидК 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба И питание тоже включал. Правда конденсаторы 9,1 пФ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Проверьте часовой кварц. Резонит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ЛеонидК 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Да Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Да Тогда может Вам стоит проверить конкретно биты в регистрах, почему не устанавливаються флаги? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zksystem 0 21 ноября, 2010 Опубликовано 21 ноября, 2010 · Жалоба Использую библиотеки ST и пример RTCCalendar. При инициализации на RTC_WaitForLastTask() программа виснет. В пошаговом режиме чаще проходит. Может кто подскажет в чем может быть проблема. Генератор часов раскачивается полминуты в моем случае, потом, после первой инициализации все нормально, пока батарейку не выдернешь. Советую посмотреть, правильные ли нагрузочные емкости к Вашему кварцу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ashr 0 22 ноября, 2010 Опубликовано 22 ноября, 2010 · Жалоба void RTC_Config(void) {...} Что-то здесь не так с последовательностью инициализации (хотя вдумчиво не смотрел). Посмотрите как у меня сделано. //****************************************************************************** // RTC_DRV_CPP // DESCRIPTION: // Драйвер аппаратного RTC. // При совпадении текущего времени с заданными временами, // вызывается пользовательский обработчик (из прерывания). // //****************************************************************************** #include "rtc_drv.h" #include "platform_config.h" #include "stm32f10x.h" #include "helper.h" //------------------------------------------------------------------------------ // T Y P E S and D E F I N I T I O N S //------------------------------------------------------------------------------ namespace { const Time zero_time = {0,0,0}; const uint32_t sec_per_day = 0x00015180; // = 24*60*60 enum {nch = 2}; // Кол-во каналов для сравнения. const uint16_t key = 0xA5A5; } // ns //------------------------------------------------------------------------------ // G L O B A L V A R I A B L E S //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // L O C A L S //------------------------------------------------------------------------------ namespace { // Prototypes. void enable_bkp(); bool rtc_config(); void set_time(const Time& tm); uint32_t time2int(Time tm); Time int2time(uint32_t u); // Variables. rtc_drv::Cmp_callback callback; uint32_t cmp_time[nch]; } // ns //============================================================================== // I M P L E M E N T A T I O N //============================================================================== namespace rtc_drv { //------------------------------------------------------------------------------ // Инициализация и запуск "железа". // Возврат 0 - ошибок нет; 1 - кварц не запустился; 2 - восстановление по // умолчанию (следствие разряда батареи). uint8_t init() { uint8_t res = 0; NVIC_InitTypeDef NVIC_InitStructure; // Enable the RTC Interrupt. NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY; NVIC_InitStructure.NVIC_IRQChannelSubPriority = RTC_SUBPRIORITY; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); enable_bkp(); // Наличие правильной настройки определяется по ключевому значению в // регистре в BKP domain. if (key != BKP_ReadBackupRegister(BKP_DR1)) { // Backup data register value is not correct or not yet programmed (when // the first time the program is executed). if (!rtc_config()) { return 1; } set_time(zero_time); BKP_WriteBackupRegister(BKP_DR1, key); res = 2; } else { // Без основного питания может пройти не один день. Счетчик необходимо // привести в надлежащее состояние. // Wait for RTC registers synchronization. RTC_WaitForSynchro(); uint32_t ticks = RTC_GetCounter(); ticks = ticks % sec_per_day; set_time(int2time(ticks)); } // Enable the RTC Second interrupt. RTC_WaitForSynchro(); RTC_ITConfig(RTC_IT_SEC, ENABLE); RTC_WaitForLastTask(); // RTC clock output. // Disable the Tamper Pin. // To output RTCCLK/64 on Tamper pin, // the tamper functionality must be disabled. BKP_TamperPinCmd(DISABLE); // Enable RTC Clock Output on Tamper Pin. BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock); return res; } //------------------------------------------------------------------------------ // Возврат текущего времени. Time time() { return int2time(RTC_GetCounter()); } //------------------------------------------------------------------------------ // Установка текущего времени. void time(const Time& tm) { set_time( tm ); } //------------------------------------------------------------------------------ // Устанавливает значение делителя для получения секундного интервала. void set_divider(uint32_t div) { if (div) { // Wait until last write operation on RTC registers has finished. RTC_WaitForLastTask(); // Enable the RTC Second interrupt. // Set RTC prescaler: set RTC period to 1sec. RTC_SetPrescaler(div-1); // RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(div+1) // Wait until last write operation on RTC registers has finished. RTC_WaitForLastTask(); } } //------------------------------------------------------------------------------ // Устанавливает обработчик. // При вызове обработчика, ему передается номер канала, в котором было совпадение. void set_callback(Cmp_callback cb) { callback = cb; } //------------------------------------------------------------------------------ // Устанавливает время для сравнения. // ch =[0,1] - канал совпадения. void set_cmp_time(uint8_t ch, const Time& tm) { if (ch < nch) cmp_time[ch] = time2int( tm ); } } // namespace rtc_drv //------------------------------------------------------------------------------ // Обработчик секундного прерывания. extern "C" void RTC_IRQHandler() { if (RESET != RTC_GetITStatus(RTC_IT_SEC)) { RTC_ClearITPendingBit(RTC_IT_SEC); RTC_WaitForLastTask(); // Reset RTC Counter when Time is 23:59:59. uint32_t curr = RTC_GetCounter(); if (sec_per_day == curr) { curr = 0; RTC_SetCounter(0); RTC_WaitForLastTask(); } // Проверка на совпадение. for (uint_fast8_t i=0; i<nch; ++i) { if (curr == cmp_time[i] && callback) callback(i); } } } //============================================================================== // Local functions. namespace { //------------------------------------------------------------------------------ // Открывает доступ к регистрам из bkp domain. void enable_bkp() { // Enable PWR and BKP clocks. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // Allow access to BKP Domain. PWR_BackupAccessCmd(ENABLE); } //------------------------------------------------------------------------------ // Настраивает и запускает аппаратный rtc. // Возврат true, если ошибок нет. bool rtc_config() { BKP_DeInit(); // Enable LSE. RCC_LSEConfig(RCC_LSE_ON); // Wait till LSE is ready (но не более 3 секунд). uint32_t i=0; while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && i<3000) { delay_us(1000); ++i; } if (i >= 3000) return false; // Select LSE as RTC Clock Source. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Enable RTC Clock. RCC_RTCCLKCmd(ENABLE); // Wait for RTC registers synchronization. RTC_WaitForSynchro(); rtc_drv::set_divider(rtc_drv::divider_def); return true; } //------------------------------------------------------------------------------ // Устанавливает новое значение времени. void set_time(const Time& tm) { // Wait until last write operation on RTC registers has finished. RTC_WaitForLastTask(); // Change the current time. RTC_SetCounter(time2int); // Wait until last write operation on RTC registers has finished. RTC_WaitForLastTask(); } //------------------------------------------------------------------------------ // Преобразование времени в число и обратно. uint32_t time2int(Time tm) { return (tm.hour*3600 + tm.min*60 + tm.sec); } Time int2time(uint32_t u) { Time tm = {u/3600, (u%3600)/60, (u%3600)%60}; return tm; } } // ns Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ЛеонидК 0 22 ноября, 2010 Опубликовано 22 ноября, 2010 · Жалоба Так то оно так, только RTC_WaitForLastTask() не проходит. И прерываний у меня нет. Я хочу смотреть часы, когда хочу, а не во время измерения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ЛеонидК 0 22 ноября, 2010 Опубликовано 22 ноября, 2010 · Жалоба Вопрос снимается. Удалил лишнее RTC_WaitForLastTask(). Правда четкого понимания нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Faris 1 13 октября, 2011 Опубликовано 13 октября, 2011 · Жалоба Вероятно, произошло вот что: Привожу выдержку из мануала RM0008 стр 464: To enable access to the Backup registers and the RTC, proceed as follows: ● enable the power and backup interface clocks by setting the PWREN and BKPEN bits in the RCC_APB1ENR register ● set the DBP bit the Power Control Register (PWR_CR) to enable access to the Backup registers and RTC. Похоже, второй пункт у Вас не выполнен! 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rexton 0 15 февраля, 2012 Опубликовано 15 февраля, 2012 · Жалоба Еще вопрос по часам. Плата stm32discovery не могу запустить часы от внешнего кварца. Смотрел осцилом - нет генерации на кварце. На OSC32_OUT просто 3 вольта. На OSC32_IN что то около нуля. Самое странное на плате не было резистора R15 который как раз идет с OSC32_OUT на кварц. Впаял перемычку вместо него, ничего не изменилось. Вот код инициализации часов: unsigned char RtcInit (void) { //разрешить тактирование модулей управления питанием и управлением резервной областью RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN; //разрешить доступ к области резервных данных PWR->CR |= PWR_CR_DBP; //если часы выключены - инициализировать их if ((RCC->BDCR & RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN) { //выполнить сброс области резервных данных RCC->BDCR |= RCC_BDCR_BDRST; RCC->BDCR &= ~RCC_BDCR_BDRST; //выбрать источником тактовых импульсов внешний кварц 32768 и подать тактирование RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_LSE; RTC->CRL |= RTC_CRL_CNF; RTC->PRLL = 0x7FFF; //регистр деления на 32768 RTC->CRL &= ~RTC_CRL_CNF; //установить бит разрешения работы и дождаться установки бита готовности RCC->BDCR |= RCC_BDCR_LSEON; while ((RCC->BDCR & RCC_BDCR_LSERDY) != RCC_BDCR_LSERDY); RTC->CRL &= (uint16_t)~RTC_CRL_RSF; while((RTC->CRL & RTC_CRL_RSF) != RTC_CRL_RSF){} return 1; } return 0; } Что может быть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rexton 0 16 февраля, 2012 Опубликовано 16 февраля, 2012 · Жалоба Пришлось поменять микроконтроллер и все заработало.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться