Gracias por la info Manex.
Os pongo a continuación el código sobre el que se me ha planteado la duda
.
Concretamente, mi intención es cronometrar el tiempo que tarda el bucle for en el que se está cogiendo muestras del ADC.
Para ello, he establecido los contadores como véis en el código y luego hay un intento de fórmula que debe dar los milisegundos, pero está hecho con el método de prueba y error, así que seguro que no es correcto
.
Por cierto, me interesaría que el cronometraje fuese bastante preciso.
Gracias amigos
Codigo:
#include <18F452.h>
#use delay(clock=40000000)
#fuses H4 , NOLVP , NOWDT
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)
#define TRAMA 400
#ifndef __PCH__
#error This example is only for PIC18
#endif
#byte ADCON0=0XFC2
#byte ADCON1=0XFC1
#byte ADRESH=0xfc4
#byte ADRESL=0xfc3
int16 Ciclos;
#int_rtcc
void clock_isr() {
Ciclos++;
}
void CogeMuestra1(){
ADCON0=0b10000001;
#asm
bsf ADCON0,2 ;start conversion
wait1:
btfsc ADCON0,2
goto wait1 ;wait conversion completed
#endasm
// return ADRESh ;
}
void main()
{
int8 valores1[TRAMA];
int16 numvalor, HaTardado;
ADCON0=0b10000001;
ADCON1=0b01000000;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_2 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while (1) {
Ciclos=0;
for (numvalor=0;numvalor<TRAMA;numvalor++) {
CogeMuestra1();
valores1[numvalor]=ADRESh;
};
HaTardado = (long)((float)Ciclos / 22 * 1000) ;
printf ("%5lu",HaTardado);
}
Ciertamente me parece mucho más preciso saber el tiempo que tardan las instrucciones que están en el bucle y he comenzado a "desgranar" el LST y a contar los ciclos de reloj que se van gastando en cada paso, pero vuelvo con una nueva duda.
Pego el LST a continuación para que quede más claro donde me he atrancado:
Codigo:
*
0000: GOTO 0004
.................... #include <18F452.h>
....................
.................... #device PIC18F452
.................... #list
....................
....................
....................
.................... #use delay(clock=40000000)
.................... #fuses H4 , NOLVP , NOWDT
....................
.................... #ifndef __PCH__
.................... #error This example is only for PIC18
.................... #endif
....................
.................... #byte ADCON0=0XFC2
.................... #byte ADCON1=0XFC1
.................... #byte ADRESH=0xfc4
.................... #byte ADRESL=0xfc3
....................
.................... void main()
.................... {
0004: CLRF FF8
0006: BCF FD0.7
0008: CLRF FEA
000A: CLRF FE9
000C: BSF FC1.0
000E: BSF FC1.1
0010: BSF FC1.2
0012: BCF FC1.3
....................
.................... int8 valores1[400];
....................
.................... int16 numvalor;
....................
.................... ADCON0=0b10000001;
0014: MOVLW 81
0016: MOVWF FC2
.................... ADCON1=0b01000000;
0018: MOVLW 40
001A: MOVWF FC1
....................
.................... for (numvalor=0;numvalor<400;numvalor++) {
001C: MOVLB 1 2 ciclos
001E: CLRF x97 2 ciclos
0020: CLRF x96 2 ciclos
0022: MOVF x97,W 2 ciclos
0024: SUBLW 01 2 ciclos
0026: BNC 0052 2 ciclos
0028: BNZ 0030 2 ciclos
002A: MOVF x96,W 2 ciclos
002C: SUBLW 8F 2 ciclos
002E: BNC 0052 2 ciclos
.................... ADCON0=0b10000001;
0030: MOVLW 81 2 ciclos
0032: MOVWF FC2 2 ciclos
.................... #asm
.................... bsf ADCON0,2
0034: BSF FC2.2 2 ciclos
.................... wait1:
.................... btfsc ADCON0,2
0036: BTFSC FC2.2 2 ciclos * n veces (tiempo ADC)
.................... goto wait1
0038: BRA 0036 2 ciclos * n veces (tiempo ADC)
.................... #endasm
.................... valores1[numvalor]=ADRESh;
003A: MOVLW 06 2 ciclos
003C: ADDWF x96,W 2 ciclos
003E: MOVWF FE9 2 ciclos
0040: MOVLW 00 2 ciclos
0042: ADDWFC x97,W 2 ciclos
0044: MOVWF FEA 2 ciclos
0046: MOVFF FC4,FEF 2 ciclos
.................... };
004A: INCF x96,F
004C: BTFSC FD8.2
004E: INCF x97,F
0050: BRA 0022
....................
.................... }
....................
0052: SLEEP
Configuration Fuses:
Word 1: 2600 H4 NOOSCSEN
Word 2: 0E0F BROWNOUT WDT128 NOWDT BORV20 NOPUT
Word 3: 0100 CCP2C1
Word 4: 0081 STVREN NODEBUG NOLVP
Word 5: C00F NOPROTECT NOCPD NOCPB
Word 6: E00F NOWRT NOWRTD NOWRTB NOWRTC
Word 7: 400F NOEBTR NOEBTRB
Pues bien, veréis que he puesto la frase "2 ciclos" en aquellas instrucciones que están dentro del for (creo que eso está bien pero no estoy seguro) pero hay dos instrucciones que son un sub-bucle en ASM, que espera a que finalice la conversión del ADC.
En estas dos instrucciones he puesto "2 ciclos * n veces".
He estado mirando la data del 18F452 para ver cual es ese tiempo y ya es cuando me he vuelto loco completamente
, porque según dice ahí, ese tiempo depende de CHold, de RS, del Error de conversión, de VDD, de la temperatura y de VHold, variables que no controlo.
¿Existe algún atajo para calcular esto o va a resultar más complicado que el famoso Fourier? Gracias
Finalmente he seguido dándole vueltas a la opción de cronometrar el bucle y lo he conseguido, aunque no estoy nada contento porque el método ha sido casi el de prueba y error.
He cogido un generador de señal, la he sampleado con el bucle, he contado cuántas crestas de la onda han pasado por allí y he deducido qué retardo debería estar calculando la fórmula. Así hasta que he dado con ella.
Lo posteo a continuación, pero me gustaría que alguien le encontrase la lógica porque yo no lo consigo. Gracias.
Codigo:
#include <18F452.h>
#use delay(clock=40000000)
#fuses H4 , NOLVP , NOWDT
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)
#define TRAMA 500
#ifndef __PCH__
#error This example is only for PIC18
#endif
#byte ADCON0=0XFC2
#byte ADCON1=0XFC1
#byte ADRESH=0xfc4
#byte ADRESL=0xfc3
void main()
{
int8 valores1[TRAMA];
int8 valores2[TRAMA];
int16 numvalor, HaTardado;
ADCON0=0b10000001;
ADCON1=0b01000000;
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
setup_timer_0( RTCC_INTERNAL);
output_high (PIN_B3); // es un led que se enciende al arrancar
output_high (PIN_B0);
delay_ms (100); // lo mantengo encendido 3 décimas de segundo
output_low (PIN_B3); // y lo apago
output_low (PIN_B0);
delay_ms (100);
while (1) {
output_high (PIN_B3);
set_timer0(0);
for (numvalor=0;numvalor<TRAMA;numvalor++) {
#asm
bsf ADCON0,2 ;start conversion
wait1:
btfsc ADCON0,2
goto wait1 ;wait conversion completed
#endasm
valores1[numvalor]=ADRESh;
};
HaTardado = (get_timer0()/40+7)/5*4; // número de microsegundos de la captura
output_low (PIN_B3);
printf ("%C%C%C%C%5lu",0x00,0xFF,0x00,0xFF,HaTardado);
output_high (PIN_B0);
for (numvalor=0;numvalor<TRAMA;numvalor++) {
printf ("%C",valores1[numvalor]);
};
output_low (PIN_B0);
};
}