Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Autores:
Ing. Jorge R. Osio
Ing. Walter Aróztegui
Ing. José A. Rapallini
2. Software CodeWarrior………...………………...12
Tipos de datos Básicos Tamaño Rango sin signo Rango con signo
Char 8 bits 0 a 255 -128 a 127
Short int 16 bits 0 a 65535 -32768 a 32767
Int 16 bits 0 a 65535 -32768 a 32767
Long int 32 bits 0 a 4294967295 -2147483648 a 2147483647
Una variable se usa en mas de una expresión, pero algunas de estas expresiones
no requieren el tamaño de datos completo o con signo de la variable. En este caso el
ahorro se puede hacer definiendo la variable, o parte de la expresión que contiene la
variable, al tipo de datos mas apropiado.
Las variables pueden estar clasificadas por su alcance. Las variables globales
son accesibles por cualquier parte del programa y son almacenadas permanentemente en
RAM. Las variables locales son accesibles sólo por la función dentro de la cual son
declaradas y son almacenadas en la pila.
Las variables locales por consiguiente sólo ocupan RAM mientras se ejecuta la
función a la cual pertenecen. Su dirección absoluta no se puede determinar cuando el
código es compilado y conectado así es que son ubicadas en memoria relativa al puntero
de pila. Para acceder a las variables locales el compilador puede usar el modo de
direccionamiento del puntero de pila. Este modo de direccionamiento requiere un byte
adicional y un ciclo adicional para acceder a una variable, comparado a la misma
instrucción en el modo de direccionamiento indexado. Si el código requiere varios
accesos consecutivos a las variables locales, entonces el compilador transferirá el
puntero de pila al registro índice de 16 bits y usará direccionamiento indexado en lugar
de este. El acceso ' estático ' modificado puede ser usado con variables locales. Esto
causa que la variable local sea almacenada permanentemente en la memoria, como una
variable global, así es que el valor de la variable es preservado entre llamados a
funciones. Sin embargo la variable local estática es sólo accesible por la función dentro
de la cual está declarada.
Las variables globales son almacenadas permanentemente en memoria en una
dirección absoluta determinada cuando el código es conectado. La memoria ocupada
por una variable global no puede ser reusada por cualquier otra variable. De cualquier
manera las variables globales no están protegidas, ya que cualquier parte del programa
puede tener acceso a una variable global en cualquier momento. Esto da origen al
asunto de consistencia de datos para las variables globales de más de un simple byte de
tamaño. Esto quiere decir que los datos variables podrían ser corrompidos si una parte
de la variable proviene de un valor y el resto de la variable proviene de otro valor. Los
datos inconsistentes aparecen cuando una variable global es accedida (leída o escrita)
por una parte del programa y antes de que cada byte de la variable haya sido accedido el
programa se interrumpe. Esto se puede deber a una interrupción de hardware por
ejemplo, o un sistema operativo, si se usa uno. Si la variable global es entonces accedida
1.1.1.5. Bucles
Si un bucle debe ser ejecutado menos de 255 veces, se usa 'unsigned char' para
el tipo bucle contador. Si el bucle debe ser ejecutado más que 255 veces, se usa
'unsigned int' para el bucle contador. Esto es porque la aritmética de 8 bits es más
eficiente que la aritmética de 16 bits y la aritmética sin signo es mas eficiente que con
signo.
Si el valor del bucle contador es irrelevante, entonces es más eficiente el
contador para el decremento y comparar con cero que para incrementar y comparar con
un valor distinto de cero. Esta optimización no es efectiva si el bucle debe ser ejecutado
con el bucle contador igual a cero, como cuando el bucle contador se usa para indexar
un arreglo de elementos y el primer elemento debe ser accedido.
Si se usa el bucle contador en expresiones dentro del bucle, entonces se debe
guardar el tipo de datos más apropiado cada vez que se usa.
Cuando un bucle se ejecuta un número fijo de veces y aquel número es
pequeño, como tres o cuatro, es frecuentemente más eficiente no tener un bucle. En
lugar de eso, se escribe el código explícitamente tantas veces según lo solicitado. Esto
dará como resultado más líneas de código C pero a cambio generará menos código
ensamblador y puede ejecutarse mucho más rápido que un bucle. Los ahorros reales
variarán, dependiendo del código a ser ejecutado.
1.1.1.7. Ejemplos
Los siguientes ejemplos están basados en las siguientes definiciones de tipos:
1.1.1.7.1. Registro 1
Este es un ejemplo del uso inapropiado de „int‟ para la variable „i‟ que se usa
en el bucle contador y en el arreglo índice. El compilador es forzado a usar 16 bit con
signo aritméticos para calcular la dirección de cada elemento de dataPtr[ ]. Esta rutina
requiere 50 bytes de ROM y con 4 Iteraciones del bucle, ejecutados en 283 ciclos de
CPU.
En este ejemplo, los datos son copiados sin usar un bucle. Esta rutina requiere
23 bytes de ROM y se ejecuta en 36 ciclos de CPU. Ésta usa 10 bytes menos de ROM y
144 ciclos menos de CPU que en copia de datos 2. Si se copiaran 8 bytes, entonces este
método requeriría 10 bytes más de ROM que copia de datos 2, pero se ejecutaría en 280
ciclos menos de CPU. Aunque hay ahorros potenciales que se dan si la variable „buffer‟
está ubicada en la página directa, el compilador no saca mucha ventaja de ellos en este
caso.
1.1.1.7.5. Bucle
main ()
{
setbaud (BAUD9600);
printf ("Hola Mundo\n");
while (1)
;
}
Como se puede ver, éste es un programa muy simple que coloca el baud rate a
9600, usando una constante definida en el hc08.h. Esta constante es válida sólo si su
sistema usa un cristal de 10 Mhz para el HC08, así es que puede ser necesario
modificarlo. Luego, usa una función estándar C para imprimir "Hola Mundo," e ir a un
bucle infinito.
4) Al hacer click en el botón “siguiente” se pasa a una pantalla (Figura 5) que permite
adicionar cualquier archivo al proyecto, para incluirlo en el trabajo. En este caso, se
saltea está opción siguiendo a la próxima pantalla.
5) En la pantalla que se observa en la figura 6, se puede elegir la generación de código
de inicialización de los distintos periféricos asistida o no. En este caso se seleccionará la
generación de código asistida, por medio del aplicativo “Processor Expert”, que guía al
usuario paso a paso en la inicialización de los distintos periféricos del MCU elegido.
6) Al hacer click en el botón “Finalizar”, se generarán todos los archivos del proyecto,
se lanzará la pantalla principal de trabajo del mismo y se podrá ver una interfaz gráfica
con los pines y los distintos módulos que constituyen el MCU (Figura 7).
• Clock ---- Externo ---- 9,8304Mhz (lo inyectará el EVAL08QTY por pin OSC1).
• LVI ----- Habilitado ---- 3V trip point ----- LVI deshabilitado en modo STOP.
• Interrupciones Habilitadas.
• Vector de Reset apuntando a la etiqueta “_Startup”
• Pin de Reset externo no disponible.
Una vez que el sistema sortea las etapas de seguridad con éxito, aparecerá una
ventana (Erase and Program Flash?) preguntando por el borrado y grabación de la
FLASH antes de ingresar al modo de Debugging propiamente dicho. Se debe hacer
Click en el icono “Yes” para proceder a borrar y grabar el programa en la memoria
flash e ingresar al modo Debugging.
Ejemplo:
#pragma TRAP_PROC
void Mi_INTERRUPCION(void) {
...
}
NAMES END
SECTIONS
/* Z_RAM = READ_WRITE 0x0040 TO 0x00FF; */
/* 0xF0 to 0xFF reserved for Monitor stacking */
Z_RAM = READ_WRITE 0x0040 TO 0x00EF;
RAM = READ_WRITE 0x0100 TO 0x023F;
ROM = READ_ONLY 0x8000 TO 0xFDFF;
PLACEMENT
DEFAULT_ROM, ROM_VAR, STRINGS INTO ROM;
DEFAULT_RAM INTO RAM;
STACKSIZE 0x50
El bloque titulado “SECTIONS” sirve para asignar nombres a las áreas de memoria
del micro. En el ejemplo anterior, se han definido los nombres Z_RAM para la memoria
accesible con direccionamiento directo (hasta 0xFF), RAM para el resto de la memoria
RAM y ROM para la Flash, a excepción de las direcciones reservadas a los vectores.
El bloque titulado “PLACEMENT” permite ubicar las distintas secciones y
componentes del programa en áreas específicas de la memoria (RAM, Flash, etc)
La instrucción “STACKSIZE” define el tamaño del stack (0x50 bytes en el ejemplo).
Finalmente, las instrucciones “VECTOR” permiten especificar el contenido de los
vectores de interrupción del micro. La instrucción VECTOR tiene el siguiente formato:
VECTOR ADDRESS <dirección_vector> <contenido_vector>
Ejemplo:
VECTOR ADDRESS 0xFFFE 0x1000
VECTOR ADDRESS 0xFFFE StartUp
VECTOR ADDRESS 0xFFFE StartUp OFFSET 2
Un programa completo que use el Timebase para generar una onda cuadrada por
PTA7 tendría la siguiente forma:
#define TBON 2
#define TACK 8 //Ack del TBCR
#pragma TRAP_PROC
void Mi_INTERRUPCION (void)
{
TBCR |= TACK; // Acknowledge Int
PTA ^= 0x80; // invierte el estado de PTA7
}
Ejemplo:
#define TBON 2
#define TACK 8 //Ack del TBCR
#define ENABLE_INT {asm cli;}
#define DISABLE_INT {asm sei;}