Tengo algo de experiencia relativa en AVR pero solo mínimo con PIC. Para iniciar un proyecto, solo quería verificar que pude hacer que el oscilador interno funcionara a la frecuencia correcta. Entonces, mi primera prueba fue cambiar un pin y ver la frecuencia que tengo. El primer código de prueba fue
#include <p24F16KA102.h>
_FOSCSEL(FNOSC_FRCDIV & FNOSC_PRI );
_FOSC( POSCMOD_HS );
int main(void)
{
AD1PCFG = 0xffff; //make ADC pins all digital
TRISA = 0; //Make all PORTAs all outputs
while (1)
{
LATAbits.LATA6= ~LATAbits.LATA6;
}
return 0;
}
La frecuencia medida en el RA6 es de aproximadamente 59 KHZ. Esto parecía una locura de un reloj de 8MHZ. Parece ser que los LATAbits y la negación requieren 14 Instrucciones !!
He buscado en Internet para minimizar las instrucciones para simplemente cambiar un pin y descubrí un ensamblaje integrado de BTG, así que repetí el código anterior reemplazando los LATAbits con
__ builtin_btg (& LATA, 6);
Ahora el desensamblaje muestra que hay 3 instrucciones para ejecutar el ciclo y el cambio
029A 202C40 mov.w #0x2c4,0x0000
029C A26010 btg [0x0000],#6
029E 37FFFD bra 0x00029a
¡Ahora la frecuencia en PIN RA6 es 201 KHZ!
¿Qué estoy haciendo mal aquí? He probado los bits de configuración del MPLAB sin el código, etc. Esta bien ? ¿Un reloj de 8MHZ producirá 201KHZ como la mejor opción para alternar un PIN?
Es muy probable que esté haciendo algo mal, por eso decidí publicar esto aquí después de pasar más de 6 horas probando.
Por las hojas de datos, sé que cada instrucción requiere 4 ciclos de reloj, pero no estoy seguro de los ciclos de instrucción, los ciclos de reloj y los ciclos de ejecución. Apreciaré cualquier ayuda u orientación. Quizás estoy más acostumbrado a 8 bits, donde la proporción de ciclos de reloj es menor. ¿Cuál es la forma más fácil y segura de verificar la frecuencia del reloj?
Bien, gracias a todos por todas las respuestas, ya que todas me dieron una dirección a seguir. Acabo de probar las sugerencias de Olin y Madmanguruman. Como no encontré una forma directa de colocar asm en línea con etiquetas de dirección como loop: a continuación, he creado un archivo test1.s con una función llamada loop1 con el código dado por Olin a continuación y lo llamé como se muestra en el código abajo:
#include <p24F16KA102.h>
_FOSCSEL(FNOSC_FRCDIV & FNOSC_PRI );
_FOSC( POSCMOD_HS );
extern int loop1(void);
int main(void)
{
AD1PCFG = 0xffff; //make ADC pins all digital
TRISA = 0; //Make all PORTAs all outputs
loop1();
return 0;
}
Ahora la frecuencia medida en RA6 es de aproximadamente 335 KHZ. El bucle se ejecuta cada 1,47 microsegundos (670 KHZ). Por supuesto, esto es el doble de la frecuencia anterior ya que el alcance mide dos ciclos de bucle, el RA6 es alto y el RA6 es bajo.
Luego, el uso de la información de Olin debajo de la frecuencia de reloj debe ser 12 X 680KHZ = 8.16MHZ.
Lo único que no tengo claro al 100% es cómo se define la frecuencia de las instrucciones, es decir, ¿debería tener el tiempo que RA6 es alto (o bajo) como período ?, entonces 1 instrucción parece ser 2 ciclos de ck o ... ¿debo usar el tiempo que RA6 es alto, luego bajo, luego de nuevo a alto como el período? en este caso, entonces debería ser de 4 ciclos ck por instrucción.
Lo anterior es una cuestión de definición. Mi pregunta principal se responde como (gracias a toda su ayuda en este foro) Estoy seguro de que la CK debe ser de 8 MHZ, entonces, sé que la frecuencia máxima posible para cambiar el PIN de un puerto es de aproximadamente 335 KHZ con la ck a 8MHZ (aquí significa la definición estándar de frecuencia). Además, al utilizar el PLL puedo duplicar o cuadruplicar esa tasa.