Controlar 132 Led independiente

Ya veo, es como decís, el integrado resuelve todo, incluso ni siquiera necesitás agregar las resistencias limitadoras y con el pote limitás la corriente como dijiste antes.

Sin embargo me queda la duda si la corriente que puede suministrar a c/segmento es suficiente para un buen brillo, fijate que dice que la máxima corriente es de 40mA, la veo muy baja para 15 displays.
 
Hola:

Aquí lo explica.
http://playground.arduino.cc/Main/MAX72XXHardware

Forward voltage
ISeg |1.5V |2.0V |2.5V |3.0V |3.5V
40mA |12.2kΩ |11.8kΩ |11.0kΩ |10.6kΩ |9.69kΩ
30mA |17.8kΩ |17.1kΩ |15.8kΩ |15.0kΩ |14.0kΩ
20mA |29.8kΩ |28.0kΩ |25.9kΩ |24.5kΩ |22.6kΩ
10mA |66.7kΩ |63.7kΩ |59.3kΩ |55.4kΩ |51.2kΩ
Un saludo.
 
Última edición:
Ahí lo explica bien:

Internally the MAX72XX multiplexes the rows of the matrix. Multiplexing means : The drivers switches between the rows of the matrix very fast (about 800 times a second). That gives the impression all the Leds are constantly on, while in reality they just flicker very, very fast. The big advantage of this trick is that at every single point of time no more than 8 Leds (one row) are lit. The maximum current that a single matrix will ever demand is 8 times the current you have set with resistor RSet (+ some 10mA for the MAX72XX itself). In the example from section Selecting a value for RSet we selected a value for RSet that limited the Led current to 20mA. If our software now lights up all the 64 Leds in the Matrix at the same time, we still have to supply only 170mA, because of multiplexing.

PeakCurrent=(8 x LedCurrent) + MAX72XX-Supply
PeakCurrent=(8 x 20mA) + 10mA = 170mA

Es decir que la corriente pico será 8 veces la corriente que fijés con esa resistencia y por ende se supone que esa corriente que fijás con el pote es la corriente media que pasará por lo leds, es muy importante esto.
 
Última edición:
Hola gente del foro.
Ya se es un tema viejo pero veo que mucha gente tiene confución con la técnica de charlieplexing.
Basicamente se trata de usar el echo que cuando se define un pin de un puerto de los microcontroladores (PIC o AVR) como entrada, este pin presenta una alta impedancia (Z). Asi que ahora en lugar de una lógica de dos estados (binaria) tenemos una de tres. 0, 1 y Z

Así se pueden manejar más leds que con una lógica binaria. ... Se ponen los led en matriz excepto que se deja vacia la diagonal principal. Ver dibujo anexo. en el asuman que tenemos 8
Displays de 7-seg (si son catodo común este pin se conecta en la fila. y los anodos de los segmentos en las columnas, asi por ejemplo el catodo común del primer digito se coloca en la primera fila y los anodos de los segmentos a-g se colocan en columnas 2-8). Para Display Anodo común el anodo común se conecta en la coluna deseada y se manejan los catodos en las filas.

Se manejan los segmentos de la siguiente manera (Asumiendo Display de Anodos común que son los más baratos.):

Se habilita el puerto, que tenga el display que queremos iluminar, como salida y escribimos un nivel alto (1) en él.

Se habilitan los puertos, que tenga los segmentos display que NO queremos iluminar, como entrada .

Se habilitan los puertos, que tenga los segmentos display que queremos iluminar, como salida y escribimos un nivel bajo (0) en él.


Asi por ejemplo: si queremos mostrar el número 1 y despues el número 2 en el primer display
tendriamos:

Digito 1 -,a,b,c,d,e,f,g
1 = 1,Z,0,0,Z,Z,Z,Z
Espera un tiempo
2 = 1,0,0,Z,0,0,Z,0

Espero que les sea útil.
NOTA1: el uso de los transistores y el valor de las resistencias no se debe cambiar ya que determinan la iluminocidad (mA que pasan por cada led), y el duty cycle en el caso de 8 Displays es de 1/8 o 12.5% que es mucho muy superior que si multiplexaramos los led individualmente (1/56) ~ 1.78%
Nota2: Se puede implementar facilente en un PIC16F54 ... 0.57 us que es mucho más barato que un decodificador TTL de BCD a 7-seg ó el carísimo MAX
NOTA3: Usando el PIC 16F18855 (1.70 us) trae crystal interno y más puertos. por lo que se puede implementar un display de 16 digitos con la anterior técnica con un duty cycle del 12.5% y nos evitamos la rutina de transmisión serie para coordinar 2 pic16F54

Para quien quiera profundizar en el uso de shift registers ...les dejo el siguiente pdf
 

Adjuntos

  • Charlieplexing.jpg
    Charlieplexing.jpg
    62.3 KB · Visitas: 40
  • One-I-O-line-drives-shift-register-with-strobe.pdf
    601.5 KB · Visitas: 12
Última edición:
A mi me gusta más el conexionado en cascada de los display, es decir cada segmento conecta con segmento siguiente del siguiente display y el último cierra el círculo a través del cátodo común (octava línea), todos los 'a' conectan con el 'b' de su respectivo siguiente display, los 'b' con los 'c'..., y los cátodos con los 'a'. Así el control es ridículamente fácil ya que por ejemplo si quieres iluminar el primer dígito entero, escribes como salidas los display iluminados y la polaridad en el catodo o ánodo común (como salida de polaridad opuesta a los leds encendidos), y para segundo, tercer, hasta el dígito octavo, solo hay que hacer lo mismo que para el primero, pero después desplazar las líneas el número de bits como display quieras controlar, así se consigue ratios 1/8 sin transistores de buffer.
 
Estimado palurdo
No logro visualizar como conectas los displays, trate de hacer un dibujo para ello (ExpressPCB, puesto que es gratuito), pero sin resultado.

¿Podrias poner un dibujo de tu conexión para digamos 3 displays?
 
Disculpa que no haya contestado antes. Te hago el dibujo del conexionado de 8 display (ya que así se completa el esquema cíclico). Las líneas se toman desde los electrodos comunes (ya sean ánodos o cátodos). Como ves, el electrodo en común queda polarizado directamente el seleccionado y todos los demás polarizados en inversa. Al mismo tiempo cada línea encuentra su camino hacia el segmento a controlar, pudiéndose usar las 7 líneas más el común al mismo tiempo. Por la simetría radial del circuito, simplemente haciendo una rotación de bits sobre el dato en el puerto, se cambia el dígito a mostrar.

Las resistencias sirven para limitar la corriente en cada led encendido, como es habitual.

export.jpg

Y aquí un ejemplo, usando el puerto B de un PIC16F628A:

Screenshot_2017-03-28-16-10-17.jpg
 
Hola Palurdo
Gracias por tu dibujo, ahora esta muy claro. Ahora otro favor ¿Podrías indicar que PIC usas y si no es mucha molestia subir su codigo?
 
Pues como dije antes, el pic que uso es el PIC16F628A, y el código que uso no lo puedo poner al completo, pero puedo poner una rutina sobre cómo manejar el puerto B (por ejemplo), en código C para que quede más simple. Supongamos que en RB7 tenemos el electrodo común, RB6 el segmento 'a', RB5 el 'b'... , y en RB0 el 'f', entonces:
Código:
BYTE buffer[8]={1,0,6,7,4,9,1,2}; //buffer de dígitos en pantalla (8 dígitos)
BYTE segmentos={0x01,0x4F,0x12,0x06,0x4C,0x24,0x20,0x0F,0x00,0x04}; //tabla de conversión
BOOL anodocomun = True; //vamos a usar un display ánodo común.
BYTE dato, polaridad=anodocomun?0x80:0x7F; //Se determina la polaridad del display.

for(BYTE n=0;;(n++)%8){ //Bucle infinito donde n cíclicamente va de 0 a 7.
  dato=segmentos[buffer[n]]; // los segmentos del dígito de buffer en posición n. Común en bit 7.
  output_b(anodocomun?0x00:0xFF); //apaga todos los segmentos momentáneamente para evitar ghosting.
  set_tris_b((dato>>n)|(dato<<(8-n))); //prepara los segmentos que se van a encender, rotando según el dígito n.
  output_b((polaridad>>n)|(polaridad<<(8-n))); //Enciende los segmentos del dígito n.
//Aquí seguir las tareas del programa.
}

Si la polaridad del display es fija, se puede ahorrar código (o se puede definir mediante macros). Supongamos se usan display de cátodo común:


Código:
BYTE buffer[8]={1,0,6,7,4,9,1,2}; 
BYTE segmentos={0x01,0x4F,0x12,0x06,0x4C,0x24,0x20,0x0F,0x00,0x04}; 
BYTE dato; 

for(BYTE n=0;;(n++)%8){ 
  dato=segmentos[buffer[n]]; 
  output_b(0xFF); 
  set_tris_b((dato>>n)|(dato<<(8-n))); 
  output_b((0x7F>>n)|(0x7F<<(8-n))); 
//Aquí seguir las tareas del programa
}

Aunque en C la rotación de un byte queda algo fea, ya que C carece de operador de rotación y hay que simularlo con desplazamientos, el compilador lo detecta y usa eficientemente la instrucción de rotación del microcontrolador. Si por la disposición física de los displays los dígitos se muestran en orden invertido, simplemente se arregla cambiando el sentido de la rotación. Las pullups internas del puerto B deben estar deshabilitadas para evitar un ligero encendido de los segmentos apagados.
 
Última edición:
Bueno voy a tener que aprender a programar en "C", ya que hago todo en assembler .. aqui el pseudo-code de lo que estoy trabajando, basado en el dibujo de mi anterior post
Código:
; Mostrar Display usando charlieplexing
; TMR0 = tiempo multiplexado
; B_Tris = Provicional de TRISB
; B_CHAR = Provicional de Caracter a mostrar en PORTB
; Digit_Mostrar = Contador del Digito a Mostrar del Display

Muestra:
;Muestra Caracteres en digito seleccionado
 Digit_Mostrar = 1   ; valores validos 1-8 
 
Caracter:
; Caminamos los 37 caracteres a mostrar
  For i= 0 to 37
  { 
    w = 0
    call tabla caracter ; Obtener Tris-Caracter 
                        ; regresa con w = Tris-Caracter
    Guarda w en B_Tris
    Guarda w en B_CHAR
    call Intercambia   ;ajuste de bits
    w = B_Tris         ; Pon altas-Z (entradas)
    TRISB = w
    w= B_CHAR          ; Muestra caracter en PuertoB
    PortB = w
    Demora tiempo de multiplexado (Dependendo del número de digitos)
        (1 Dig = demora 1000ms, ... 2 Dig = demora 500ms ...
         8 Dig = demora 125ms)
   }
   next i
  ¿Digit_Mostrar = 8?
    si: Regresa a Muestra
	no: Digit_Mostrar = Digit_Mostrar +1
	    Regresa a Caracter
  
Intercambia:
; Entra con:
;       Digit_Mostrar ajustado al Digito a mostrar en el Display
;
  copia Digit_Mostrar en temp
  temp = temp - 1
  w = temp
  Es w = 0
     si: ;Primer digito no hay necesidad de ajustar
    	 Incrementa Digit_Mostrar
	     Regresa
	 no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 2do digito hay necesidad de ajustar
          mueve bit6 a bit7             btfss  B_CHAR,6
            si es 0                     bcf    B_CHAR,7
          PORTB = B_CHR		        movf   B_CHAR,w
		                        movwf  PORTB
	  Regresa
     no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 3er digito hay necesidad de ajustar
	                                                      1010 xxxx
          mueve bit6 a bit7             btfss  B_CHAR,6
	    si es 0                     bcf    B_CHAR,7
          mueve  bit5 a  bit6 		btss   B_CHAR,5
            si es 0                     bcf    B_CHAR,6
		                        btsc   B_CHAR,5
	    si es 1                     bsf    B_CHAR,6
	  ajusta  bit5 a 1		bsf    B_CHAR,5
          PORTB = B_CHR		        movf   B_CHAR,w
		                        movwf  PORTB
	  Regresa
     no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 4to digito hay necesidad de ajustar
          mueve  bit6 a  bit7          btfss  B_CHAR,6
	    si es 0                    bcf    B_CHAR,7
          mueve  bit5 a  bit6          btss   B_CHAR,5
            si es 0                    bcf    B_CHAR,6
		                       btsc   B_CHAR,5
	    si es 1                    bsf    B_CHAR,6
	 ajusta  bit5 a 1              bsf    B_CHAR,5
         mueve  bit4 a  bit5           btfss  B_CHAR,4
	    si es 0                    bcf    B_CHAR,5
         		               bsf    B_CHAR,6
         ajusta  bit4 a 1              bsf    B_CHAR,4
         PORTB = B_CHR		       movf   B_CHAR,w
		                       movwf  PORTB
	 Regresa
     no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 5to digito hay necesidad de ajustar
         mueve  bit6 a  bit7          btfss  B_CHAR,6
	   si es 0                    bcf    B_CHAR,7
         mueve  bit5 a  bit6          btss   B_CHAR,5
           si es 0                    bcf    B_CHAR,6
	                              btsc   B_CHAR,5
	   si es 1                    bsf    B_CHAR,6
	ajusta  bit5 a 1              bsf    B_CHAR,5
        mueve  bit4 a  bit5           btfss  B_CHAR,4
	   si es 0                    bcf    B_CHAR,5
        		              bsf    B_CHAR,6
        ajusta  bit4 a 1              bsf    B_CHAR,4
        mueve  bit3 a  bit4           btfss  B_CHAR,3
	   si es 0                    bcf    B_CHAR,4
	                              btsc   B_CHAR,3
	   si es 1                    bsf    B_CHAR,4
        ajusta  bit3 a 1              bsf    B_CHAR,3
        PORTB = B_CHR	              movf   B_CHAR,w
		                      movwf  PORTB
	 Regresa
     no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 6to digito hay necesidad de ajustar
         mueve  bit6 a  bit7          btfss  B_CHAR,6
	   si es 0                    bcf    B_CHAR,7
         mueve  bit5 a  bit6          btss   B_CHAR,5
           si es 0                    bcf    B_CHAR,6
	                              btsc   B_CHAR,5
	   si es 1                    bsf    B_CHAR,6
	ajusta  bit5 a 1              bsf    B_CHAR,5
        mueve  bit4 a  bit5           btfss  B_CHAR,4
	   si es 0                    bcf    B_CHAR,5
        		              bsf    B_CHAR,6
        ajusta  bit4 a 1              bsf    B_CHAR,4
        mueve  bit3 a  bit4           btfss  B_CHAR,3
	   si es 0                    bcf    B_CHAR,4
	                              btsc   B_CHAR,3
	   si es 1                    bsf    B_CHAR,4
        ajusta  bit3 a 1              bsf    B_CHAR,3
        mueve  bit2 a  bit3           btfss  B_CHAR,2
           si es 0                    bcf    B_CHAR,3
				      btsc   B_CHAR,2
	   si es 1                    bsf    B_CHAR,3
        ajusta  bit2 a 1              bsf    B_CHAR,2
        PORTB = B_CHR	              movf   B_CHAR,w
		                      movwf  PORTB		  
	Regresa
     no: temp = temp - 1
         w = temp
  Es w = 0
     si: ; 7mo digito hay necesidad de ajustar
         mueve  bit6 a  bit7          btfss  B_CHAR,6
	   si es 0                    bcf    B_CHAR,7
         mueve  bit5 a  bit6          btss   B_CHAR,5
           si es 0                    bcf    B_CHAR,6
	                              btsc   B_CHAR,5
	   si es 1                    bsf    B_CHAR,6
	ajusta  bit5 a 1              bsf    B_CHAR,5
        mueve  bit4 a  bit5           btfss  B_CHAR,4
	   si es 0                    bcf    B_CHAR,5
        		              bsf    B_CHAR,6
        ajusta  bit4 a 1              bsf    B_CHAR,4
        mueve  bit3 a  bit4           btfss  B_CHAR,3
	   si es 0                    bcf    B_CHAR,4
	                              btsc   B_CHAR,3
	   si es 1                    bsf    B_CHAR,4
        ajusta  bit3 a 1              bsf    B_CHAR,3
        mueve  bit2 a  bit3           btfss  B_CHAR,2
           si es 0                    bcf    B_CHAR,3
				      btsc   B_CHAR,2
	   si es 1                    bsf    B_CHAR,3
        ajusta  bit2 a 1              bsf    B_CHAR,2
        mueve  bit1 a  bit2           btfss  B_CHAR,1
           si es 0                    bcf    B_CHAR,2
			              btsc   B_CHAR,1
	   si es 1	              bsf    B_CHAR,2
        ajusta  bit1 a 1              bsf    B_CHAR,1
        PORTB = B_CHR	              movf   B_CHAR,w
		                      movwf  PORTB
	Regresa
    no: temp = temp - 1
        w = temp
  Es w = 0
     si: ; 8vo digito hay necesidad de ajustar
         mueve  bit6 a  bit7          btfss  B_CHAR,6
	   si es 0                    bcf    B_CHAR,7
         mueve  bit5 a  bit6          btss   B_CHAR,5
           si es 0                    bcf    B_CHAR,6
	                              btsc   B_CHAR,5
	   si es 1                    bsf    B_CHAR,6
	ajusta  bit5 a 1              bsf    B_CHAR,5
        mueve  bit4 a  bit5           btfss  B_CHAR,4
	   si es 0                    bcf    B_CHAR,5
        		              bsf    B_CHAR,6
        ajusta  bit4 a 1              bsf    B_CHAR,4
        mueve  bit3 a  bit4           btfss  B_CHAR,3
	   si es 0                    bcf    B_CHAR,4
	                              btsc   B_CHAR,3
	   si es 1                    bsf    B_CHAR,4
        ajusta  bit3 a 1              bsf    B_CHAR,3
        mueve  bit2 a  bit3           btfss  B_CHAR,2
           si es 0                    bcf    B_CHAR,3
				      btsc   B_CHAR,2
	   si es 1                    bsf    B_CHAR,3
        ajusta  bit2 a 1              bsf    B_CHAR,2
        mueve  bit1 a  bit2           btfss  B_CHAR,1
           si es 0                    bcf    B_CHAR,2
			              btsc   B_CHAR,1
	   si es 1	              bsf    B_CHAR,2
        ajusta  bit1 a 1              bsf    B_CHAR,1
        PORTB = B_CHR	              movf   B_CHAR,w
		                      movwf  PORTB

        mueve  bit0 a  bit1           btfss  B_CHAR,0
           si es 0                    bcf    B_CHAR,1
				      btsc   B_CHAR,0
	   si es 1                    bsf    B_CHAR,1
        ajusta  bit0 a 1              bsf    B_CHAR,0
        PORTB = B_CHR		      movf   B_CHAR,w
		                      movwf  PORTB
	     Regresa
    no:  señala error regresa con w=1   retlw  1

subo el file en TXT (Uso NotePad++), ya lo se es un spagueti y necesita depurarse para salvar las preciosas lococalidades del PIC16F54 más del 10% en ahorro con el uso de subrutinas (Cuando suba ver 1.1) ..pero hasta donde lo he podido probar .... Trabaja

NOTA: no puedo usar las rotaciones porque afectan a todos los bits del caracter a mostrar. Por eso
el manipuleo de bits depende del Digito a mostrar en el display

-------------- Software update ----------------
Aqui esta version 1.1 ... solo se comprime el codigo usando subrutinas ...pero da una reduccion del
12% del codigo. Todavia es pseudocode .... pero ya se ve como ensamblador.

Código:
; Mostrar Display usando charlieplexing
; version 1.1
; Reviciones:
; - Se corrigen algunos errores de escritura y se ordenan comentarios
;   para que se vea mas como ensamblador que como pseudocode
; - Usamos instruccion "Rotar a la derecha" ahorrando memoria de programa
;
; Definicion de variables:
; TMR0 = tiempo multiplexado
; B_Tris = Provicional de TRISB
; B_CHAR = Provicional de Caracter a mostrar en PORTB
; Digit_Mostrar = Contador del Digito a Mostrar del Display

Muestra:
;Muestra Caracteres en digito seleccionado

 Digit_Mostrar = 1   ; valores validos 1-8 
 
Caracter:
; Mostramos los 37 caracteres en digito seleccionado

  For i= 0 to 37
  { 
    w = 0
    call tabla_caracter ; Obtener Tris-Caracter 
                        ; regresa con w = Tris-Caracter
    Guarda w en B_Tris
    Guarda w en B_CHAR
    call Intercambia    ;ajuste de bits
    w = B_Tris          ; Pon altas-Z (entradas)
    TRISB = w
    w= B_CHAR           ; Muestra caracter en PuertoB
    PortB = w
    Demora tiempo de multiplexado (Dependendo del número de digitos)
        (1 Dig = demora 1000ms, ... 2 Dig = demora 500ms ...
         8 Dig = demora 125ms)
   }
   next i
  ¿Digit_Mostrar = 8?
    si: Regresa a Muestra
	no: Digit_Mostrar = Digit_Mostrar +1
	    Regresa a Caracter

; Subrutinas de ajuste de bits usadas por Intercambia
;

ADJ_3:
        btfss  B_CHAR,6   ; mueve bit6 a bit7
	bcf    B_CHAR,7   ;   si es 0
        btss   B_CHAR,5   ; mueve bit5 a bit6
        bcf    B_CHAR,6   ;   si es 0
        btsc   B_CHAR,5
	bsf    B_CHAR,6   ;   si es 1               
        retlw  0          ; Regresa a Intercambia

ADJ_4:
        btfss  B_CHAR,4   ; mueve  bit4 a bit5
        bcf    B_CHAR,5   ;   si es 0
        btsc   B_CHAR,4
	bsf    B_CHAR,5   ;   si es 1
        retlw  0          ; Regresa a Intercambia

ADJ_5:
        btfss  B_CHAR,3   ; mueve  bit3 a bit4        
	bcf    B_CHAR,4   ;   si es 0
	btsc   B_CHAR,3
	bsf    B_CHAR,4   ;   si es 1
        retlw  0          ; Regresa a Intercambia


ADJ_6:
        btfss  B_CHAR,2   ; mueve  bit2 a bit3
        bcf    B_CHAR,3   ;   si es 0
        btsc   B_CHAR,2
	bsf    B_CHAR,3   ;  si es 1
        retlw  0          ; Regresa a Intercambia


ADJ_7:
        btfss  B_CHAR,1   ; mueve  bit1 a bit2        
        bcf    B_CHAR,2   ;   si es 0
        btsc   B_CHAR,1
	bsf    B_CHAR,2   ;   si es 1
        retlw  0          ; Regresa a Intercambia

  
Intercambia:
; hace el manipuleo de los bits para hacer el charlieplexing
;  de acuerdo al Digito a mostrar en el Display
; Entra con:
;       Digit_Mostrar ajustado al Digito a mostrar en el Display
;
  copia Digit_Mostrar en temp
  temp = temp - 1
  w = temp

  Es w = 0
     si: ;Primer digito no hay necesidad de ajustar
	  retlw  0          ; Sal de Intercambia
     no: temp = temp - 1
         w = temp

  Es w = 0
     si: ; 2do digito hay necesidad de ajustar
          btfss  B_CHAR,6   ; mueve bit6 a bit7
          bcf    B_CHAR,7   ;   si es 0
          movf   B_CHAR,w   ; PORTB = B_CHR		       
          movwf  PORTB
	  retlw  0          ; Sal de Intercambia
     no: temp = temp - 1
         w = temp

  Es w = 0
     si: ; 3er digito hay necesidad de ajustar
          CALL   ADJ_3      ; mueve  bit6 a  bit7 y bit5 a bit6 
          bsf    B_CHAR,5   ; ajusta  bit5 a 1                            
          movf   B_CHAR,w   ; PORTB = B_CHR		            
          movwf  PORTB
	  retlw  0          ; Sal de Intercambia
     no: temp = temp - 1
         w = temp
 
 Es w = 0
     si: ; 4to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          bsf    B_CHAR,4  ; ajusta  bit4 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR
	  movwf  PORTB
	  retlw  0         ; Sal de Intercambia
     no: temp = temp - 1
         w = temp

 Es w = 0
     si: ; 5to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          bsf    B_CHAR,3  ; ajusta  bit3 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          movwf  PORTB
	  retlw  0         ; Sal de Intercambia
     no:  temp = temp - 1
          w = temp

  Es w = 0
      si: ; 6to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          CALL   ADJ_6     ; mueve  bit2 a bit3
          bsf    B_CHAR,2  ; ajusta  bit2 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          movwf  PORTB
	  retlw  0         ; Sal de Intercambia
      no: temp = temp - 1
          w = temp

 Es w = 0
     si: ; 7mo digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          CALL   ADJ_6     ; mueve  bit2 a bit3
          CALL   ADJ_7     ; mueve  bit1 a bit2
          bsf    B_CHAR,1  ; ajusta  bit1 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          movwf  PORTB
	  retlw  0         ; Sal de Intercambia
     no: temp = temp - 1
         w = temp
 
 Es w = 0
     si: ; 8vo digito hay necesidad de ajustar
         ; como se tienen que rotar todos los digitos usamos:
         RLF B_CHAR,1       ; rotamos B_CHAR a la izquierda (bit 0=?)
         ; en lugar de:
         ; CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
         ; CALL   ADJ_4     ; mueve  bit4 a bit5
         ; CALL   ADJ_5     ; mueve  bit3 a bit4
         ; CALL   ADJ_6     ; mueve  bit2 a bit3
         ; CALL   ADJ_7     ; mueve  bit1 a bit2
         ; btfss  B_CHAR,0  ; mueve  bit0 a bit1
         ; bcf    B_CHAR,1  ;    si es 0
	 ; btsc   B_CHAR,0
	 ; bsf    B_CHAR,1  ;    si es 1
          bsf    B_CHAR,0  ; ajusta  bit0 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          movwf  PORTB
	  retlw  0         ; Sal de Intercambia
     no:  retlw  1         ; señala error regresa con w=1 
      ;  "Digito a mostrar mayor excede el numero de digitos del display"
 

Adjuntos

  • Seudo-Code charlieplexing.txt
    8.5 KB · Visitas: 0
  • Seudo-Code 1ver1 charlieplexing.txt
    6.2 KB · Visitas: 0
Última edición:
-------------- Solo un poco de mejoras ---------
Disculpen por los errores (involuntarios) que tiene el Pseudocode (Las 2 versiones anteriores),
actualizo el Pseudo code a 1ver2
Código:
; Mostrar Display usando charlieplexing
; version 1.2     Fecha última edición : Abril 14,2012
;
; Futuras revisiones contempladas
;   - Añadir el despachador de tareas .... máquina de estado para no estar
;        esperando que trascurra el tiempo de multiplexado .... mientras
;        puede estar haciendo otras cosas útiles
;   - Añadir el control del Timer0, para el despachador de tareas
;   - Añadir los timers del software ... entre ellos el tiempo de multiplexado
;       haciendo mucho uso de Directivas #DEFINE, etc
;   - Hacer la Subrutina para recivir comandos por puerto serie
;   - Hacer la máquina de estados para interpretar comandos recividos.
;   - Hacer subrutina para leer dip-switches de configuración (4) de número de
;       displays
; 
;  Y lo más importante hacerlo caber en el PIC16F54 (25 localidades RAM,
;      y  512 Flash de memoria de program
;
; Reviciones:
; ver1.2
; - Se visualiza el añadir directivas #DEFINE , .Ifdef , .Ifndef , .endif
;      para reducir tamaño del programa generado por MPLAB de acuerdo con
;      #Define DisplayX  X  = Donde X = 1 a 8
; - Se corrigen algunos errores menores en subrutina "Intercambia"
; - Se agregan más comentarios para mejorar seguimiento
; ver 1.1
; - Se corrigen algunos errores de escritura y se ordenan comentarios
;   para que se vea mas como ensamblador que como pseudocode
; - Usamos instruccion "Rotar a la derecha" ahorrando memoria de programa
;
; Definicion de variables (en RAM):
; T_TMR0 = tiempo multiplexado
; B_Tris = Provicional de TRISB
; B_CHAR = Provicional de Caracter a mostrar en PORTB
; Digit_Mostrar = Contador del Digito a Mostrar del Display
; Cnt_Char = apuntador i en ciclo FOR de presentación de caracteres
;
; Tablas (en memoria del programa):
; tabla_caracter = Diccionario de caracteres que podemos
;                   mostrar en el display      
;
; Seleccionamos la directiva correcta de al número de digitos
;   para prueba empesamos con 2

; #DEFINE Digit1 1  ; número de digitos en el display = 1

#DEFINE Digit2 2  ; número de digitos en el display = 2

; #DEFINE Digit3 3  ; número de digitos en el display = 3
; #DEFINE Digit4 4  ; número de digitos en el display = 4
; #DEFINE Digit5 5  ; número de digitos en el display = 5
; #DEFINE Digit5 5  ; número de digitos en el display = 6
; #DEFINE Digit6 6  ; número de digitos en el display = 7
; #DEFINE Digit7 7  ; número de digitos en el display = 8
; #DEFINE Digit8 8  ; número de digitos en el display = 9

Muestra:
;Muestra Caracteres en digito seleccionado

 Digit_Mostrar = 1   ; valores validos 1-8 
 
Caracter:
; Mostramos los 37 caracteres del diccionario
;    en digito seleccionado por Digit_Mostrar

  For i= 0 to 37
  { 
    w = i
    call tabla_caracter ; Obtener Tris-Caracter 
                        ; regresa con w = Tris-Caracter
    Guarda w en B_Tris
    Guarda w en B_CHAR
 
    .ifndef DIGIT1
    call Intercambia    ; ajuste de bits en B_CHAR 
    .endif
	
    w = B_Tris          ; Pon altas-Z (entradas)
    TRISB = w
    w= B_CHAR           ; Muestra caracter en PuertoB
    PortB = w
    Demora tiempo de multiplexado (Dependendo del número de digitos)
        (1 Dig = demora 1000ms, ... 2 Dig = demora 500ms ...
         8 Dig = demora 125ms)
   }
   next i
 
.ifndef DIGIT1
     ¿Digit_Mostrar = 8?
      si: Regresa a Muestra
      no: Digit_Mostrar = Digit_Mostrar +1
.endif
      Regresa a Caracter

.ifndef DIGIT1
      {

; Subrutinas de ajuste de bits usadas por Intercambia
;

; Subrutina ADJ_3 mueve  bit6 a bit7 y bit5 a bit6 de B_CHAR
ADJ_3:
        btfss  B_CHAR,6   ; mueve bit6 a bit7
        bcf    B_CHAR,7   ;   si es 0
        btss   B_CHAR,5   ; mueve bit5 a bit6
        bcf    B_CHAR,6   ;   si es 0
        btsc   B_CHAR,5
        bsf    B_CHAR,6   ;   si es 1               
        retlw  0          ; Regresa a Intercambia

; Subrutina ADJ_4 mueve  bit4 a bit5  de B_CHAR
ADJ_4:
        btfss  B_CHAR,4   ; mueve  bit4 a bit5
        bcf    B_CHAR,5   ;   si es 0
        btsc   B_CHAR,4
        bsf    B_CHAR,5   ;   si es 1
        retlw  0          ; Regresa a Intercambia

; Subrutina ADJ_4 mueve  bit3 a bit4  de B_CHAR
ADJ_5:
        btfss  B_CHAR,3   ; mueve  bit3 a bit4        
        bcf    B_CHAR,4   ;   si es 0
        btsc   B_CHAR,3
        bsf    B_CHAR,4   ;   si es 1
        retlw  0          ; Regresa a Intercambia

; Subrutina ADJ_4 mueve  bit2 a bit3  de B_CHAR
ADJ_6:
        btfss  B_CHAR,2   ; mueve  bit2 a bit3
        bcf    B_CHAR,3   ;   si es 0
        btsc   B_CHAR,2
        bsf    B_CHAR,3   ;  si es 1
        retlw  0          ; Regresa a Intercambia


; Subrutina Intercambia
; hace el manipuleo de los bits para hacer el charlieplexing
;  de acuerdo al Digito a mostrar en el Display
; Entra con:
;       Digit_Mostrar ajustado al Digito a mostrar en el Display
;       B_CHAR = Caracter a mostrar en Digito-1 del Display
;
; Modifica:
;           Contenido de B_CHAR (Caracter a mostrar en Display)
;
; Usa subrutinas:
;           ADJ_3 = mueve  bit6 a bit7 y bit5 a bit6 de B_CHAR
;           ADJ_4 = mueve  bit4 a bit5 de B_CHAR
;           ADJ_5 = mueve  bit3 a bit4 de B_CHAR
;           ADJ_6 = mueve  bit2 a bit3 de B_CHAR
;
; Sale con :
;  w = 0   si no hay error
;  w = 1  "Digito a mostrar excede el numero de digitos del display"     
;

Intercambia:
  copia Digit_Mostrar en temp
  temp = temp - 1
  w = temp

  Es w = 0
     si: ;Primer digito no hay necesidad de ajustar
         retlw  0          ; Regresa a programa Principal
     no: temp = temp - 1
         w = temp

  Es w = 0
     si: ; 2do digito hay necesidad de ajustar
          btfss  B_CHAR,6   ; mueve bit6 a bit7
          bcf    B_CHAR,7   ;   si es 0
          movf   B_CHAR,w   ; PORTB = B_CHR		       
          retlw  0          ; Regresa a programa Principal
     no:  temp = temp - 1
          w = temp

  Es w = 0
     si: ; 3er digito hay necesidad de ajustar
          CALL   ADJ_3      ; mueve  bit6 a  bit7 y bit5 a bit6 
          bsf    B_CHAR,5   ; ajusta  bit5 a 1                            
          movf   B_CHAR,w   ; PORTB = B_CHR		            
          retlw  0          ; Regresa a programa Principal
     no:  temp = temp - 1
          w = temp
 
 Es w = 0
     si: ; 4to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          bsf    B_CHAR,4  ; ajusta  bit4 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR
          retlw  0         ; Regresa a programa Principal
     no:  temp = temp - 1
          w = temp

 Es w = 0
     si: ; 5to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          bsf    B_CHAR,3  ; ajusta  bit3 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          retlw  0         ; Regresa a programa Principal
     no:  temp = temp - 1
          w = temp

  Es w = 0
      si: ; 6to digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          CALL   ADJ_6     ; mueve  bit2 a bit3
          bsf    B_CHAR,2  ; ajusta  bit2 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          retlw  0         ; Regresa a programa Principal
      no: temp = temp - 1
          w = temp

 Es w = 0
     si: ; 7mo digito hay necesidad de ajustar
          CALL   ADJ_3     ; mueve  bit6 a bit7 y bit5 a bit6 
          CALL   ADJ_4     ; mueve  bit4 a bit5
          CALL   ADJ_5     ; mueve  bit3 a bit4
          CALL   ADJ_6     ; mueve  bit2 a bit3
          btfss  B_CHAR,1  ; mueve  bit1 a bit2        
          bcf    B_CHAR,2  ;   si es 0
          btsc   B_CHAR,1
          bsf    B_CHAR,2  ;   si es 1
          bsf    B_CHAR,1  ; ajusta  bit1 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          retlw  0         ; Regresa a programa Principal
     no:  temp = temp - 1
          w = temp
 
 Es w = 0
     si: ; 8vo digito hay necesidad de ajustar
          RLF B_CHAR,1     ; rotamos B_CHAR a la izquierda (bit 0=?)
          bsf    B_CHAR,0  ; ajusta  bit0 a 1
          movf   B_CHAR,w  ; PORTB = B_CHR		       
          retlw  0         ; Regresa a programa Principal
     no:  retlw  1         ; señala error regresa con w=1 
      ;  "Digito a mostrar excede el numero de digitos del display"

      }
.endif

En el programa real las comparaciones de w=0 con el previo no: temp = temp -1; w=temp
se sustituyeron con un simple CASE
Ejemplo:
Código:
	   movfw  Cnt_Digito   ; variable a probar del CASE
	   xorlw  8                  ; Comparación  ¿Es el 8vo digito? 
           btfss  STATUS,Z      ; 
	   goto   otrocase        ; no:  sigue al otro CASE
          ; si: nuestra variable es igual al CASE
          ------ el codigo va aqui ------
 
Última edición:
Atrás
Arriba