lunes, 1 de octubre de 2012

Control PID de un levitador magnético


martes, 25 de septiembre de 2012

Control PI discreto de iluminacion con ATmega8a

La corriente eléctrica es una señal alterna sinusoidal como la de la figura:

  
Al pasar esta corriente eléctrica por el bombillo haremos que se ilumine al 100 %.

Si logramos hacer que la señal aplicada al bombillo se recorte como se ve en la figura siguiente, obtendremos valores de iluminación entre un 0% y un 100%.

           
El objetivo del proyecto es controlar el ángulo de disparo de un TRIAC que estará conectado en serie con el bombillo, mediante el controlador PI, de acuerdo a la intensidad de luz que perciba un sensor LDR.  

Etapas

Sensor y acondicionamiento


El sensor que se utiliza es una fotorresistencia, el cual varía su valor, dependiendo de la intensidad de luz que se le aplique. La señal de salida alta en caso de baja intensidad de luz, y baja en caso contrario.

Como la salida del sensor (LDR) varia de 0-2.5v y la entrada del microcontrolador ATMEGA8 recibe voltajes de 0-5v, amplificamos este valor en un factor de 2 para aprovechar la sensibilidad del ADC del microcontrolador.

Referencia



Este potenciómetro se utilizará para elegir la intensidad de luz de referencia que se requiera mantener. También irá conectado a uno de los pines ADC del microcontrolador.

Control



El esquema muestra las conexiones de los pines del microcontrolador.



Se utiliza este bloque de circuito para poder sincronizar el programa con la señal sinusoidal del circuito de potencia que se quiere controlar. Este circuito enviará un pulso de interrupción cuando la señal cruce por 0, iniciando la rutina correspondiente en el programa. 

Circuito de Potencia


El diodo D1 se utiliza para proteger al microcontrolador. El MOC3031 es un optotriac que enviará una señal de activación al triac U6 cuando la salida del circuito de control sea 1 lógico (5 V), lo cual hará que el bombillo se encienda; caso contrario, si la salida del circuito de control es 0 lógico (0 V) el bombillo no se encenderá.

Circuito Completo


Programa en Basic

$regfile = "m8def.dat"     'ATmega8
$crystal = 8000000         'Frecuencia de cristal=8 MHz
$hwstack = 32              'Hardware Stack
$swstack = 10              'Software Stack
Config Portb = Output      'Puerto B como salida
Config Portc = Input       'Puerto C como entrada

'Definicion de variables

Dim Sensor As Word         'Dato medido en ADC1=Sensor
Dim Ref As Word            'Dato medido en ADC0=Referencia
Dim Ek As Single           'Error actual
Dim Ek_1 As Single         'Error anterior
Dim Pk As Single           'Componente Proporcional
Dim Ik As Single           'Componente Integral actual
Dim Ik_1 As Single         'Componente integral anterior
Dim Kp As Single           'Ganancia Proporcional
Dim Ki As Single           'Ganancia Integral
Dim Uk As Single           'Señal de control
Dim Uk_dig As Word
Dim Ukmax As Word          'Límite máximo de Uk
Dim Ukmin As Word          'Límite mínimo de Uk
Dim T As Single            'Periodo de muestreo
Dim Rampa As Word          'Señal escalón

'Configuracion ADC

Config Adc = Single , Prescaler = Auto
'Configuracion de unterrupciones
Config Timer1 = Timer , Prescale = 256                      'Configuración TIMER1, f=31.25 KHz
On Compare1a Int_timer1                                     'Interrupción por comparación
Enable Compare1a                                            'Habilitación interrupción por comparación
Config Int1 = Low Level                                     'INT1, flanco de bajada
On Int1 Int_zc                                              'Interrupción externa INT1
Enable Int1                                                 'Habilitación INT1
Enable Interrupts                                           'Habilitación global de interrupciones

Timer1 = 0
Stop Timer1


'Programa principal
   Ik_1 = 0
   Ek_1 = 0
   T = 0.0083       'Periodo de muestreo T=1/120=0.0083 s
   Kp = 1
   Ki = 0.04
   Ukmax = 32       'Ukmax=32 escalones
   Ukmin = 0        'Ukmin=0 escalones
   Rampa = 0                                                'Reinicialización de Rampa
 Do
   nop              'Bucle infinito
 Loop

'Rutinas de interrupción

'Interrupcion cruce por cero
 Int_zc:
   Stop Timer1
   Timer1 = 0       'Reinicialización de Timer1
   Compare1a = 7                                            'Interrupción cada 7*1/31250= 0.22 ms = 7.5ms/32
   Rampa = 0        'Reiniciar Rampa en cada Interrupción
   Portb.0 = 0      'Señal a Triac =0
   'Obtensión de señales Referencia y Sensor
   Start Adc
   Ref = Getadc(0)
   Sensor = Getadc(1)
   Stop Adc
   'control PI
   Ek = Ref - Sensor
   Pk = Ek * Kp         ' P(k)=Kp*e(k)
   Ik = Ek + Ek_1       ' I(k)=I(k-1)+Ki*T*(e(k)+e(k-1))/2
   Ik = Ki * Ik
   Ik = Ik * T
   Ik = Ik / 2
   Ik = Ik + Ik_1
   Uk = Pk + Ik         ' u(k)=P(k)+I(k)
   Uk_dig = Uk + 1023   ' Ajuste en rango 0 - 32 escalones
   Uk_dig = Uk_dig / 63
   Ek_1 = Ek
   Ik_1 = Ik

   'limitación de rango de señal de control
   If Uk_dig > Ukmax Then
      Uk_dig = Ukmax
   Elseif Uk_dig < Ukmin Then
      Uk_dig = Ukmin
   End If

   Start Timer1
   Return

'Interrupcion Timer  cada 0.22 ms 32 escalones por semiciclo
  Int_timer1:
   Stop Timer1
   Timer1 = 0         'Reiniciar Timer1
   Rampa = Rampa + 1                                             'Incrementar rampa por cada interrupción

   'Determinar instante en que se envia señal al TRIAC
   If Uk_dig > Rampa Then
      Portb.0 = 0     'Señal a Triac = 0
   Else
      Portb.0 = 1     'Señal a Triac =1
   End If

   Return

End


Funcionamiento:

El funcionamiento del programa es el siguiente:

  • Se establece un nivel de iluminación deseado en un ambiente mediante el potenciómetro RV1.
  • La iluminación se debe mantener en el nivel deseado, ya sea por acción del bombillo o por fuentes externas, como por ejemplo luz solar.
  • El programa principal no realiza ninguna operación (se puede implementar alguna rutina). El control se realiza mediante una rutina de interrupción, por lo que no se tendrá al microcontrolador ocupado todo el tiempo.
  • La rutina de interrupción, que se ejecuta en cada cruce por cero de la señal de potencia, consiste en un control PI discreto, en el que se implementan los siguientes algoritmos:


         Se debe determinar el periodo de muestreo:

  La señal de interrupción se genera en los cruces por cero. En la rutina de interrupción se obtienen las   
  señales del ADC, por lo tanto el periodo de muestreo es igual al periodo de los pulsos de interrupción:

                                                    T=1 / (120 Hz) = 8.33 ms


  • Se implementa una segunda rutina de interrupción por comparación que se ejecuta 32 veces en cada semiciclo de la señal de potencia. En cada interrupción una señal rampa se incrementa en una unidad y se reinicia en cada interrupcion de cruce por cero.


                   Se determina el valor en Compare1a:

                   El programa debe ejecutar una interrupción por comparación cada:

                                          t = 7.5 ms / (32 escalones) = 0.23 ms

                   Frecuencia de Tiner1:

                                           f = 8 MHz/256 = 31.25 KHz

                   Valor numérico en Compare1a:

                                        Compare1a = 0.23 · 10^(-3) · 31.25 · 10^(3) = 7.18
                                        Compare1a = 7

  •  Esta señal rampa se utiliza junto a la señal de control para determinar el ángulo de disparo del TRIAC.

         La señal de control “Uk” puede tomar un valor 0 -32 dependiendo de la intensidad de 
         iluminación (mayor intensidad àUk mayor y viceversa). 

                Si Uk > Rampa entonces el TRIAC no se dispara, el bombillo no se enciende.
                Si Uk <= Rampa entonces el TRIAC se dispara, el bombillo se enciende.

           La forma de la señal en el bombillo, que varía según el ángulo de disparo, hace que el
           voltaje eficáz también varíe; en consecuencia la intensidad de iluminación se controla.



Control de Temperatura con ATmega8a

Este circuito se implementa para mantener un ambiente dentro de un rango de temperatura, el caso más práctico es una incubadora. El controlador se encargará de hacer las correcciones necesarias cuando el sistema no cumpla las condiciones deseadas.

En este caso, el controlador de temperatura tendrá el papel de calefactor; ya que cuando el ambiente disminuya su temperatura respecto de la mínima del rango, el controlador se activará y lo calentará hasta que la temperatura regrese al intervalo. Ahora, cuando el sector aumente su temperatura respecto de la máxima del rango, el circuito se desactivará dejando de calentarlo para que éste se enfríe con el ambiente.

Para proveer de calor el sector mencionado se utilizará un bombillo incandescente el cuál se encenderá y apagará según sea el caso.

Etapas

Sensor de temperatura y acondicionamiento:


El LM35 es un sensor de temperatura que, según la configuración utilizada, entrega en su salida 10mV/oC; es decir, si la temperatura es de 25oC entonces la salida será 0.25 V.

El ADC del microcontrolador trabaja en el rango 0 – 5V, por lo tanto, para aprovechar mejor su sensibilidad, debemos amplificar la señal del LM35 10 veces. Es por ello que se utiliza el amplificador activo que puede implementarse en la configuración mostrada o utilizar la configuración básica con un LM741.

Referencia


Este potenciómetro se utilizará para elegir la temperatura de referencia que se requiera mantener. También irá conectado a uno de los pines ADC del microcontrolador.

Control


El esquema muestra las conexiones de los pines del microcontrolador.

Circuito de potencia

El diodo D1 se utiliza para proteger al microcontrolador. El MOC3031 es un optotriac que enviará una señal de activación al triac U6 cuando la salida del circuito de control sea 1 lógico (5 V), lo cual hará que el bombillo se encienda; caso contrario, si la salida del circuito de control es 0 lógico (0 V), el bombillo no se encenderá.

Circuito Completo


Programa en Basic


'configuracion de microcontrolador
$regfile = "m8def.dat"                                      'Microcontrolador a utilizar
$crystal = 8000000                                          'Frecuencia de oscilador interno =8 MHz
$hwstack = 32                                               'Hardware stack
$swstack = 10                                               'Software stack
Config Timer1 = Timer , Prescale = 64                       'Configuracion de TIMER1 F=Fosc/64
Config Portb = Output                                       'Puerto B como salida
Config Adc = Single , Prescaler = Auto                      'Configuracion de ADC

'Definicion de variables
Dim Vsensor As Word
Dim Vref As Word
Dim Tmin As Single
Dim Tmax As Single
Dim Tempref As Single
Dim Temp As Single

'Habilitacion de interrupcion por comparacion
Enable Interrupts
On Compare1a Interrupcion
Enable Compare1a

'Inicializacion de registros para comparacion
Timer1 = 0
Compare1a = 62500

'Programa principal
Do
   nop                                                      'Ninguna operacion
Loop

'Rutina de interrupcion
Interrupcion:

 'Rutina de ADC
 Start Adc                                                  'Iniciar ADC
 Vsensor = Getadc(1)                                        'Vsensor= Canal 1 de ADC
 Vref = Getadc(0)                                           'Vref= Canal 0 de ADC
 Stop Adc

 'Convertir valor obtenido de ADC a valor de temperatura
 Temp = Vsensor / 1023
 Temp = Temp * 50
 Tempref = Vref / 1023
 Tempref = Tempref * 50

 'Establecimiento de rango de temperatura
 Tmin = Tempref - .5
 Tmax = Tempref + .5

 'Control de temperatura en rango Tempref +/- 2
 If Temp < Tmin Then                                        'Si Temp<Tmin encender foco
   Portb.6 = 1
   Portb.5 = 0
 Elseif Temp > Tmax Then                                    'Si Temp>Tmax apagar foco
   Portb.6 = 0
   Portb.5 = 0
   If Temp > 32 Then
      Portb.5 = 1
   End If
 End If

 'Reinicializacion de registros para comparacion
 Timer1 = 0
 Return                                                     'Retorno de interrupción

End                                                         'Fin de programa


Funcionamiento

El funcionamiento del programa es el siguiente:


  • Se establece una temperatura de referencia mediante el potenciómetro RV2.
  • la temperatura se mantendrá en el rango Trmpref +/- 0.1ºC.
  • La rutina principal no realiza ninguna operación, en este caso, pero si se desea se podría mantener al microcontrolador realizando alguna tarea y el control de temperatura sólo será una rutina de interrupción que no lo mantendrá ocupado todo el tiempo.
  • La rutina de interrupción se ejcutará cada 0.5s, hace falta calcular el valor en Comapare1a:  
                   Se requiere que la rutina de interrupción se ejecute cada 0.5 s.             

                               La frecuencia del TIMER1 es:

                                                       f=fosc/64=8 MHz / 64 = 125 KHz

         La cuenta en el TIMER1debe llegar hasta un cierto valor, inicializado en COMPARE1A,en 0.5 s 
         para  que se ejecute la rutina de interrupción.

                                                              N·T = N / f = 0.5 s
                                                                 N = 0.5 · f=0.5 · 125000
                                                                 N = 62500 
  • Se sensa la temperatura de referencia y de salida del sistema. El ADC lo convierte a un valor digital de 0 - 1023. Es necesario llevarlo al rango 0 - 50ºC:
                    El ADC entrega un valor 0 – 1023d correspondiente a 0 – 5 V respectivamente, entonces:

                                                               Vadc=Vin · 1023 / 5
                                                                 Vin = 5·Vadc / 1023

                      En este caso el valor numérico de temperatura es 10 veces el valor numérico de voltaje, 
                es decir: 
         
                                                                   Temp = 10· Vin

           
                               Por lo tanto para obtener el valor numérico de temperatura  se realizan las operaciones:

                                                               Temp=50·Vadc/1023
  • En la rutina de interrupción se observa  que se crea un rango Tmin - Tmax. en el que se quiere mantener al sistema. 

             Si Temp<Tmin entonces se enciende el bombillo para que actúe como calefactor.
             Si Temp>Tmax entonces se apaga el bombillo para que el ambiente baje de temperatura.

El proceso se repite indefinidamente, pero si por alguna razón se sobrepasara una temperatura máxima, en este caso 32ºC, se activará una alarma en el pin 5 del Puerto B.

sábado, 8 de octubre de 2011

Teclado Matricial 4x4


Es un dispositivo de entrada que consiste en un arreglo matricial de 16 teclas (pulsadores). Dispone de un conector SIL (Single In Line) de 8 pines: 4 filas y 4 columnas. La interconexión de los pulsadores es como se muestra en la imagen:


Cuando se presiona una tecla se conecta una fila con una columna. La manera de averiguar la tecla presionada consiste en enviar un nivel lógico a una de las filas (diferente al nivel de las filas restantes) y buscar la columna por la que se recibe el mismo nivel lógico. De esta manera se obtiene la fila y columna al igual que en una matriz. 

El diagrama de conexión típico al ATmega8 es el siguiente:

Las resistencias de 1K son necesarias para evitar hacer un cortocircuito accidental si se comparten los mismos pines del PIC con otro periférico, como por ejemplo un Display o un LCD.

Las resistencias de 10K son necesarias para asegurar el nivel lógico 0 en las entradas del ATmega8.

Algoritmo de búsqueda:
  • Los pines PD0-PD3 se configuran como Salidas. Los pines PD4-PD7 se configuran como Entradas.
  • Las filas del teclado se conectan a los pines PD0-PD3 y las columnas a los pines PD4-PD7.
  • Se envía “0” a todas las filas.
  • Se envía “1” a la primera fila.
  • Se verifica el nivel lógico en cada una de las columnas. Si se pulsó una tecla de la primera fila se obtendrá un “1” en la columna correspondiente.
  • Si no se encuentra un “1” (no se pulsó tecla en la primera fila) se envía un  “1” a la siguiente fila (a las filas restantes se envía “0”).
  • Se verifican las columnas en busca del nivel lógico “1”.
  • El procedimiento continúa hasta completar las 4 filas.
  • Conociendo la fila por la que se envió “1” y conociendo la columna por la que se recibe “1” se puede conocer la tecla pulsada.

 Programa Para ATmega8:

El programa lee la tecla pulsada en un teclado matricial 4x4 y simultáneamente muestra la última tecla pulsada en un display de 7 segmentos.

Diagrama de Conexión:


Programa en Assembler:

;---------------------------------------------------------
;Autor: LONELY113
; http://lonely113.blogspot.com
;
;Programa para control de teclado matricial 4x4 
;Adicionalmente muestra la tecla pulsada en un display
;Para teclado: Salida: PD0-PD3
;        Entradas: PD4-PD7
;Para Display: Salidas: PD1-PD7 (7 segmentos)
;        PC0 (Habilitacion catodo comun)
;Oscilador interno de 8 MHz
;---------------------------------------------------------
.nolist
.include "m8def.inc"
.list
.device  atmega8

.def KEY=r17
.def TEMP=r18
.def COUNT=r19
.def CHAR=r20
.def ROW=r21

.org 0x0000

; Inicializacion de stack

 ldi r16,HIGH(RAMEND)
 out SPH,r16
 ldi r16,LOW(RAMEND)
 out SPL,r16

; Fin inicializacion de Stack

; Inicio de programa

 ldi r16,0x01
 out DDRC,r16  ; PC0 como salida
 ldi r16,0x0F
 out DDRD,r16  ; PD7-PD4 como entradas, PD3-PD0 como salidas
 sbi PORTC,0
 clr TEMP
BEGIN: clr KEY
 inc KEY
 ldi ROW,0x01
 out PORTD,ROW
KEY_V: nop
 sbic PIND,4         ; Verifica tecla pulsada en columna 1
 rjmp CON2  ; Ir a CON2 si se pulsa tecla
 inc KEY  ; Incrementar KEY si no se pulsa tecla
 sbic PIND,5  ; Verifica tecla pulsada en columna 2
 rjmp CON2  ; Ir a CON2 si se pulsa tecla
 inc KEY  ; Incrementar KEY si no se pulsa tecla
 sbic PIND,6  ; Verifica tecla pulsada en columna 3
 rjmp CON2  ; Ir a CON2 si se pulsa tecla
 inc KEY  ; Incrementar KEY si no se pulsa tecla
 sbic PIND,7  ; Verifica tecla pulsada en columna 4
 rjmp CON2  ; Ir a CON2 si se pulsa tecla
 inc KEY  ; Incrementar KEY si no se pulsa tecla
 cpi KEY,0x11
 brbs 1,CON1  ; Comprueba si llego a ultima tecla
 lsl ROW
 out PORTD,ROW
 rjmp KEY_V
CON1: clr KEY
 rjmp DISP
CON2: mov TEMP,KEY ; Retiene ultima tecla pulsada
DISP: ldi r16,0xFF
 out DDRD,r16 ; PORTD como salida
 rcall CONV
 out PORTD,CHAR
 cbi PORTC,0
 nop
 sbi PORTC,0
 ldi r16,0x0F
 out DDRD,r16 ; PD7-PD4 como entradas, PD3-PD0 como salidas
 clr r16
 out PORTD,r16
 out PIND,r16
 rjmp BEGIN

; Subrutinas

CONV: ldi ZH,HIGH(2*TABLE)
 ldi ZL,LOW(2*TABLE)
 add ZL,TEMP
 lpm
 mov CHAR,r0
 ret

; Tabla de datos

TABLE:
.DB 0x00,0x0C,0xB6,0x9E,0xE2,0xCC,0xDA,0xFA,0xF2,0x0E,0xFE,0xDE,0xBC,0xEE,0x7E,0xF8,0x72

Archivos de Programa:

Multiplexaje de Display con Desplazamiento de Caracteres

Programa para ATmega8

El programa consiste en mostrar una serie caracteres en 4 display multiplexados.
los caracteres se muestran en grupos de 4 y se desplazan a la izquierda.

Diagrama de Conexión:




 
Funcionamiento:

  • Aplicando un procedimiento de multiplexaje se muestran los primeros 4 caraceres (CHAR1, CHAR2, CHAR3 y CHAR4). 
  • transcurrido un tiempo tal que el ojo pueda captar los caracteres se desplaza la cadena hacia la izquierda y se muestran los siguientes 4 caracteres (CHAR2, CHAR3, CHAR4, CHAR5). 
  • El programa comprueba si se mostraron todos los caracteres y cuando esto ocurre el proceso se repite.
Programa en Assembler:

;-----------------------------------------------------------
;Autor: LONELY113
;  http://lonely113.blogspot.com
;
;Programa para multiplexar 4 display
;Muestra mensaje LONELY113 con desplazamiento a la izquierda
;Salidas: Puerto D (PD1-PD7) 7 segmentos de display
;   Puerto A (PB0-PB3) habilitacion de display 
;Tipo de display: Catodo comun
;Calibrado para oscilador interno de 8 MHz
;-----------------------------------------------------------
.nolist
.include "m8def.inc"
.list
.device  atmega8

.def CHAR=r1
.def COUNT1=r20
.def COUNT2=r21
.def COUNT3=r22
.def TEMP=r18

.org 0x0000

;Inicializacion de Stack
 ldi r16,HIGH(RAMEND)
 out SPH,r16
 ldi r16,LOW(RAMEND)
 out SPL,r16
; Fin inicializacion de Stack

; Inicio de programa

 ldi r16,0xFF
 out DDRB,r16  ;PORTB como salida de habilitacion
 ldi r16,0xFF
 out DDRD,r16  ;PORTD como salida a displays
 ldi r16,0x0F
 out PORTB,r16 ;Deshabilitacion de displays
 clr r16
 out PORTD,r16
 clr CHAR
 ldi COUNT1,0xFF ; Inicia contadores
 ldi COUNT2,0x20
 ldi COUNT3,0x10
BEGIN: rcall CONVER
 out PORTD,TEMP
 cbi PORTB,3
 nop   ; Habilita display 4
 sbi PORTB,3
 inc CHAR
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,2
 nop   ; Habilita display 3
 sbi PORTB,2
 inc CHAR
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,1
 nop                ; Habilita display 2
 sbi PORTB,1
 inc CHAR
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,0
 nop   ; Habilita display 1
 sbi PORTB,0
 ldi r16,0x03
 sub CHAR,r16 
 dec COUNT1  ; Rutina de repeticion de 
 brne BEGIN  ; visualizacion de los 
 ldi COUNT1,0xFF ; 4 caracteres
 dec COUNT2
 brne BEGIN
 ldi COUNT1,0xFF
 ldi COUNT2,0x20
 dec COUNT3
 brne BEGIN
 ldi COUNT1,0xFF     ; Reinicia contadores
 ldi COUNT2,0x20
 ldi COUNT3,0x10
 inc CHAR         ; 4 siguientes caracteres
 ldi r16,0x0D
 cp r16,CHAR
 brne BEGIN
 clr CHAR
 rjmp BEGIN

; Subrutinas

CONVER: ldi ZH,HIGH(2*TABLE)
 ldi ZL,LOW(2*TABLE)
 add ZL,CHAR
 lpm
 mov TEMP,r0
 ret

TABLE:
.DB 0x00,0x00,0x00,0x70,0x7E,0x6E,0xF3,0x70
.DB 0xDC,0x0C,0x0C,0x9E,0x00,0x00,0x00,0x00

Archivos de Programa:
Descargar

Multiplexaje de Display

Programa para ATmega8


El programa consiste en controlar la visualización simultánea en 4 display cátodo común de 7 segmentos utilizando el método de multiplexaje para optimizar el uso de pines del ATmega8 .

Diagrama de Conexión:

Funcionamiento:
  • Se deshabilitan todos los displays (PB3-PB0=1111).
  • Se envía dato a mostrar al Puerto D (PD1-PD7).
  • Se habilita el display que mostrará el dato (Por ejemplo Display 1 a PB0=0).
  • Se deshabilita Display (Por ejemplo Display 1 a PB0=1).
  •  Se envía nuevo dato al Puerto D.
  • Se habilita el display que mostrará el dato.
  • Se deshabilita el display.
  • El procedimiento continúa hasta enviar 4 datos a los 4 displays.
  • Todo el proceso se repite endefinidamente. El ojo humano no llega a notar el parpadeo de los displays pues ocurre a muy alta frecuencia, por lo tanto se percibe como si los 4 displays estuvieran iluminados y mostrando los 4 datos simultáneamente.
  • El diagrama siguiente muestra el funcionamiento:

Programa en Assembler:

;-------------------------------------------------------
;Autor: LONELY113
; http://lonely113.blogspot.com
;
;Programa para multiplexar 4 display 
;y mostrar el mensaje HOLA
;Salidas: Puerto D (PD1-PD7) 7 segmentos de display
;   Puerto B (PB0-PB3) habilitacion de display 
;Tipo de display: Catodo comun
;Oscilador interno de 8 MHz
;-------------------------------------------------------
.nolist
.include "m8def.inc"
.list
.device  atmega8

.def TEMP=r17
.def DISP=r18

.org 0x0000
; Inicializacion de Stack
 ldi r16,HIGH(RAMEND)
 out SPH,r16
 ldi r16, LOW(RAMEND)
 out SPL,r16
; Fin inicializacion de Stack

; Inicio de programa
  
 ldi r16,0x0F  ; PORTB habilitacion de displays
 out DDRB,r16  ; PB3-PB0
 ldi r16,0xFF 
 out DDRD,r16  ; PORTB salida a displays
 ldi r16,0x0F
 out PORTB,r16 ; Deshabilita displays
BEGIN: ldi DISP,0x00
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,3
 nop
 sbi PORTB,3
 inc DISP
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,2
 nop
 sbi PORTB,2
 inc DISP
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,1
 nop
 sbi PORTB,1
 inc DISP
 rcall CONVER
 out PORTD,TEMP
 cbi PORTB,0
 nop
 sbi PORTB,0
 rjmp BEGIN

; subrutinas

CONVER: ldi ZH,HIGH(TABLE*2)
 ldi ZL,LOW(TABLE*2)
 add ZL,DISP
 lpm
 mov TEMP,r0
 ret

; Tabla en memoria de programa
TABLE:
.DB 0xEC,0x7E,0x70,0xEE

Archivos de programa:
Descargar