pic18F47J53 RTCC не запускается
Используя PIC18F47J53, MPLAB x, XC8 (v2.31), я пытаюсь использовать внутренний RTCC, но не вижу, как он считает (секунды). Регистр RTCVALL не меняется после ожидания в течение нескольких секунд.
Я хотел бы использовать внутренний генератор 8 МГц для основных часов и внутренний INTRC для RTCC. Может быть, сначала кто-то может подтвердить, можно ли использовать эти 2?
Код довольно прост, просто установите значение «секунды» в RTCVALL, немного подождите, прочитайте тот же регистр и надейтесь найти, что он изменился... но это не так.
Выкладываю основную часть кода. Другой вопрос, что должен выводить вывод RTCC? Я выбрал «секунды» в качестве вывода, но если он должен переключаться между высокими и низкими значениями каждую секунду, где я могу увидеть в таблице данных рабочий цикл? в моем случае светодиод на выводе RTCC остается постоянно высоким.
'''
// CONFIG1L
#pragma config WDTEN = OFF // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV = 1 // PLL Prescaler Selection (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CFGPLLEN = OFF // PLL Enable Configuration Bit (PLL Disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config CPUDIV = OSC1 // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF // Code Protect (Program memory is not code-protected)
// CONFIG2L
#pragma config OSC = INTOSC // Oscillator (INTOSC)
#pragma config SOSCSEL = HIGH // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected)
#pragma config CLKOEC = ON // EC Clock Out Enable Bit (CLKO output enabled on the RA6 pin)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor (Enabled)
#pragma config IESO = ON // Internal External Oscillator Switch Over Mode (Enabled)
// CONFIG2H
#pragma config WDTPS = 32768 // Watchdog Postscaler (1:32768)
// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = INTOSCREF // RTCC Clock Select (INTRC)
#pragma config DSBOREN = ON // Deep Sleep BOR (Enabled)
#pragma config DSWDTEN = ON // Deep Sleep Watchdog Timer (Enabled)
#pragma config DSWDTPS = G2 // Deep Sleep Watchdog Postscaler (1:2,147,483,648 (25.7 days))
// CONFIG3H
#pragma config IOL1WAY = ON // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set once)
#pragma config ADCSEL = BIT10 // ADC 10 or 12 Bit Select (10 - Bit ADC Enabled)
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)
// CONFIG4L
#pragma config WPFP = PAGE_127 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 127)
#pragma config WPCFG = OFF // Write/Erase Protect Configuration Region (Configuration Words page not erase/write-protected)
// CONFIG4H
#pragma config WPDIS = OFF // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored)
#pragma config WPEND = PAGE_WPFP// Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages WPFP<6:0> through Configuration Words erase/write protected)
#pragma config LS48MHZ = SYS48X8// Low Speed USB mode with 48 MHz system clock bit (System clock at 48 MHz USB CLKEN divide-by is set to 8)
#define UINT_TO_BCD_ONES(x) ((x) % 10)
#define UINT_TO_BCD_TENS(x) (((x) % 100) / 10)
#define BCD_TO_UINT_TENS(x) ((x) >> 4)
#define BCD_TO_UINT_ONES(x) ((x) & 0x0F)
void main(void)
{
// set to 8MHz internal oscillator
OSCCON = 0x70;
// not sure that is necessary but either 0 or 1 don't work
OSCTUNEbits.INTSRC = 1;
pic_uart1_init(UART_BDS_9600);
__delay_ms(1000);
uint8_t seconds = 0;
// seconds RTCC output pin
PADCFG1bits.RTSECSEL1 = 0;
PADCFG1bits.RTSECSEL0 = 1;
pic_rtc_set_alarm_output(ON);
pic_rtc_enable(ON);
pic_rtc_wr_enable(ON);
pic_rtc_set_seconds(45);
pic_rtc_wr_enable(OFF);
// wait some time
for (int i = 0; i < 12; i++){
__delay_ms(1000);
printf("-> RTCVALL = %d\n", RTCVALL);
printf("-> RTCVALH = %d\n", RTCVALH);
}
pic_rtc_read_seconds(&seconds);
pic_rtc_enable(OFF);
printf("seconds = %d\n", seconds);
}
pic_status_t pic_rtc_enable(feature_status_t set_status)
{
pic_rtc_wr_enable(ON);
RTCCFGbits.RTCEN = set_status;
pic_rtc_wr_enable(OFF);
return PIC_SUCCESS;
}
pic_status_t pic_rtc_set_alarm_output(feature_status_t set_status)
{
RTCCFGbits.RTCOE = set_status;
return PIC_SUCCESS;
}
pic_status_t pic_rtc_wr_enable(feature_status_t set_status)
{
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
RTCCFGbits.RTCWREN = set_status;
INTCONbits.GIE = 1;
return PIC_SUCCESS;
}
pic_status_t pic_rtc_read_seconds(uint8_t *seconds)
{
// point to minutes
RTCCFGbits.RTCPTR1 = 0;
RTCCFGbits.RTCPTR0 = 0;
printf("RTCCFGbits.RTCPTR1 = %d\n", RTCCFGbits.RTCPTR1);
printf("RTCCFGbits.RTCPTR0 = %d\n", RTCCFGbits.RTCPTR0);
printf("RTCCFGbits.RTCWREN = %d\n", RTCCFGbits.RTCWREN);
uint8_t buffer_rd_sec = RTCVALL;
printf("buffer_rd_sec (BCD) = 0x%02x\n", buffer_rd_sec);
*seconds = (uint8_t)((BCD_TO_UINT_TENS(buffer_rd_sec) * 10) + (BCD_TO_UINT_ONES(buffer_rd_sec)));
return PIC_SUCCESS;
}
pic_status_t pic_rtc_set_seconds(uint8_t seconds)
{
if (seconds > 59)
return PIC_FAIL;
// point to seconds
RTCCFGbits.RTCPTR1 = 0;
RTCCFGbits.RTCPTR0 = 0;
printf("RTCCFGbits.RTCPTR1 = %d\n", RTCCFGbits.RTCPTR1);
printf("RTCCFGbits.RTCPTR0 = %d\n", RTCCFGbits.RTCPTR0);
printf("RTCCFGbits.RTCWREN = %d\n", RTCCFGbits.RTCWREN);
uint8_t buf_ones = UINT_TO_BCD_ONES(seconds);
printf("buf_ones = 0x%02x\n", buf_ones);
uint8_t buf_tens = UINT_TO_BCD_TENS(seconds);
printf("buf_tens = 0x%02x\n", buf_tens);
uint8_t buffer = buf_tens << 4 | buf_ones;
printf("buffer = 0x%02x\n", buffer);
RTCVALL = buffer;
return PIC_SUCCESS;
}
'''
Спасибо за внимание и помощь
1 ответ
У меня это заработало, похоже, проблема была не в понимании PIC, а в компиляторе XC8. Я думал, что бит RTCWREN должен быть проверен, прежде чем включать RTCEN
pic_status_t pic_rtc_enable(feature_status_t set_status)
{
while(!RTCCFGbits.RTCWREN); // wait for the bit to be set
RTCCFGbits.RTCEN = set_status;
return PIC_SUCCESS;
}
и обнаружил, что бит вообще не был установлен, в результате чего остальная часть кода была проигнорирована. поэтому я заглянул в свою функцию pic_rtc_wr_enable и очень озадачен, почему параметр set_status создает блок!
это перечисление,
typedef enum {
OFF = 0,
ON = 1,
} feature_status_t;
но если вы замените код на
pic_status_t pic_rtc_wr_enable(feature_status_t set_status)
{
if (set_status == 1) {
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
RTCCFGbits.RTCWREN = 1;
INTCONbits.GIE = 1;
}
return PIC_SUCCESS;
}
то работает отлично.
Так почему же XC8 не заменяет мое перечисление ON значением int, равным 1, для назначения битов? несмотря на то, что он работает в чеке? Любые идеи?
Что касается контакта RTCC, теперь он тоже работает, и похоже, что вывод пульсирует каждую секунду (в моем случае), а рабочий цикл составляет 50%.