Capitulo5. Sentencias de Control Programación del ATmega32 (español)

5
__________________________________________________________________________ITSP Documento traducido de la pagina AVRfreaks.net 1 Sentencias de Control de Programación 5.1 INTRODUCCIÓN Las instrucciones en ensamblador son pequeñas, por ejemplo out PortD,r15, la cual escribe el contenido del registro 15 en el Puerto D (el cual es un registro de 8 líneas de I/O). La mayoría de las instrucciones al ser ejecutadas dejan ciertos bits en cero o puestos a uno en el Registro de Estado [SREG (5Fh)]. Estos bits se pueden usar para instrucciones de salto o instrucciones aritméticas. Las instrucciones de salto se dirigen a ciertas líneas de código, si el microcontrolador está en un estado específico o solamente se dirigen a la próxima línea de código. Si la variable de conteo en un lazo no ha alcanzado el valor deseado, el microcontrolador tiene que repetir el ciclo. Aquí se tiene un ejemplo sencillo, que muestra las instrucciones aritméticas, de salto y de I/O. ldi r16,0 ;carga el registro 16 con cero for_loop: ;etiqueta para saltar inc r16 ;se incrementa registro r16 out PortD,r16 ;escribe el contenido de r16 a PortD cpi r16,10 ;compara el valor de r16 con 10 Brlo for_loop ;si no ha llegado a 10, salta a for_loop ;de lo contrario se dirige a la siguiente ;línea En el lazo, r16 actúa como un contador que se incrementa en cada iteración y se escribe en el puerto D (PortD). Cuando el contador alcanza el valor de 10, la instrucción brlo no saltará al inicio del lazo, solamente se dirigirá a la siguiente instrucción. Los comentarios son importantes, especialmente cuando no se tiene un diagrama de flujo. Un comentario se escribe en la misma línea de código con “;” antes del comentario. DIAGRAMA DE FLUJO El Diagrama de Flujo es una representación grafica del código, el estado del programa o incluso el contenido de la SRAM. Especialmente cuando se escribe código en ensamblador ellos son de gran ayuda, debido a que las instrucciones en ensamblador no siempre son del todo explicativas.

description

Sentencias de Control Programación del ATmega32 para la materia de Microcontroladores I

Transcript of Capitulo5. Sentencias de Control Programación del ATmega32 (español)

Page 1: Capitulo5. Sentencias de Control Programación del ATmega32 (español)

__________________________________________________________________________ITSP

Documento traducido de la pagina AVRfreaks.net 1

Sentencias de Control de Programación

5.1 INTRODUCCIÓN

Las instrucciones en ensamblador son pequeñas, por ejemplo out PortD,r15, la cual

escribe el contenido del registro 15 en el Puerto D (el cual es un registro de 8 líneas de I/O).

La mayoría de las instrucciones al ser ejecutadas dejan ciertos bits en cero o puestos a uno en el Registro de Estado [SREG (5Fh)]. Estos bits se pueden usar para instrucciones de salto o instrucciones aritméticas.

Las instrucciones de salto se dirigen a ciertas líneas de código, si el microcontrolador está en un estado específico o solamente se dirigen a la próxima línea de código. Si la variable de conteo en un lazo no ha alcanzado el valor deseado, el microcontrolador tiene que repetir el ciclo.

Aquí se tiene un ejemplo sencillo, que muestra las instrucciones aritméticas, de salto y de I/O.

ldi r16,0 ;carga el registro 16 con cero for_loop: ;etiqueta para saltar

inc r16 ;se incrementa registro r16 out PortD,r16 ;escribe el contenido de r16 a PortD cpi r16,10 ;compara el valor de r16 con 10 Brlo for_loop ;si no ha llegado a 10, salta a for_loop

;de lo contrario se dirige a la siguiente ;línea

En el lazo, r16 actúa como un contador que se incrementa en cada iteración y se

escribe en el puerto D (PortD). Cuando el contador alcanza el valor de 10, la

instrucción brlo no saltará al inicio del lazo, solamente se dirigirá a la siguiente

instrucción.

Los comentarios son importantes, especialmente cuando no se tiene un diagrama de flujo. Un comentario se escribe en la misma línea de código con “;” antes del comentario.

DIAGRAMA DE FLUJO

El Diagrama de Flujo es una representación grafica del código, el estado del programa o incluso el contenido de la SRAM. Especialmente cuando se escribe código en ensamblador ellos son de gran ayuda, debido a que las instrucciones en ensamblador no siempre son del todo explicativas.

Page 2: Capitulo5. Sentencias de Control Programación del ATmega32 (español)

__________________________________________________________________________ITSP

Documento traducido de la pagina AVRfreaks.net 2

Falso

Verdadero

contador = 0

for_loop

contador = contador + 1

PortD = counter

contador = 10?

siguiente línea

Aquí se tiene un ejemplo del diagrama de flujo:

5.2 ESTRUCTURA “CASE”

A menudo, por ejemplo cuando se reciben comando de valores vía el Puerto serial (USART), es necesario construir una estructura “case” que determine que función se necesita llamar. La estructura “case” compara un valor para varios casos de valores. Como la instrucción de salto no cambian las banderas, esto puede se implementado de la siguiente manera:

in r16,UDR cpi r16,0 breq case_0 cpi r16, 1 breq case_1 cpi r16, 2 breq case_2

; se obtiene el dato del USART ; se compara r16 con 0 ; Si son iguales salta a case_0 ; se compara r16 con 1 ; Si son iguales salta a case_1 ; se compara r16 con 2 ; Si son iguales salta a case_2 ; y así sucesivamente.

Page 3: Capitulo5. Sentencias de Control Programación del ATmega32 (español)

__________________________________________________________________________ITSP

Documento traducido de la pagina AVRfreaks.net 3

Después de que todos los casos se hayan comparado, tu puedes escribir la directiva “default” la cual se ejecutara si ninguno de los casos han resultado iguales. La estructura “case” no solamente compara valores unicos, también de pueden verificar un rango específico de valores o comparar cadenas. Aquí tenemos un ejemplo:

in r16, UDR chk_case_03: cpi r16, 4 brlo case_03 cpi r16, 20 brlo case_419 default: ;aquí va código por ;default

; se obtiene el dato del USART ; se compara r16 con 4 ; si el valor es menor a (0,1,2,3) salta a case_03 ; se compara r16 con 20 ; si el valor está entre (4 a 19), salta a case_419 ; si ninguno de los casos se llevan a cabo, ; se ejecuta el código por default

Para esté último ejemplo también se puede usar la instrucción brlt (salta si es menor

que) si estas usando números con signo.

5.3 ESTRUTURA “LOOP”

Para esta instrucción, no es necesario explicar esta instrucción si usamos lenguaje c o Pascal, pero para el ensamblador se requiere tomar con cuidado el conteo de registros.

Una versión flexible cuenta de cero hacia arriba hasta un número requerido de iteraciones. Es posible usar el registro de conteo

ldi r16,0 loop: out PortB,r16 inc r16 cpi r16,10 brne loop ldi r16, 0 loop1: inc r16 out PortB, r16 cpi r16, 10 brne loop1

; se limpia el registro r16 ; se escribe el conteo en el Puerto B ; se incrementa el contador ; se compara el contador con 10 ; Si es diferente a 10, salta a loop ; básicamente este lazo actúa como el ; anterior, con una excepción ; Encuéntrala!

¿Cual es la diferencia entre los dos lazos? El primer lazo incrementa el contador antes de escribirse en el Puerto B. Así los valores en el puerto van de 0..9. Mientras que en el segundo lazo se incrementa el contador antes de escribirse en el puerto B. Así que vemos los valores en el puerto que van de 1..10.

Page 4: Capitulo5. Sentencias de Control Programación del ATmega32 (español)

__________________________________________________________________________ITSP

Documento traducido de la pagina AVRfreaks.net 4

Recuerda que siempre que utilices los registros en los lazos de control, tendrás que incrementar el registro, de lo contrario entrarías a un ciclo infinito.

También podrás utilizar la operación de decremento en un ciclo “loop”.

ldi r16, 10 loop2: (inserta el código de lazo) dec r16 brne loop2

; se carga r16 con el numero deseado de iteraciones ; se ejecuta el lazo... ; se decrementa el contador de loop ; si no es cero, se repite el lazo

5.4 ESTRUTURA “WHILE”

El ciclo while()...do{} revisa si una condición resulta verdadera, de ser así se ejecutan las instrucciones que se encuentran dentro del lazo.

while1: in R16,PinD cpi r16,1 brne while1_end rcall port_is_1 rjmp while1 while1_end:

; mientras (PinD = 1) manda a llamar a subrutina port_is_1 ; lee el PinD y lo almacena en R16 ; lo compara con 1 ; Si no es verdadero, se va al final del lazo, ; de lo contrario, manda a llamar a port_is_1 ; al final la rutina port_is_1 se repite el lazo

Este tipo de lazo solamente ejecutara las instrucciones del lazo si la condición es verdadera, de lo contrario nunca hará nada.

El lazo do{}...while() ejecuta las instrucciones del lazo al menos una vez:

while2: rcall port_is_1 in r16, PinD cpi r16, 1 breq while2 while2_end:

; manda a llamar a la rutina port_is_1 mientras(PinD = 1) ; llama a rutina port_is_1 ; lee el PinD y lo almacena a R16 ; compara con 1 ; Si es verdadera, se repite el lazo ; si no es verdadera; se procede con el código siguiente

Estos dos ejemplos demuestran dos diferentes instrucciones de salto usados básicamente para lo mismo. “Saltos condicionales”.

5.5 MACROS EN ENSAMBLADOR AVR

Las macros son una mejor manera de hacer el código más legible, por ejemplo, si existe código que es a menudo reutilizado o si alrededor de 16 cálculos de bits se ejecutan.

Page 5: Capitulo5. Sentencias de Control Programación del ATmega32 (español)

__________________________________________________________________________ITSP

Documento traducido de la pagina AVRfreaks.net 5

Las macros en el ensamblador AVR pueden definirse en cualquier lugar dentro del código, pero tendrán que ser usadas después de ser definidas.

La directiva MACRO le dice al ensamblador que este es el inicio de una macro. Las macros pueden tomar hasta 10 argumentos. Estos argumentos son referidos como @0-@9 dentro de la definición de la macro. Estos argumentos son reemplazados durante el ensamblado pero no pueden cambiarse durante el tiempo de ejecución. Los argumentos que maneja el ensamblador son casi todos: enteros, caracteres, registros, direcciones de I/O, enteros de 16 o 32 bits, expresiones binarias, etc.

Macro definida antes de mandarla a llamar:

.macro ldi16 ldi @0,low(@2) ldi @1,high(@2) .endmacro ldi16 r16,r17,1024

;la macro se llama ldi16, utiliza dos registros de 8 bits ;se carga el primer argumento en (@0) con el byte bajo de @2 ;se carga el segundo argumento en (@1) y el byte alto de @2 ;fin de la macro ;se manda a llamar así: ldi16 arg 0,arg 1,arg 2 ;r16 = 0x00 r17 = 0x04

Mientras que esto no, macro se manda a llamar primero sin haber sido definida:

ldi16 r16, r17, 1024 .macro ldi16 ldi @0, low(@2) ldi @1, high(@2) .endmacro

; r16 = 0x00 r17 = 0x04

Lo siguiente deberá estar más claro:

ldi16 r16, r17, 1024 ; se ensambla así: ldi r16, 0 ldi r17, 0x04

; la macro trabaja así: ; ldi @0, low(@2) ; ldi @1, high(@2)

Las macros pueden también usarse para reemplazar los cálculos a 16 bits.

.macro addi subi @0,-(@1) .endmacro .macro addi16 subi @0, low(-@2) sbci @1, high(-@2) .endmacro

; Esta es la instrucción "Suma inmediata a registro” ; que no se encuentra en el set de instrucciones! ; La versión a 16 bits ”Suma inmediata a registro”

Las macros pueden ser más complejas, tener más argumentos. Si muchas macros se definen una sola línea, las últimas no podrán encontrarse.