Autor Tema: Uso y Configuracion del Fail-safe Clock Monitor en PIC18F46K22  (Leído 3032 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado trunksx64

  • PIC10
  • *
  • Mensajes: 16
    • Trunksx64-Blog
Uso y Configuracion del Fail-safe Clock Monitor en PIC18F46K22
« en: 24 de Enero de 2018, 17:06:16 »
Buenos dias todos, Actualmente me encuentro usando el Microcontrolador PIC18F46K22 para algunos de mis proyectos y otros trabajos, actualmente tengo una duda que espero que uds que ayuden y explico asi:

Este PIC traen en su caracteristicas "Fail-safe Clock Monitor", lo cual es una opcion para que en caso de fallo de la fuente principal del oscilar externo, el PIC es capaz de activar el oscilador interno y seguir funcionando, ya detectado el error, se puede programar para restablecer nuevamente el oscilador externo, esto ya lo habia visto en el 18F4550 y otras familias pero nunca lo habia puesto en practica y realmente funciona, pero tengo un incoveniente, y esque he tratado de buscar informacion para configurarlo correctamente y realizar el programa para que haga esto, pero solo encuento datos para los dsPICS.

Se detecta el fallo del Oscilador externo y automaticamente se realiza el cambio al interno y dispara la Interrupcion, pero aveces no se repone, queda el oscilador interno y otras veces se bloquea todo el PIC.

Cofiguro los Fuses de Esta manera: con un Crystal de 16Mhz y el Oscilador Interno tambien de 16Mhz

Código: [Seleccionar]
#include <p18F46K22.h>

// CONFIG1H
#pragma config FOSC = HSMP      // Oscillator Selection bits (HS oscillator (medium power 4-16 MHz))
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON    // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON        // Internal/External Oscillator Switchover bit (Oscillator Switchover mode enabled)

// CONFIG2L
#pragma config PWRTEN = ON      // Power-up Timer Enable bit (Power up timer enabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 285       // Brown Out Reset Voltage bits (VBOR set to 2.85 V nominal)

// CONFIG2H
#pragma config WDTEN = ON       // Watchdog Timer Enable bits (WDT is always enabled. SWDTEN bit has no effect)
#pragma config WDTPS = 4096     // Watchdog Timer Postscale Select bits (1:4096)

// CONFIG3H
#pragma config CCP2MX = PORTC1  // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON      // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2   // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

Configuro las opciones asi:

Código: [Seleccionar]
void vHardwareConfiguration(void) {
    /* < Configuracion ::: Control WDT > */
    WDTCONbits.SWDTEN = pdClear; // WDT is turned off (Reset value)             
    /* < Configuracion ::: Control de OSC (16Mhz Internal) > */
    OSCCONbits.IRCF = 0b111; // Internal RC Oscillator Frequency Select         
    /* < Configuracion ::: Puertos > */
    TRISA = 0xFF;
    TRISB = 0xFF;
    TRISC = 0xFF;
    TRISD = 0xFF;
    TRISE = 0x07;
    SLRCON = 0x00;
    /* < Configuracion ::: Entras Analogas y Capaciteve Touch > */
    ANSELA = 0x00;
    ANSELB = 0x00;
    ANSELC = 0x00;
    ANSELD = 0x00;
    ANSELE = 0x00;
    /* < Configuracion ::: Desactivacion Modulos por Hardware > */
    PMD0 = 0xFF;
    PMD1 = 0xFF;
    PMD2 = 0xFF;
    /* < Configuracion ::: Control ISR del OSC > */
    PIR2bits.OSCFIF = pdClear; // Device clock operating
    PIE2bits.OSCFIE = pdSet; // Oscillator Fail Interrupt Enable bit
    /* < Deshablita ::: Interrupciones > */
    INTCONbits.GIE = pdSet; // < Habilita la Interrupciones Globales >
    INTCONbits.PEIE = pdSet; // < Habilita la Interrupcion de Perifericos >

El codigo de la Interrupcion asi;

Código: [Seleccionar]
/* < Funcion ::: Interrupcion :: OSC > */
#pragma interrupt prvFailSafeClock

void prvFailSafeClock(void) {
    /* < Check :: Status OSC Oscillator >*/
    if (OSCCONbits.OSTS == pdFalse) {
        /* < Resets the Main Oscillator > */
        OSCCONbits.SCS = 0b00; // Select External clock           
        /* < Wait Select Primay Clock > */
        while (OSCCONbits.OSTS == pdClear);
    }
    /* < Clear ::: Flag Interruption > */
    PIR2bits.OSCFIF = pdClear;
}

Y aca es donde yo tengo la Duda, en la interrupcion esta bien y el cambio de Reloj se efectua, puesto en el Datasheet, indica que hay que estar pendiente de OSCCONbits.OSTS para saber que fuente de Reloj se usa, pero veo en el Debug que esta ya a cambiado  a Cero, pero OSCCONbits.SCS sigue estando en Cero, lo cual indica que esta el Reloj Externo, en algunos casos fuerzo a que cambie al interno colocando OSCCONbits.SCS = 0b11 y nuevamente OSCCONbits.SCS = 0b00 para cambiar al externo, pero no funciona correctamente, aveces lo hace otras se bloquea el PIC.

Código: [Seleccionar]
/* < Funcion ::: Interrupcion :: OSC > */
#pragma interrupt prvFailSafeClock

void prvFailSafeClock(void) {
    /* < Check :: Status OSC Oscillator >*/
    if (OSCCONbits.OSTS == pdFalse) {
        /* < Clear WDT > */
        ClrWdt();
        /* < Resets the Main Oscillator > */
        OSCCONbits.SCS = 0b11; // Select Internal clock
        /* < Wait Select Secunday Clock > */
        while (OSCCONbits.HFIOFS == pdClear); // While HFINTOSC frequency is stable
        OSCCONbits.SCS = 0b00; // Select Primary clock           
        /* < Wait Select Primay Clock > */
        while (OSCCONbits.OSTS == pdClear);
    }
    /* < Clear ::: Flag Interruption > */
    PIR2bits.OSCFIF = pdClear;
}

Agradecedira mucho su Colaboracion si me ayudan, tanto si es error en el codigo, o alguna documentacion que explique bien esto para esta familia de PICS, porque el control en si no es complejo pero estoy seguro que omitio algo.

PD: esto lo estoy escribiendo en C18 y XC8, pero obtengo los mismos resultados.
Uno es Amo y Señor de lo que calla, pero un esclavo de lo que dice....

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Uso y Configuracion del Fail-safe Clock Monitor en PIC18F46K22
« Respuesta #1 en: 26 de Enero de 2018, 10:00:09 »
Citar
pero no funciona correctamente, aveces lo hace otras se bloquea el PIC.

Para mi esta funcionando correctamente, al hacer un toggle de los bits SCS (System Clock Select bits ), logras que comience de nuevo el start-up timer, el que debe esperar de 1024 ciclos, antes de considerarse "bueno".

El problema esta en tu codigo..

Citar
    if (OSCCONbits.OSTS == pdFalse) {

        OSCCONbits.SCS = 0b00;

        while (OSCCONbits.OSTS == pdClear);

El codigo asume que SI o SI el oscilador externo esta funcionando correctamente. Si por algun motivo a pesar de que cambiaste al oscilador externo este VUELVE a fallar, aunque sea 1 sola ves mientras pasa el Start-up Timer (mientras ejecuta el while), implica que quede encerrado en el while ese. Ya que al fallar el paso al oscilador externo, ya no hay mas instrucciones entre medio que lo cambie nuevamente al oscilador externo. Otro tema es que estas en la interrupcion (imagino que de alta prioridad) por lo cual no tenes mas las interrupciones habiiltadas y no va a poder a acceder a la interrupcion ya que estas estan desactivadas ahi dentro.