| Форум РадиоКот https://radiokot.ru/forum/ |
|
| STM8L и его RTC https://radiokot.ru/forum/viewtopic.php?f=62&t=154693 |
Страница 1 из 1 |
| Автор: | a_winner [ Пт май 04, 2018 22:17:33 ] |
| Заголовок сообщения: | STM8L и его RTC |
Доброго времени суток, господа. Не могу запустить RTC на STM8L051F3P6. Пробую делать так: Код: CLK_PCKENR2 = 0b00000101; // ADC + RTC while (CLK_CRTCR & CLK_CRTCR_RTCSWBSY); // Wait for RTCSWBSY flag to clear led(LED_3); CLK_CRTCR = 0xB0; // RTC clock: source LSE, RTCDIV = 32 while (!(CLK_ECKCR & CLK_ECKCR_LSERDY)); // Wait for LSE stabilization led(LED_2); RTC_WPR = 0xCA; RTC_WPR = 0x53; RTC_ISR1 |= RTC_ISR1_INIT; // Enter initialization mode while (!(RTC_ISR1 & RTC_ISR1_INITF)); // <--- тут зависаем led(LED_1); RTC_APRER = 0x08; RTC_SPRERH = 0x00; RTC_SPRERL = 0x80; RTC_WUTRH = 0xFF; // Wakeup timer = 0xFFFF RTC_WUTRL = 0xFF; RTC_DR1 = 0x16; RTC_DR2 = 0x04; RTC_DR3 = 0x18; RTC_TR3 = 0x21; RTC_TR2 = 0x37; RTC_TR1 = 0x54; RTC_ISR1 &= ~RTC_ISR1_INIT; // Exit initialization mode RTC_WPR = 0xFF; где Код: #define RTC_ISR1_INIT ((uint8_t)0x80) #define RTC_ISR1_INITF ((uint8_t)0x40) #define CLK_CRTCR_RTCSWBSY ((uint8_t)0x01) /*!< RTC clock switch busy */ #define CLK_ECKCR_LSERDY ((uint8_t)0x08) /*!< Low speed external crystal oscillator ready */ и регистры: Код: #define RTC_ISR1 *(unsigned char*)0x514C // RTC Initialization and status register 1 0x01 #define RTC_WPR *(unsigned char*)0x5159 // RTC Write protection register 0x00 Вроде бы всё по даташитам, но на ожидании флага INITF мы останавливаемся и не выходим из этого цикла. Вроде бы и разблокировку делаю, и адреса правильные, но что-то не работает. Даже LSI вместо LSE пытался использовать, результат тот же. Если читать из регистров RTC, то в RTC_DR1 получам 0x01, в RTC_DR2 - 0x21 - всё как положено. Ну, а если убрать ожидание входа в режим инициализации, то содержимое регистров не изменяется. Помогите найти ошибку, где я не прав. Спасибо. |
|
| Автор: | uldemir [ Сб май 05, 2018 13:37:49 ] |
| Заголовок сообщения: | Re: STM8L и его RTC |
С stm8l часы еще не делал, это у меня было запланировано когда-то. По коду пока проблем не вижу. только хочу уточнить: а LSEON сделан? Хотя, он должен был сам включиться, но можно проверить тоже. p.s. А. у меня платка с stm8l152 но даташит, вроде, тот же самый. Добавлено after 5 hours 38 minutes 44 seconds: Еще, к делу не относится, но в RTC_DR2 старшие 3 бита не должны быть нулями: Цитата: Bits 7:5 WDU[2:0]: Week day units 000: forbidden. 001: Monday ... 111: Sunday Добавлено after 15 minutes 30 seconds: Глягул внимательнее, что-то странные у вас коэффициенты деления. Для асинхронного счетчика рекомендуется использовать максимальное значение - 128. Т.е. грузить - 127 (0x7F). Тогда, если кварц 32768, для синхронного остаётся 256 - грузить 255 (0xff). Хотя, вы делите заранее на 32 (я бы этого не делал), то коэфиициенты верные, только грузить всё-равно надо на 1 меньше. Добавлено after 1 hour 51 minute 40 seconds: Вот мой вариант - не зависает в фазе INITF: СпойлерКод: void init_periph(void) { CLK_CKDIVR_CKM = 0x3; // HSintCLK / 8 CLK_CCOR_CCOSEL = 0; // disable clock output CLK_ECKR_LSEON = 1; // enable LSE 32768 while (!CLK_ECKR_LSERDY) ; // wait while LSE ready CLK_CRTCR_RTCSEL3 = 1; CLK_PCKENR2_PCKEN23 = 1; // LCD CLK_PCKENR2_PCKEN22 = 1; // RTC // LCD stuff skipped // Port stuff skipped RTC_WPR = 0xCA; RTC_WPR = 0x53; RTC_ISR1_INIT = 1; while (RTC_ISR1_INITF == 0) continue; RTC_APRER_PREDIV_A = 127; RTC_SPRERH = 0; RTC_SPRERL = 255; RTC_TR1 = 0x00; RTC_TR2 = 0x32; RTC_TR3 = 0x14; RTC_DR1 = 0x05; RTC_DR2 = 0x05 | (6 << 5); RTC_DR3 = 0x18; RTC_CR1 = 0; RTC_ISR1_INIT = 0; } Еще, насчет раздела "где". Какой у вас компилятор? У IAR RTC_ISR1_INIT - это RTC_ISR1bits.INIT. , а 0x80 - это MASK_RTC_ISR1_INIT. |
|
| Автор: | a_winner [ Сб май 05, 2018 19:54:05 ] |
| Заголовок сообщения: | Re: STM8L и его RTC |
Да, прошу прощения, самого главного не сказал: компилятор - SDCC. Делитель можно по-разному настроить. Вот как инициализация выглядит в прошивке уже: Код: ; main.c: 223: CLK_PCKENR2 = 0b00000101; // ADC + RTC ldw x, #0x50c4 ld a, #0x05 ld (x), a ; main.c: 224: CLK_CRTCR = 0b00010000; // RTC clock: source LSE ldw x, #0x50c1 ld a, #0x10 ld (x), a ; main.c: 225: while (!(CLK_ECKCR & CLK_ECKCR_LSERDY)); // Wait for LSE stabilization 00104$: ldw x, #0x50c6 ld a, (x) bcp a, #0x08 jreq 00104$ ; main.c: 227: RTC_WPR = 0xCA; ldw x, #0x5159 ld a, #0xca ld (x), a ; main.c: 228: RTC_WPR = 0x53; ldw x, #0x5159 ld a, #0x53 ld (x), a ; main.c: 229: RTC_ISR1 |= RTC_ISR1_INIT; // Enter initialization mode bset 0x514c, #7 ; main.c: 231: while (!(RTC_ISR1 & RTC_ISR1_INITF)); 00107$: ldw x, #0x514c ld a, (x) bcp a, #0x40 jreq 00107$ ; main.c: 236: RTC_APRER = 0x7F; ldw x, #0x5152 ld a, #0x7f ld (x), a ; main.c: 237: RTC_SPRERH = 0x00; ldw x, #0x5150 clr (x) ; main.c: 238: RTC_SPRERL = 0xFF; ldw x, #0x5151 ld a, #0xff ld (x), a ; main.c: 240: RTC_DR1 = 0x16; ldw x, #0x5144 ld a, #0x16 ld (x), a ; main.c: 241: RTC_DR2 = 0x04; ldw x, #0x5145 ld a, #0x04 ld (x), a ; main.c: 242: RTC_DR3 = 0x18; ldw x, #0x5146 ld a, #0x18 ld (x), a ; main.c: 244: RTC_TR3 = 0x21; ldw x, #0x5142 ld a, #0x21 ld (x), a ; main.c: 245: RTC_TR2 = 0x37; ldw x, #0x5141 ld a, #0x37 ld (x), a ; main.c: 246: RTC_TR1 = 0x54; ldw x, #0x5140 ld a, #0x54 ld (x), a ; main.c: 248: RTC_ISR1 &= ~RTC_ISR1_INIT; // Exit initialization mode bres 0x514c, #7 ; main.c: 249: RTC_WPR = 0xFF; ldw x, #0x5159main.c: 40: ld a, #0xff ld (x), a ret Случайно обнаружил, что если после установки флага INIT немного подождать, то потом флаг INITF нормально читается и устанавливаются остальные регистры, но никогда не взводится флаг RSF в RTC_ISR1 и часы не тикают. Вроде бы в free run режим перевожу... Тактирование контроллера от HSI, никаких особых настроек. Странно выходит с задержкой, нигде в ДШ такого не встречал, да и в примерах в интернете тоже. Что-то я всё-таки неправильно делаю похоже... Добавлено after 25 minutes 37 seconds: Так, чтобы часы пошли нужно флаг RSF сбрасывать руками, например так: Код: RTC_ISR1 &= ~(RTC_ISR1_INIT | RTC_ISR1_RSF); Всё равно с задержкой меня решение смущает, потому что как-то ненадёжно это. |
|
| Автор: | uldemir [ Вс май 06, 2018 05:46:08 ] |
| Заголовок сообщения: | Re: STM8L и его RTC |
a_winner писал(а): что если после установки флага INIT немного подождать, то потом флаг INITF нормально читается Ну дык, для того этот флаг (INITF) и есть. Тем более в даташите явно сказано, что переход в режим инициализации требует 2 такта RTCCLK, который вы еще и затормозили в 32 раза! У моего кристалла всё нормально работает: и RSF взводится, и часы тикают.a_winner писал(а): Так, чтобы часы пошли нужно флаг RSF сбрасывать руками, например так: Не нужно. По входу в режим инициализации оно и так сбрасывается. Надо просто читать все регистры TR и DR. Так как в даташите написано, что обновление теневых регистров блокируется после чтения TR1 или SSRL и разблокируется после чтения DR3.
|
|
| Автор: | a_winner [ Вс май 06, 2018 12:35:59 ] |
| Заголовок сообщения: | Re: STM8L и его RTC |
Уже переделал без предделителя в RTCCLK, см. ассемблерный листинг сообщением выше. Да и с предделителем 32, ну, вошел бы в режим инициализации RTC не через 60мкс, а за 2мс, так у меня он (флаг INITF) в цикле никогда не читается единичкой. Если в while вставить небольшую задержку, то инициализация проходит нормально. Про блокировку теневых регистров я невнимательно прочитал даташит, спасибо. Только получается, мне всегда нужно читать все регистры, даже, если нужно только часы и минуты прочитать? Лучше я буду сбрасывать флаг RSF. В итоге у меня сейчас так: Код: // Enter initialization mode
void RTC_InitModeEnter() { RTC_ISR1 |= RTC_ISR1_INIT; while (!(RTC_ISR1 & RTC_ISR1_INITF)) { _delay_ms(10); } } // Exit initialization mode inline void RTC_InitModeExit() { RTC_ISR1 &= ~(RTC_ISR1_INIT | RTC_ISR1_RSF); } // Unlock write protection of the RTC registers inline void RTC_Unlock() { RTC_WPR = 0xCA; RTC_WPR = 0x53; } // Lock write protection of the RTC registers inline void RTC_Lock() { RTC_WPR = 0xFF; } // Init the RTC module void initRTC() { while (CLK_CRTCR & CLK_CRTCR_RTCSWBSY); // Wait for RTCSWBSY flag to clear CLK_CRTCR = 0b00010000; // RTC clock: source LSE while (!(CLK_ECKCR & CLK_ECKCR_LSERDY)); // Wait for LSE stabilization RTC_Unlock(); RTC_InitModeEnter(); RTC_APRER = 0x7F; RTC_SPRERH = 0x00; RTC_SPRERL = 0xFF; if (!(RTC_ISR1 & RTC_ISR1_INITS)) { RTC_DR1 = 0x07; RTC_DR2 = 0x05 | 0x20; RTC_DR3 = 0x18; RTC_TR3 = 0x21; RTC_TR2 = 0x04; RTC_TR1 = 0x54; } RTC_InitModeExit(); RTC_Lock(); } |
|
| Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


