Analizador Lógico

Este artículo esta dedicado a un analizador lógico que hice cuando tuve ciertos problemas con la placa del proyecto, los cuales no eran resolubles mediante el uso del debugger.

Como digo en el vídeo que mostraré a continuación, un analizador lógico es un dispositivo que muestrea las señales en distintos puntos de un circuito sin cortar la comunicación original en el dispositivo. …

Las diferencias de éste con un osciloscopio son:

    • Está destinado a señales digitales. El osciloscopio está destinado a señales analógicas.
    • Tiene menor resolución. Las señales digitales suelen ser binarias, luego con 1 solo bit se puede representar gráficamente su señal, así lo he hecho en el mio. Existen más señales digitales aparte de las binarias, pero nos da una idea de porque no hace falta 16 bits de resolución.
    • Mayor velocidad. Para transmitir la misma información una señal digital oscila mas rápidamente que una analógica (sin contar las señales portadoras en radio frecuencia).
    • Mayor numero de canales. Un osciloscopio típico tendrá 2 o 3 canales, mientras que el A.L. tendrá como mínimo 8, siendo habitual tener varias decenas de ellos.

 

 

Un modelo comercial básico puede costar de medía unos 300€, aunque a su favor podemos decir de que dispondrá de protección de sus circuitos y mayor versatilidad, incluyendo por ejemplo inyección de datos.

Presentación

La importancia de un A.L. es debida a que por su naturaleza síncrona, hay ciertas señales que no pueden ser analizadas por el debugger del entorno de programación, en mi caso el protocolo SPI. Este protocolo puede ser configurado de 4 formas distintas según se registran y se programan los datos en los flancos de subida y bajada del reloj. En un microcontrolador con protocolo SPI preprogramado la escritura y lectura se hacen en instrucciones atómicas, en las cuales es imposible detener el depurador y resulta muy difícil determinar la causa cuando algo falla.

En mi caso el primer problema encontrado fue que los puertos estaban mal nombrados en la documentación del módulo ATZB-24-A2. El pin número 2 indica que es MOSI (Master Output, Slave Input) cuando en realidad es MISO y el pin número 3 indica que es MISO cuando es MOSI. La única pista que se puede obtener con un depurador en este tipo de errores es obtener 0x00 o 0xFF, depende del dispositivo. Pero aún después de arreglar el cruce de cables la recepción seguía siendo invalida, con lo cual, solo quedaban 2 posibles problemas no relacionados con la inexperiencia del programador: o una mala soldadura o un dispositivo defectuoso. La solución más rápida fue cambiar el dispositivo por otro nuevo, con lo que era obligatorio una nueva soldadura. Después de esto el circuito funcionó correctamente.

Nota: en el vídeo hay veces que hablo de ceros y unos y otras veces hablo de F, esto es porque la conversión directa del número binario 1111 a hexadecimal es F, que se suele expresar como 0xF o Fh. Es algo básico pero viene bien aclararlo.

 

Programación

Al final colgaré el proyecto completo con el archivo main.c, que es el único que he usado, está programado en el entorno AVRStudio.

Voy a comentar ciertos aspectos del diseño y lo que hacen algunos bucles:

 

  • Escribir en la pantalla las etiquetas de las líneas y configurar los puertos correspondientes a los interruptores, LED y lineas de muestreo.

 

ioport_set_pin_high(NHD_C12832A1Z_BACKLIGHT);
st7565r_set_contrast(ST7565R_DISPLAY_CONTRAST_MIN);
gfx_mono_draw_string("SS",0,0,&sysfont);
gfx_mono_draw_string("SCK",0,8,&sysfont);
gfx_mono_draw_string("MISO",0,16,&sysfont);
gfx_mono_draw_string("MOSI",0,24,&sysfont);

//configure ports
PORTE_DIR &= ~0x20; //Bit E5 as input (SW0)
PORTF_DIR &= ~0x06; //Bit F1 as input (SW1 & SW2)
PORTR_DIR |= 0x01; //Bit R0 as output (LED0)
PORTB_DIR &= ~0x0F; // J2_1-4 as input

 

Esto se hace solo una vez al comienzo del programa, dividiremos así el LCD en 2 partes, una a la izquierda, con las etiquetas, que irá de la columna 0 a la 24 y otra a la derecha, de la columna 25 a la 127, con eso tendremos ocupado todo el display, el cual esta compuesto de una matriz de 128×32 píxeles.

 

  • Comienza el bucle infinito, este es un bucle obligatorio al programar microcontroladores, ya que si no, la única forma de volver a la ejecución sería reseteando el circuito.
    Una vez dentro del bucle lo primero es inicializar el array creado que funcionará como registro:

 

for(log_ix=0;log_ix<MAX_LOG;log_ix++){
	SPILOG[log_ix]=0;
}
log_ix = 0;

 

  • A continuación se realiza una espera mientras el bit de SlaveSelect esté a nivel alto, ya que este funciona en lógica inversa. En este punto es donde debe coincidir también el breakpoint del depurador, de forma que la siguiente instrucción ponga a nivel bajo la línea SlaveSelect y comience la comunicación.
    while(PORTB_IN & 0x08); //wait until SPI_SS goes low
    

     

  • En este punto se demostrará la capacidad de reacción del A.L.. Dependiendo de la optimización de este bucle conseguiremos muestrear señales de mayor o menor velocidad, en mi caso, con el reloj del microcontrolador funcionando a 8 Mhz, era capaz de muestrear claramente señales de unos 125KHz. La señal de reloj que se ve en el vídeo es de 62,5 KHz.
    while((~PORTB_IN & 0x08)&&(log_ix<MAX_LOG)){ //log during SPI_SS is low
    	SPILOG[log_ix] = PORTB_IN;
    	log_ix++;
    }
    
    PORTR_OUT &= ~0x01;		//light up LED0 after logging
    

     

  • Luego se procede a dibujar el gráfico de los datos anteriormente registrados, limpiando primero los que hubiese dibujado en la pantalla:
    for(column=25;column<128;column++){ //clean the graph
    	for(segment=0;segment<4;segment++){
    		gfx_mono_put_byte(segment,column,0x00);
    		gfx_mono_put_byte(segment,column,0x00);
    	}
    }
    

    Cada segmento es un grupo de 8 lineas, un byte por cada columna y segmento.

    El gráfico se dibuja página a página, siguiendo para cada bit el siguiente comportamiento:

    if((SPILOG[log_ix]&0x01)!=(SPILOG[log_ix+1]&0x01)){	//Bit 1 change (SCK)
    	gfx_mono_put_byte(1,column,0x7F);
    }else if(SPILOG[log_ix]&0x01){				//Bit 1 set (SCK)
    	gfx_mono_put_byte(1,column,0x01);
    }else{
    	gfx_mono_put_byte(1,column,0x40);		//Bit 1 clear (SCK)
    }
    

    En el caso de que el bit actual sea distinto de el que hay en el siguiente registro se dibuja un flanco, no importa si es de subida o bajada, éste está representado con una línea vertical (0x7F = 01111111), es casi un segmento entero, pero se reserva el bit más significativo para dejar un hueco y que no se mezclen las gráficas de las distintas líneas. En caso de que se halle registrado un 0, se representa con el bit menos significativo del segmento (00000001) y por último, si hay registrado un 1 se representa con el penúltimo bit más significativo (01000000) por la misma razón que en el primer caso.

  • Finalmente, cada vez que se representa una página se realiza una espera interactiva comprobando el estado de los pulsadores de avanzar, retroceder o reset, tras lo cual se procede a la acción correspondiente.
    //wait untill SW0 or SW1 goes low to show a new screen
    while( (((PORTE_IN & 0x20)>>5) || (log_ix<206)) && ((PORTF_IN & 0x02)>>1) ){ 
    	if((~PORTF_IN & 0x04)>>2){  //when SW2 goes low reset
    		goto RESET;
    	}
    }
    
    //if SW0 goes low prepare to show the anterior screen
    if(((~PORTE_IN & 0x20)>>5) && (log_ix>=206)){ 
    	log_ix -= 206;
    }
    
    while( ((~PORTE_IN & 0x20)>>5) || ((~PORTF_IN & 0x02)>>1) || 
    ((~PORTF_IN & 0x04)>>2) );
    

 

Mejoras
A mi no me han hecho falta, pero no descarto que en un trabajo más serio puedan venir bien ciertas opciones:

  1. Mandar los datos al ordenador, disponiendo así de registro virtualmente infinito.
  2. Monitorizar siempre una cantidad de posiciones antes del evento disparador.
  3. Utilizar variables para almacenar el estado de los pulsadores en vez de confiar en que el tiempo de una pulsación es el óptimo para aguantar solo el paso por las instrucciones que nos interesan.

Código

Para acabar, como prometí, dejo el enlace al proyecto. Me alegrará saber si a alguien le ha resultado útil, porque aunque sea un programa muy sencillo, a veces no nos damos cuenta de que tenemos a mano las herramientas suficientes para realizar muchos de nuestros proyectos.
LogicAnalyzer

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s