PIC16F18855 funciona a la mitad de la frecuencia del reloj cuando lo apago y lo enciendo demasiado rápido

Tengo una placa que tiene un PIC16F18855 funcionando a 8 MHz desde un cristal externo. La mayoría de las veces funciona bien, pero si se enciende rápidamente, se reiniciará a 4MHz. Los principales síntomas de esto son cosas como la velocidad en baudios de UART y la frecuencia de PWM que se reduce a la mitad.

Más específicamente, si enciendo y apago el interruptor de encendido en menos de ~2 segundos, funcionará a la frecuencia más baja. Más tiempo y funciona correctamente. Cuando programo la placa, se reinicia a 4 MHz, lo que significa que tengo que apagarla y encenderla físicamente antes de que funcione. Si corto el pin MCLR a tierra, el comportamiento es inconsistente: a veces comenzará a 4 MHz y, por lo general, comenzará a 8 MHz.

También tuve un caso en el que tomó mucho más tiempo, en el que encenderlo dentro de los 10 minutos posteriores a apagarlo hizo que comenzara a 4MHz. No estoy seguro de si el problema está relacionado, pero no puedo reproducir ese error en este momento.

Al probar el pin OSC2/CLKOUT, puedo ver que el cristal mismo sigue funcionando a 8 MHz. Con las sondas que tengo, no puedo sondear el pin OSC1 sin que reinicie el micro.

EDITAR 1:

Cuando la placa funciona a 8 MHz, sus registros OSCCONx son:

OSCCON1: 0x70
OSCCON2: 0x70
OSCCON3: 0x10

y cuando está funcionando a 4MHz son:

OSCCON1: 0x70
OSCCON2: 0x60
OSCCON3: 0x00

Así que funciona con el oscilador interno de HF. Miraré esto un poco más de cerca. Sabiendo esto, es posible que pueda encontrar una solución alternativa, pero prefiero descubrir la causa del problema.

OSCFRQ = 0x02, que es la configuración de 4 MHz, por lo que esto es definitivamente lo que está sucediendo. Una solución terrible sería configurar el OSCFRQregistro en la configuración de 8MHz, por lo que funciona de la misma manera, pero luego pierdo la precisión del cristal. Puede que eso no arruine todo, pero tengo algunas cosas sensibles al tiempo, así que prefiero usar el cristal si puedo.

¿Cuáles son sus configuraciones OSCCONx?
OSCCON1: 0x70, OSCCON2: 0x70, OSCCON3: 0x10,
Hay mucha fuente de reloj y complejidad de preescalador en ese chip. RSTOSC también importa. Voy a mirar mañana si nadie ha ayudado.
¿El chip tiene habilitada la conmutación por error del reloj? Algunos PIC usarán el oscilador interno 1: mientras el oscilador externo se estabiliza. y o 2: si falla el oscilador externo. Si tiene un alcance, es posible que desee comprobar y ver si el cristal está oscilando correctamente. (eso no será una garantía, porque la sonda afectará el circuito pero puede decirle algo).
Las sondas que tengo cargan demasiado el circuito para probar el pin de entrada del oscilador. No estoy totalmente seguro de lo que quiere decir con conmutación por error del reloj, pero está predeterminado en el oscilador interno HF (resuelto gracias a los comentarios de Spehro, está en las ediciones). Actualmente estoy tratando de averiguar qué está causando eso
Intente configurar /PWRTE en "0" (CONFIG2 bit 1). Esto le dará al voltaje de su fuente de alimentación 64 ms para estabilizarse antes de salir del reinicio.

Respuestas (1)

Esta no es una explicación de por qué estaba sucediendo, pero encontré una solución. Lo primero que intenté fue configurar los bits de fusible para RSTOSC_EXT (es decir #pragma fuses HS, RSTOSC_EXT) sobre la base de lo que dijo Spehro en los comentarios, pero eso no funcionó para mí. Lo que hice fue agregar lo siguiente (tenga en cuenta que OSCCON2 es la configuración real y OSCCON1 es el búfer):

if(OSCCON2 == 0x60){
    OSCCON1 = 0x60;
    OSCCON1 = 0x70;
}

Mi razón para probar esto es: OSCCON2 es la configuración real y cargará el valor en OSCCON1 cuando esté listo. De mi investigación anterior, sabía que el valor correcto estaba en OSCCON1 y OSCCON2 nunca lo cargó. Entonces, la suposición era que el proceso de carga se atascó en algún lugar, y cargar el valor en OSCCON2 en OSCCON1 haría que el chip pensara que se cargó correctamente. Esto lo 'desataría' y luego me permitiría volver a cargar el valor correcto sin que se atasque.

Este código está justo al comienzo de la función principal, después de las declaraciones de variables. Resuelve el problema, pero no explica por qué estaba sucediendo en primer lugar. Si alguien sabe qué estaba causando esto y si hay una mejor solución, todavía estoy abierto a mejores respuestas.