ATmega16 – Tablas

El manejo de tablas es de gran ayuda cuando se tiene gran cantidad de datos almacenados y necesitamos recuperarlos de una ubicación específica rápidamente.

Ejemplo:

// * Author: Victor Dueñas Guardia
// * Info: www.netzek.com
// @Ejemplo1:
// Ingresar un valor en Binario Natural y obtener su equivalente en Código Gray.
// Pseudocódigo:
// – Cargo el valor en binario.
// – Cargo la dirección de la tabla.
// – Calculo la posición del código correspondiente en gray.
.INCLUDE "M16DEF.INC" //Incluye definicion archivos ATmega16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16 //Coloco la Pila al final de la RAM
LDI R16,0B00001100 //Coloco en R16 la cifra binario (12)
LDI ZL,LOW(TablaGRAY<<1)
LDI ZH,HIGH(TablaGRAY<<1) //Cargo en el puntero Z la dirección de la tabla TablaGRAY
ADD ZL,R16
LDI R16,0
ADC ZL,R16
LPM R16,Z //Cargo el R16 el código correspondiente
BUCLE: RJMP BUCLE //Bucle infinito
//……TABLAS
.CSEG
.ORG 0x100
TablaGRAY:
.DB 0B0000,0B0001,0B0011,0B0010 //0,1,2,3
.DB 0B0110,0B0111,0B0101,0B0100 //4,5,6,7
.DB 0B1100,0B1101,0B1111,0B1110 //8,9,10,11
.DB 0B1010,0B1011,0B1001,0B1000 //12,13,14,15
view raw BinGray.asm hosted with ❤ by GitHub

El valor se ingresa en el registro R16 y nos devuelve el resultado en R16.

Simulación:

En la simulación podemos ver que cuando ingresamos el valor binario 12 nos devuelve el valor en gray 0B1010 ($0A).

Ejemplo:

// * Author: Victor Dueñas Guardia
// * Info: www.netzek.com
// @Ejemplo2:
// Ingresar un valor en Código Gray y obtener su equivalente en Binario Natural.
// Pseudocódigo:
// – Cargo el valor en código gray.
// – Inicio un puntero para la tabla en binario.
// – Calculo la primera posición.
// – Comparo si el valor en la posición es igual al puntero.
// – Si es igual se muestra el número.
// – Sino es igual calculo la siguiente posición y sigo comparando hasta encontrar la comparación correcta.
.INCLUDE "M16DEF.INC" //Incluye definición archivos ATmega16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16 //Coloco la Pila al final de la RAM
LDI R16,0B00000111 //Coloco en R16 la cifra GRAY (5)
LDI R18,0 //R18 es mi indice
Seguir:
MOV R17,R18
LDI ZL,LOW(TablaGRAY<<1)
LDI ZH,HIGH(TablaGRAY<<1) //Cargo en el puntero Z la dirección de la tabla TablaGRAY
ADD ZL,R17
LDI R17,0
ADC ZL,R17
LPM R17,Z //Cargo el R17 el código correspondiente
CP R17,R16 //Comparo con mi cifra GRAY
BRNE Incrementar
MOV R16,R17 //Obtengo mi cifra GRAY en R16
BUCLE: RJMP BUCLE //Bucle infinito
Incrementar:
INC R18
RJMP Seguir
;…….TABLAS
.CSEG
.ORG 0x100
TablaGRAY:
.DB 0B0000,0B0001,0B0011,0B0010 //0,1,2,3
.DB 0B0110,0B0111,0B0101,0B0100 //4,5,6,7
.DB 0B1100,0B1101,0B1111,0B1110 //8,9,10,11
.DB 0B1010,0B1011,0B1001,0B1000 //12,13,14,15
view raw GrayBin.asm hosted with ❤ by GitHub

Ingresamos el valor en el registro R16 y nos devuelve el resultado en R18.

Simulación:

El valor 5 ($07) en Código Gray (0111) ingresado en el registro R16 nos devuelve el valor $05 en el registro R18.

Ejemplo:

// * Author: Victor Dueñas Guardia
// * Info: www.netzek.com
// @Ejemplo3:
// Ingresar un número hexadecimal y devolver su equivalente en código de 7 Segmentos.
// Pseudocódigo:
// – Cargo el valor en hexadecimal.
// – Calculo la posición del valor de la posición.
// – Cargo el valor de la posición calculada.
.INCLUDE "M16DEF.INC" //Incluye definición archivos ATmega16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16 //Coloco la Pila al final de la RAM
LDI R16,$0B //Coloco en R16 la cifra hexadecimal
LDI R30,LOW(TablaHex7Seg<<1)
LDI R31,HIGH(TablaHex7Seg<<1) //Cargo en el puntero Z la dirección de la tabla TablaHex7Seg
ADD R30,R16
LDI R16,0
ADC R30,R16
LPM R16,Z //Cargo el R16 el código correspondiente
BUCLE: RJMP BUCLE //Bucle infinito
//……TABLAS
.CSEG
.ORG 0x100
TablaHex7Seg:
.DB 0B1111110,0B0110000 //0,1
.DB 0B1101101,0B1111001 //2,3
.DB 0B0110011,0B1011011 //4,5
.DB 0B1011111,0B1110000 //6,7
.DB 0B1111111,0B1111011 //8,9
.DB 0B1110111,0B0011111 //A,b
.DB 0B1001110,0B0111101 //C,d
.DB 0B1001111,0B1000111 //E,F
view raw Hex7Seg.asm hosted with ❤ by GitHub

El valor se ingresa en el registro R16 y nos devuelve el resultado en el mismo registro.

Simulación:

Se ha ingresado el valor $0B y nos devuelve su respectivo código 0B0011111 ($1F).

Las tablas de bifurcaciones son muy útiles cuando se quieren realizar distintos tipos de procedimientos a diferentes valores ingresados, por ejemplo cada vez que ingresemos el valor cero nos configure un puerto de entrada/salida, cuando ingresemos el valor uno nos devuelva el valor en código gray, cuando ingresemos el valor dos nos devuelva el valor en código de 7 segmentos …y así sucesivamente.

Ejemplo:

// * Author: Victor Dueñas Guardia
// * Info: www.netzek.com
// @Ejemplo4:
// Cada vez que se ingrese el valor uno incremente el registro R17
// Pseudocódigo:
// – Cargo el número de la tabla de bifurcación.
// – Cargo la dirección de la tabla de bifurcación.
// – Realiza la operación correspondiente en la tabla.
// – Continúa con el programa.
.INCLUDE "M16DEF.INC" //Incluye definicion archivos ATmega16
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16 //Coloco la Pila al final de la RAM
LDI R16,1 //Cargo el numero de la bifurcacion
LDI ZL,LOW(Bifurcaciones)
LDI ZH,HIGH(Bifurcaciones) //Cargo en el puntero Z la direccion de la tabla de bifurcaciones
ADD R16,R16
ADD ZL,R16
LDI R16,0
ADC ZH,R16
IJMP
Seguir:
BUCLE: RJMP BUCLE //Bucle infinito
//……PROCEDIMIENTOS
CERO:
NOP
JMP Seguir
UNO:
INC R17
JMP Seguir
DOS:
NOP
JMP Seguir
//……TABLAS
.CSEG
.ORG 0x100
Bifurcaciones:
JMP CERO
JMP UNO
JMP DOS

Simulación:

Vemos que el registro R17 solo se ha incrementado en uno ya que solo se ha ingresado el valor uno solo una vez.