Actualmente estoy trabajando en un proyecto donde el reloj necesita cambiar entre el oscilador primario con PLL (POSCPLL) al FRC y viceversa.
He inicializado el Reloj como PRIPLL usando los bits de configuración:
#pragma config FNOSC = PRIPLL
#pragma config POSCMOD = HS
#pragma config FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2
#pragma config FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1
#pragma config FCKSM = CSECME
que establece el OSCCON en 0x01453360 y da una señal de reloj de 80 MHz. Luego uso esta función para cambiar al FRC:
INTDisableInterrupts();
//Execute the System unlock sequence
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
OSCCONbits.NOSC = 000;
OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);
//Initiate the clock switch
OSCCONbits.OSWEN = 1;
//Lock SYSKEY
SYSKEY = 0x33333333;
int k = 0;
//Wait until OSWEN = 0 and switch is complete
while (OSCCONbits.OSWEN == 1){
k++;
}
//Re-enable interrupts
INTEnableInterrupts();
SYSTEMConfig(GetStandbySystemClock(), SYS_CFG_ALL);
Para volver a POSC PLL, uso la misma estructura pero cambio el valor de NOSC a 011; y actualice OSCConfig a
OSCConfig(OSC_POSC_PLL, OSC_PLL_MULT_20, OSC_PLL_POST_1, 0);
Que coincide con la secuencia en los bits de configuración pragma. Sin embargo, cuando lo ejecuto en el PIC32MX, el depurador en un PICKIT3 no puede pasar la función con estos bits de configuración, sin embargo, permitirá que se configure a la mitad de la velocidad (OSC_PLL_POST_2).
Sin embargo, si el depurador está en pausa, se puede ver que el OSCCON es el mismo, pero cuando se reanuda, el software se reinicia.
Si alguien pudiera decirme si me he perdido un bit de configuración para permitir volver al reloj inicial o si hay una mejor manera de hacerlo, ¡estaría extremadamente agradecido!
Información adicional: PIC32MX775F256L, placa personalizada, cristal de 8 MHz (FOXSDLF/080-20), el cristal se conecta a OSC1 y OSC2 (pin 63 y pin 64), cargando condensadores 22pF
gracias de antemano
EDITAR Ahora también he intentado configurar la nueva fuente de reloj sin usar la función OSCConfig y usando los valores duros en su lugar.
OSCCONbits.NOSC = 0b011;
OSCCONbits.PLLODIV = 0b000;
OSCCONbits.PLLMULT = 0b101;
OSCCONbits.PBDIV = 0b00;
Cuando PLLODIV es 0b000 pasa lo mismo, sin embargo cuando se pone a 0b001 funciona y el sistema va a media velocidad, ya que se divide por dos
EDITAR 2
Ahora he intentado cambiar entre relojes sin usar los bits de configuración #pragma que he eliminado
#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_1
#pragma config FNOSC = PRIPLL
#pragma config FPBDIV = DIV_1
Utilizo las mismas funciones para configurar el reloj en primer lugar y obtengo el resultado deseado sin problemas. Luego cambio al reloj FRC, nuevamente sin problemas. Solo cuando trato de volver al reloj original encuentro un problema. Tampoco ayuda si primero cambio al mismo reloj con diferentes parámetros antes de volver a cambiar a los correctos a través del FRC nuevamente. Pero funcionará si primero cambio al reloj con diferentes parámetros, luego cambio al correcto a través del FRC al inicio.
Ahora tengo el código aislado para evitar que cualquier otro código afecte el cambio de reloj y todavía no hay diferencia.
Si tenía la intención de establecer esos bits como binarios, debe cambiar esto:
OSCCONbits.NOSC = 000;
a esto:
OSCCONbits.NOSC = 0b000;
Además, dondequiera que retroceda NOSC
, debe establecerse 0b011
no solo en 011
.
Un prefijo de "0" en realidad hace que el valor sea octal en el compilador XC32 (como lo señaló @Lundin en los comentarios), que es decimal 9, que == 0b1001, por lo que este es ciertamente un problema que necesita solución.
Además, en la Guía de la biblioteca periférica PIC32 dice:
"En general, cuando se cambia a una frecuencia de reloj de CPU más alta, el divisor de bus periférico debe establecerse en el nuevo valor más bajo antes de cambiar la frecuencia de CPU"
Por lo tanto, al subir/bajar velocidades, debe usar el orden apropiado de las siguientes llamadas:
OSCConfig(OSC_FRC, 0, 0, OSC_FRC_POST_1);
mOSCSetPBDIV(OSC_PB_DIV_1);
011
es octal (9 de diciembre), por lo que esta respuesta tiene algunos errores.
Lundin
10
, notación hexadecimal:0xA
, notación octal:012
. No hay notación binaria en C, pero una extensión común no estándar es0b1010
.