pic18F47J53 RTCC 未启动

问题描述

使用 PIC18F47J53、MPLAB x、XC8 (v2.31),我尝试使用内部 RTCC,但我看不到它在计数(秒)。寄存器 RTCVALL,在等待几秒钟后没有改变。

我想使用 8MHz 内部振荡器作为主时钟,内部 INTRC 用于 RTCC。也许首先有人可以确认是否可以使用这两个?

代码相当简单,只需在 RTCVALL 中设置一个“秒”值,稍等片刻,读取相同的寄存器并希望发现它已更改..但它没有。

我正在发布代码的主要部分。 另一个问题,RTCC 引脚应该输出什么?我选择了“秒”作为输出,但如果它应该每秒切换高/低,我可以在数据表中的哪个位置看到占空比?在我的情况下,RTCC 引脚上的 LED 保持高电平。

'''

// 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.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;
}

'''

感谢您的浏览和帮助

解决方法

我让它工作了,看起来问题不是对 PIC 的理解,而是 XC8 编译器。 我认为在启用 RTCEN 之前必须检查 RTCWREN 位

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%。