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 OSCFRQ
registro 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.
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.
Spehro Pefhany
Escapar
Spehro Pefhany
Dibujó
Escapar
Juan Birckhead