Top Banner
CAPITULO 2 - PROGRAMACIÓN DE LOS MICROCONTROLADORES Usted seguramente sabe que no es suficiente sólo conectar el microcontrolador a los otros componentes y encender una fuente de alimentación para hacerlo funcionar, ¿verdad? Hay que hacer algo más. Se necesita programar el microcontrolador. Si cree que esto es complicado, está equivocado. Todo el procedimiento es muy simple. Basta con leer el texto para entender de lo que estamos hablando. 2.1 LENGUAJES DE PROGRAMACIÓN El microcontrolador ejecuta el programa cargado en la memoria Flash. Esto se denomina el código ejecutable y está compuesto por una serie de ceros y unos, aparentemente sin significado. Dependiendo de la arquitectura del microcontrolador, el código binario está compuesto por palabras de 12, 14 o 16 bits de anchura. Cada palabra se interpreta por la CPU como una instrucción a ser ejecutada durante el funcionamiento del microcontrolador. Todas las instrucciones que el microcontrolador puede reconocer y ejecutar se les denominan colectivamente Conjunto de instrucciones. Como es más fácil trabajar con el sistema de numeración hexadecimal, el código ejecutable se representa con frecuencia como una serie de los números hexadecimales denominada código Hex. En los microcontroladores PIC con las palabras de programa de 14 bits de anchura, el conjunto de instrucciones tiene 35 instrucciones diferentes. LENGUAJE ENSAMBLADOR
61

CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Feb 05, 2023

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

CAPITULO 2 - PROGRAMACIÓN DE LOS MICROCONTROLADORES

Usted seguramente sabe que no es suficiente sólo conectar el microcontrolador a los otros

componentes y encender una fuente de alimentación para hacerlo funcionar, ¿verdad? Hay que

hacer algo más. Se necesita programar el microcontrolador. Si cree que esto es complicado,

está equivocado. Todo el procedimiento es muy simple. Basta con leer el texto para entender

de lo que estamos hablando.

2.1 LENGUAJES DE PROGRAMACIÓN

El microcontrolador ejecuta el programa cargado en la memoria Flash. Esto se denomina el

código ejecutable y está compuesto por una serie de ceros y unos, aparentemente sin

significado. Dependiendo de la arquitectura del microcontrolador, el código binario está

compuesto por palabras de 12, 14 o 16 bits de anchura. Cada palabra se interpreta por la

CPU como una instrucción a ser ejecutada durante el funcionamiento del microcontrolador.

Todas las instrucciones que el microcontrolador puede reconocer y ejecutar se les denominan

colectivamente Conjunto de instrucciones. Como es más fácil trabajar con el sistema de

numeración hexadecimal, el código ejecutable se representa con frecuencia como una serie de

los números hexadecimales denominada código Hex. En los microcontroladores PIC con las

palabras de programa de 14 bits de anchura, el conjunto de instrucciones tiene 35

instrucciones diferentes.

LENGUAJE ENSAMBLADOR

Page 2: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Como el proceso de escribir un código ejecutable era considerablemente arduo, en

consecuencia fue creado el primer lenguaje de programación denominado ensamblador (ASM).

Siguiendo la sintaxis básica del ensamblador, era más fácil escribir y comprender el

código. Las instrucciones en ensamblador consisten en las abreviaturas con significado y a

cada instrucción corresponde una localidad de memoria. Un programa denominado ensamblador

compila (traduce) las instrucciones del lenguaje ensamblador a código máquina (código

binario).

HEste programa compila instrucción a instrucción sin optimización. Como permite controlar

en detalle todos los procesos puestos en marcha dentro del chip, este lenguaje de

programación todavía sigue siendo popular.

Ventajas de lenguajes de programación de alto nivel

A pesar de todos los lados buenos, el lenguaje ensamblador tiene algunas desventajas:

Incluso una sola operación en el programa escrito en ensamblador consiste en muchas

instrucciones, haciéndolo muy largo y difícil de manejar.

Cada tipo de microcontrolador tiene su propio conjunto de instrucciones que un

programador tiene que conocer para escribir un programa

Un programador tiene que conocer el hardware del microcontrolador para escribir un

programa

Programa escrito en C (El mismo programa compilado al código ensamblador):

Page 3: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Los lenguajes de programación de alto nivel (Basic, Pascal, C etc.) fueron creados con el

propósito de superar las desventajas del ensamblador. En lenguajes de programación de alto

nivel varias instrucciones en ensamblador se sustituyen por una sentencia. El programador

ya no tiene que conocer el conjunto de instrucciones o características del hardware del

microcontrolador utilizado. Ya no es posible conocer exactamente cómo se ejecuta cada

sentencia, de todas formas ya no importa. Aunque siempre se puede insertar en el programa

una secuencia escrita en ensamblador.

Si alguna vez ha escrito un programa para un microcontrolador PIC en lenguaje ensamblador,

probablemente sepa que la arquitectura RISC carece de algunas instrucciones. Por ejemplo,

no hay instrucción apropiada para multiplicar dos números. Por supuesto, para cada problema

hay una solución y éste no es una excepción gracias a la aritmética que permite realizar

las operaciones complejas al descomponerlas en un gran número operaciones más simples. En

este caso, la multiplicación se puede sustituir con facilidad por adición sucesiva (a x b =

a + a + a + ... + a). Ya estamos en el comienzo de una historia muy larga... No hay que

preocuparse al utilizar uno de estos lenguajes de programación de alto nivel como es C,

porque el compilador encontrará automáticamente la solución a éste problema y otros

similares. Para multiplicar los números a y b, basta con escribir a*b.

Page 4: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

LENGUAJE C

El lenguaje C dispone de todas las ventajas de un lenguaje de programación de alto nivel

(anteriormente descritas) y le permite realizar algunas operaciones tanto sobre los bytes

como sobre los bits (operaciones lógicas, desplazamiento etc.). Las características de C

pueden ser muy útiles al programar los microcontroladores. Además, C está estandarizado (el

estándar ANSI), es muy portable, así que el mismo código se puede utilizar muchas veces en

diferentes proyectos. Lo que lo hace accesible para cualquiera que conozca este lenguaje

sin reparar en el propósito de uso del microcontrolador. C es un lenguaje compilado, lo que

significa que los archivos fuentes que contienen el código C se traducen a lenguaje máquina

por el compilador. Todas estas características hicieron al C uno de los lenguajes de

programación más populares.

La figura anterior es un ejemplo general de lo que sucede durante la compilación de

programa de un lenguaje de programación de alto nivel a bajo nivel.

2.2 CARACTERÍSTICAS PRINCIPALES DEL MIKROC

A continuación vamos a presentar a los elementos principales del lenguaje mikroC

desarrollado por Mikroelektronika. Este lenguaje es muy similar al C estándar, no obstante

en determinados aspectos difiere del ANSI estándar en algunas características. Algunas de

estas diferencias se refieren a las mejoras, destinadas a facilitar la programación de los

microcontroladores PIC, mientras que las demás son la consecuencia de la limitación de la

arquitectura del hardware de los PIC. Aquí vamos a presentar características específicas

del lenguaje mikroC en la programación de los microcontroladores PIC. El término C se

utilizará para referirse a las características comunes de los lenguajes C y mikroC.

Page 5: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Este libro describe una aplicación muy concreta del lenguaje de programación C utilizado en

el compilador mikroC PRO for PIC. En este caso, el compilador se utiliza para la

programación de los microcontroladores PIC.

FASES DE COMPILACIÓN

El proceso de compilación consiste en varios pasos y se ejecuta automáticamente por el

compilador. Por con, un conocimiento básico del funcionamiento puede ser útil para entender

el concepto del lenguaje mikroC.

El archivo fuente contiene el código en mikroC que usted escribe para programar el

microcontrolador. El preprocesador se utiliza automáticamente por el compilador al

iniciarse el proceso de la compilación. El compilador busca las directivas del

preprocesador (que siempre empiezan por ‘#’) dentro del código y modifica el código fuente

de acuerdo con las directivas. En esta fase se llevan a cabo inclusión de archivos,

definición de constantes y macros etc, lo que facilita el proceso. Más tarde vamos a

describir estas directivas en detalle. El analizador sintáctico (parser) elimina toda la

información inútil del código (comentarios, espacios en blanco). Luego, el compilador

traduce el código a un archivo binario denominado archivo .mcl. El enlazador (linker)

recupera toda la información requerida para ejecutar el programa de los archivos externos y

la agrupa en un solo archivo (.dbg). Además, un proyecto puede contener más de un archivo

fuente y el programador puede utilizar funciones predefinidas y agrupadas dentro de los

archivos denominados librerías. Por último, el generador .hex produce un archivo .hex. Es

el archivo que se va a cargar en el microcontrolador.

El proceso entero de la compilación que incluye todos los pasos anteriormente descritos se

le denomina “building”.

Page 6: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

ESTRUCTURA DE PROGRAMA

La idea principal de escribir un programa en C es de “romper” un problema mayor en varios

trozos más pequeños. Supongamos que es necesario escribir un programa para el

microcontrolador para medir la temperatura y visualizar los resultados en un LCD. El

proceso de medición se realiza por un sensor que convierte temperatura en voltaje. El

microcontrolador utiliza el convertidor A/D para convertir este voltaje (valor analógico)

en un número (valor digital) que luego se envía al LCD por medio de varios conductores. En

consecuencia, el programa se divide en cuatro partes, de las que cada una corresponde a una

acción específica:

1. Activar y configurar el convertidor A/D incorporado;

2. Medir el valor analógico;

3. Calcular temperatura; y

4. Enviar los datos en el formato apropiado al LCD;

Los lenguajes de programación de alto nivel como es C le permiten solucionar este problema

con facilidad al escribir cuatro funciones que se ejecutarán cíclicamente sin parar.

La idea general es de dividir el problema en varios trozos, de los que cada uno se puede

escribir como una sola función. Todos los programas escritos en mikroC contienen por lo

menos una función llamada main() que encierra entre llaves {} las sentencias a ser

ejecutadas. Esto es la primera función a ser ejecutada al iniciarse la ejecución de

programa. Las otras funciones se pueden llamar dentro de la función main. En otras

palabras, podemos decir que la función main() es obligatoria, mientras que las demás son

opcionales. Si todavía no ha escrito un programa en C, es probable que todo le resulte

confuso. No se preocupe, acéptelo tal como es por el momento y más tarde entenderá la

sintaxis.

¡Y ahora, su primer programa ‘real’! La figura muestra la estructura de programa, señalando

las partes en las que consiste.

Page 7: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

La manera de escribir el código en C es muy importante. Por ejemplo, C difiere entre

minúsculas y mayúsculas, así que la función main() no se puede escribir MAIN() o Main().

Además, note que dos líneas del código dentro de la función terminan con un punto y coma.

En C todas las sentencias deben terminar con un punto y coma ‘;’, así el compilador puede

aislarlas y traducirlas a código máquina.

Page 8: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

COMENTARIOS

Los comentarios son las partes del programa utilizados para aclarar las instrucciones de

programa o para proporcionar más información al respecto. El compilador no hace caso a los

comentarios y no los compila al código ejecutable. Dicho de manera sencilla, el compilador

es capaz de reconocer los caracteres especiales utilizados para designar dónde los

comentarios comienzan y terminan y no hace nada de caso al texto entre ellos durante la

compilación. Hay dos tipos de tales caracteres. Unos designan los comentarios largos que

ocupan varias líneas de programa marcados por la secuencia especial /*...*/, mientras que

otros designan los comentarios cortos que caben en una sola línea //. Aunque los

comentarios no pueden afectar a la ejecución de programa, son tan importantes como

cualquier otra parte de programa. Aquí está el porqué... Con frecuencia es necesario

Page 9: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

mejorar, modificar, actualizar, simplificar un programa... No es posible interpretar

incluso los programas simples sin utilizar los comentarios.

2.3 TIPOS DE DATOS EN MIKROC

En el lenguaje C, los datos tienen un tipo, o sea, cada dato utilizado en el programa debe

tener su tipo especificado. Esto permite al compilador conocer el tamaño de dato (número de

bytes requerido en la memoria) y su representación. Hay varios tipos de datos que se pueden

utilizar en el lenguaje de programación mikroC dependiendo del tamaño de dato y del rango

de valores. La tabla muestra el rango de valores que los datos pueden tener cuando se

utilizan en su forma básica.

T I P O D ED A T O D E S C R I P C I Ó N T A M A Ñ O ( N Ú M E R O

D E B I T S ) R A N G O D E V A L O R E S

char Texto (caracteres) 8 de 0 a 255

int Valores enteros 16 de -32768 a 32767

float Valores en punto flotante 32 de ±1.17549435082·10-38 a

±6.80564774407·1038

doubleValores en punto flotante de doble precisión

32 de ±1.17549435082·10-38 a ±6.80564774407·1038

*Debido a las limitaciones impuestas por el hardware del microcontrolador, es imposible

alcanzar una mayor precisión de datos que la del tipo float. Por eso, el tipo double en

mikroC equivale al tipo float.

Al añadir un prefijo (calificador) a cualquier tipo de dato entero o carácter, el rango de

sus posibles valores cambia así como el número de los bytes de memoria necesarios. Por

defecto, los datos de tipo int son con signo, mientras que los de tipo char son sin signo.

El calificador signed (con signo) indica que el dato puede ser positivo o negativo. El

prefijo unsigned indica que el dato puede ser sólo positivo. Note que el prefijo es

opcional.

T I P O D ED A T O

T I P O D E D A T O C O NP R E F I J O

T A M A Ñ O ( N Ú M E R O D EB I T S ) R A N G O D E V A L O R E S

char signed char 8 de -128 a 128

int

unsigned int 16 de 0 a 65535

short int 8 de 0 a 255

signed short int 8 de -128 a 127

long int 32 de 0 a 4294967295

signed long int 32 de -2147483648 a2147483647

Page 10: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

TIPO ENTERO (INT)

Un entero es un número sin parte fraccionaria que puede estar expresado en los siguientes

formatos:

Hexadecimal (base 16): el número empieza con 0x (o 0X). Los enteros hexadecimales

consisten en los dígitos (de 0 a 9) y/o las letras (A, B, C,D, E, F). Por ejemplo:

‘0x1A’.

Decimal (base 10): el número consiste en los dígitos (de 0 a 9). El primer dígito no

puede ser 0. En este formato, se puede introducir el signo de número (‘+’ o ‘-’). Por

ejemplo: 569, -25, +1500.

Octal (base 8): los números se representan a base 8 utilizando sólo 8 dígitos (de 0 a

7). Los enteros octales empiezan con 0. Por ejemplo: ‘056’.

Binario: cuando un entero empieza con 0b (o 0B) se representan como una serie de bits

(‘0’ y ‘1’). Por ejemplo: 0B10011111

0x11 // formato hexadecimal equivale a decimal 1711 // formato decimal-152 // formato decimal011 // formato octal equivale a decimal 9 0b11 // formato binario equivale a decimal 3

TIPO PUNTO FLOTANTE (FLOAT)

El tipo punto flotante (float) se utiliza para los números reales con el punto decimal. Los

datos de tipo float se pueden representar de varias maneras. Un dato float es siempre

consigno (signed).

0. // = 0.0-1.23 // = -1.2323.45e6 // = 23.45 * 10^62e-5 // = 2.0 * 10^-53E+10 // = 3.0 * 10^10.09E34 // = 0.09 * 10^34

TIPO CARÁCTER (CHAR)

El tipo char es considerado como un entero por el compilador. No obstante, se utiliza

normalmente para los datos de tipo carácter. Un dato de tipo carácter está encerrado entre

comillas y codificado en un carácter ASCII.

59 // entero

'p' // carácter ASCII 'p'

Una secuencia de caracteres es denominada cadena (string). Las cadenas están encerradas

entre comillas dobles, por ejemplo:

"Presione el botón RA0"

Page 11: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

2.4 VARIABLES Y CONSTANTES

Definiciones

Una variable es un objeto nombrado capaz de contener un dato que puede ser modificado

durante la ejecución de programa. En C, las variables tienen tipo, que significa que es

necesario especificar el tipo de dato que se le asigna a una variable (int, float etc.).

Las variables se almacenan en la memoria RAM y el espacio de memoria que ocupan (en bytes)

depende de su tipo.

/* dos líneas de programa consecutivas. En la primera línea del programa

se define el tipo de variable */

int a = 1000; // Variable a es de tipo int y equivale a 1000

a = 15; // a equivale a 15

Una constante tiene las mismas características que una variable excepto el hecho de que su

valor asignado no puede ser cambiado durante la ejecución de programa. A diferencia de las

variables, las constantes se almacenan en la memoria Flash del microcontrolador para

guardar el mayor espacio posible de memoria RAM. El compilador las reconoce por el nombre y

el prefijo const. En mikroC, el compilador reconoce automáticamente el tipo de dato de una

constante, así que no es necesario especificar el tipo adicionalmente.

/* dos líneas de programa consecutivas */

const A = 1000 // el valor de la constante A está definido

A = 15; // ¡ERROR! no se puede modificar el valor de la constante

Cada variable o constante debe tener un identificador que lo distingue de otras variables y

constantes. Refiérase a los ejemplos anteriores, a y A son identificadores.

Reglas para nombrar

En mikroC, los identificadores pueden ser tan largos como quiera. Sin embargo, hay varias

restricciones:

Los identificadores pueden incluir cualquiera de los caracteres alfabéticos A-Z (a-

z), los dígitos 0-9 y el carácter subrayado '_'. El compilador es sensible a la

diferencia entre minúsculas y mayúsculas. Los nombres de funciones y variables se

escriben con frecuencia con minúsculas, mientras que los nombres de constantes se

escriben con mayúsculas.

Los identificadores no pueden empezar con un dígito.

Los identificadores no pueden coincidir con las palabras clave del lenguaje mikroC,

porque son las palabras reservadas del compilador.

El compilador mikroC reconoce 33 palabras clave:

Page 12: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

MI KR OC - P AL AB RA S CL AV E

absolute data if return typedef

asm default inline rx typeid

at delete int sfr typename

auto do io short union

bit double long signed unsigned

bool else mutable sizeof using

break enum namespace static virtual

case explicit operator struct void

catch extern org switch volatile

char false pascal template while

class float private this

code for protected throw

const friend public true

continue goto register try

Ejemplos de los identificadores válidos e inválidos:

temperatura_V1 // OK

Presión // OK

no_corresponder // OK

dat2string // OK

SuM3 // OK

_vtexto // OK

7temp // NO -- no puede empezar con un número

%más_alto // NO -- no pueden contener caracteres especiales

if // NO -- no puede coincidir con una palabra reservada

j23.07.04 // NO -- no puede contener caracteres especiales (punto)

nombre de variable // NO -- no puede contener espacio en blanco

Declaración de variables

Cada variable debe ser declarada antes de ser utilizada en el programa. Como las variables

se almacenan en la memoria RAM, es necesario reservar el espacio para ellas (uno, dos o más

bytes). Al escribir un programa, usted sabe qué tipo de datos quiere utilizar y qué tipo de

datos espera como resultado de una operación, mientras que el compilador no lo sabe. No se

olvide de que el programa maneja las variables con los nombres asignados. El compilador las

reconoce como números en la memoria RAM sin conocer su tamaño y formato. Para mejorar la

legibilidad de código, las variables se declaran con frecuencia al principio de las

funciones:

Page 13: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

<tipo> variable;

Es posible declarar más de una variable de una vez si tienen el mismo tipo.

<tipo> variable1, variable2, variable3;

Aparte del nombre y del tipo, a las variables se les asignan con frecuencia los valores

iniciales justamente enseguida de su declaración. Esto no es un paso obligatorio, sino ‘una

cuestión de buenas costumbres’. Se parece a lo siguiente:

unsigned int peso; // Declarar una variable llamada peso

peso = 20; // Asignar el valor 20 a la variable peso

Un método más rápido se le denomina declaración con inicialización (asignación de los

valores iniciales):

unsigned int peso = 20; // peso está declarado y su valor es 20

Si hay varias variables con el mismo valor inicial asignado, el proceso se puede

simplificar:

unsigned int peso1 = peso2 = peso3 = 20;

int valor_inicial = un_mínimo_de_petróleo = 0;

Tenga cuidado de no declarar la misma variable otra vez dentro de la misma función.

Puede modificar el contenido de una variable al asignarle un nuevo valor tantas veces

que quiera

Al declarar una variable, siempre piense en los valores que la variable tendrá que

contener durante la ejecución de programa. En el ejemplo anterior, peso1 no se puede

representar con un número con punto decimal o un número con valor negativo.

Declaración de constantes

Similar a las variables, las constantes deben ser declaradas antes de ser utilizadas en el

programa. En mikroC, no es obligatorio especificar el tipo de constante al declararla. Por

otra parte, las constantes deben ser inicializadas a la vez que se declaran. El compilador

reconoce las constantes por su prefijo const utilizado en la declaración. Dos siguientes

declaraciones son equivalentes:

const int MINIMUM = -100; // Declarar constante MINIMUM

const MINIMUM = -100; // Declarar constante MINIMUM

Las constantes pueden ser de cualquier tipo, incluyendo cadenas:

const T_MAX = 3.260E1; // constante de punto flotante T_MAX

Page 14: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

const I_CLASS = 'A'; // constante carácter I_CLASS

const Mensaje = "Presione el botón IZQUIERDA"; // constante de cadena Mensaje

Las constantes de enumeración son un tipo especial de constantes enteras que hace un

programa más comprensible al asignar los números ordinales a las constantes. Por defecto,

el valor 0 se asigna automáticamente a la primera constante entre llaves, el valor 1 a la

segunda, el valor 2 a la tercera etc.

enum surtidores {AGUA,GASÓLEO,CLORO}; // AGUA = 0; GASÓLEO = 1; CLORO = 2

Es posible introducir directamente el valor de una constante dentro de la lista de

enumeraciones. El incremento se detiene al asignar un valor a un elemento de matriz,

después se reinicia a partir del valor asignado. Vea el siguiente ejemplo:

enum surtidores {AGUA,GASÓLEO=0,CLORO}; // AGUA = 0; GÁSOLEO = 0; CLORO = 1

Las constantes de enumeración se utilizan de la siguiente manera:

int Velocidad_de_ascensor

enum motor_de_ascensor {PARADA,INICIO,NORMAL,MÁXIMO};

Velocidad_de_ascensor = NORMAL; // Velocidad_de_ascensor = 2

Definir los nuevos tipos de datos

La palabra clave typedef le permite crear con facilidad los nuevos tipos de datos.

typedef unsigned int positivo; // positivo es un sinónimo para el tipo sin signo int

positivo a,b; // Variables a y b son de tipo positivo

a = 10; // Variable a equivale a 10

b = 5; // Variable b equivale a 5

Ámbito de variables y constantes

Una variable o una constante es reconocida por el compilador en base de su identificador.

Un identificador tiene significado si el compilador lo puede reconocer. El ámbito de una

variable o una constante es el rango de programa en el que su identificador tiene

significado. El ámbito es determinado por el lugar en el que se declara una variable o una

constante. Intentar acceder a una variable o una constante fuera de su ámbito resulta en un

error. Una variable o una constante es invisible fuera de su ámbito. Todas las variables y

constantes que pensamos utilizar en un programa deben ser declaradas anteriormente en el

código. Las variables y constantes pueden ser globales o locales. Una variable global se

declara en el código fuente, fuera de todas las funciones, mientras que una variable local

se declara dentro del cuerpo de la función o dentro de un bloque anidado en una función.

Page 15: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

A las variables globales se les puede acceder de cualquiera parte en el código, aún dentro

de las funciones con tal de que sean declaradas. El ámbito de una variable global está

limitado por el fin del archivo fuente en el que ha sido declarado.

El ámbito de variables locales está limitado por el bloque encerrado entre llaves {} en el

que han sido declaradas. Por ejemplo, si están declaradas en el principio del cuerpo de

función (igual que en la función main) su ámbito está entre el punto de declaración y el fin

de esa función. Refiérase al ejemplo anterior. A las variables locales declaradas en main()

no se les puede acceder desde la Función_1 y al revés.

Un bloque compuesto es un grupo de declaraciones y sentencias (que pueden ser bloques también) encerradas entre llaves.

Un bloque puede ser una función, una estructura de control etc. Una variable declarada dentro de un bloque se considera

local, o sea, ‘existe’ sólo dentro del bloque. Sin embargo, las variables declaradas fuera del ámbito todavía son visibles.

Aunque las constantes no pueden ser modificadas en el programa, siguen las mismas reglas

que las variables. Esto significa que son visibles dentro de su bloque a excepción de las

constantes globales (declaradas fuera de cualquier función). Las constantes se declaran

normalmente en el inicio del código fuera de cualquier función (como variables globales).

Clases de almacenamiento

Las clases de almacenamiento se utilizan para definir el ámbito y la vida de variables,

constantes y funciones dentro de un programa. En mikroC se pueden utilizar diferentes

clases de almacenamiento:

auto es una clase de almacenamiento por defecto para las variables locales, así que

se utiliza raramente. Se utiliza para definir que una variable local tiene duración

local. La clase de almacenamiento auto no se puede utilizar con variables globales.

Page 16: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

static es una clase de almacenamiento por defecto para las variables globales.

Especifica que una variable es visible dentro del archivo. A las variables locales

declaradas con el prefijo static se les puede acceder dentro del archivo fuente (o

sea se comportan como variables globales).

extern: la palabra clave extern se utiliza cuando el programa está compuesto por

diferentes archivos fuente. Esto le permite utilizar una variable, una constante o

una función declarada en otro archivo. Por supuesto, para compilar y enlazar este

archivo correctamente, el mismo debe ser incluido en su proyecto. En los siguientes

ejemplos, el programa consiste en dos archivos: File_1 y File_2. El File_1 utiliza una

variable y una función declaradas en File_2.

File 1:

extern int cnt; // Variable cnt es visible en File_1extern void hello(); // Función hello()se puede utilizar en File_1

void main(){ PORTA = cnt++; // Cualquier modificación de cnt en File_1 será visible en File_2 hello(); // Función hello()se puede llamar desde aquí}

File 2:

int cnt = 0; void hello();void hello(){ // Modificaciones que afectan a la. // cnt en File_1 son visibles aquí .}

2.5 OPERADORES

Un operador es un símbolo que denota una operación aritmética, lógica u otra operación

particular. Dicho de manera sencilla, varias operaciones aritméticas y lógicas se realizan

por medio de los operadores. Hay más de 40 operaciones disponibles en el lenguaje C, pero

se utiliza un máximo de 10-15 de ellas en práctica. Cada operación se realiza sobre uno o

más operandos que pueden ser variables o constantes. Además, cada operación se caracteriza

por la prioridad de ejecución y por la asociatividad.

OPERADORES ARITMÉTICOS

Los operadores aritméticos se utilizan en las operaciones aritméticas y siempre devuelven

resultados numéricos. Hay dos tipos de operadores, los unitarios y los binarios. A

diferencia de las operaciones unitarias que se realizan sobre un operando, las operaciones

binarias se realizan sobre dos operandos. En otras palabras, se requieren dos números para

ejecutar una operación binaria. Por ejemplo: a+b o a/b.

OP ER AD OR O PE RA CI ÓN

+ Adición

Page 17: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

- Resta

* Multiplicación

/ División

% Resto de la división

int a,b,c; // Declarar 3 enteros a, b, ca = 5; // Inicializar ab = 4; // Inicializar bc = a + b; // c = 9c = c%2; // c = 1. Esta operación se utiliza con frecuencia // para comprobar la paridad. En este caso, el // resultado es 1 lo que significa que la variable // es un número impar

OPERADORES DE ASIGNACIÓN

Hay dos tipos de asignación en el lenguaje C:

Los operadores simples asignan los valores a las variables utilizando el carácter

común '='. Por ejemplo: a =8

Las asignaciones compuestas son específicas para el lenguaje C. Consisten en dos

caracteres como se muestra en la tabla a la derecha. Se utilizan para simplificar la

sintaxis y habilitar la ejecución más rápida.

OP ER AD OREJ EM PL O

Expresión Equivalente

+= a += 8 a = a + 8

-= a -= 8 a = a - 8

*= a *= 8 a = a * 8

/= a /= 8 a = a / 8

%= a %= 8 a = a % 8

int a = 5; // Declarar e inicializar la variable aa += 10; // a = a + 10 = 15

OPERADORES DE INCREMENTO Y DECREMENTO

Las operaciones de incremento y decremento por 1 se denotan con "++" y "--". Estos

caracteres pueden preceder o seguir a una variable. En primer caso (++x), la variable x

será incrementada por 1 antes de ser utilizada en la expresión. De lo contrario, la

variable se utilizará en la expresión antes de ser aumentada por 1. Lo mismo se aplica a la

operación de decremento.

OP ER AD OR EJ EM PL O DE SC RI PC IÓ N

++ ++a Variable "a" es incrementada

por 1a++

Page 18: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

----b Variable "a" es decrementada

por 1b--

int a, b, c;a = b = 5;c = 1 + a++; // c = 6b = ++c + a // b = 7 + 6 = 13

OPERADORES RELACIONALES

Los operadores relacionales se utilizan en comparaciones con el propósito de comparar dos

valores. En mikroC, si una expresión es evaluada como falsa (false), el operador devuelve

0, mientras que si una oración es evaluada como verdadera (true), devuelve 1. Esto se

utiliza en expresiones tales como ‘si la expresión es evaluada como verdadera, entonces...’

OP ER AD OR DE SC RI PC IÓ N E JE MP LO CO ND IC IÓ N DE V ER AC ID AD

> mayor que b > a si b es mayor que a

>= mayor o igual que a >= 5 si a es mayor o igual que 5

< menor que a < b si a es menor que b

<= menor o igual que a <= b si a es menor o igual que b

== igual que a == 6 si a es igual que 6

!= desigual que a != b si a es desigual que b

int prop;int var = 5;prop = var < 10; // Expresión es evaluada como verdadera, prop = 1

OPERADORES LÓGICOS

Hay tres tipos de operaciones lógicas en el lenguaje C: Y (AND) lógico, O (OR) lógico y

negación - NO (NOT) lógico. Los operadores lógicos devuelven verdadero (1 lógico) si la

expresión evaluada es distinta de cero. En caso contrario, devuelve falso (0 lógico) si la

expresión evaluada equivale a cero. Esto es muy importante porque las operaciones lógicas

se realizan generalmente sobre las expresiones, y no sobre las variables (números)

particulares en el programa. Por lo tanto, las operaciones lógicas se refieren a la

veracidad de toda la expresión.

Por ejemplo: 1 && 0 es igual a (expresión verdadera) && (expresión falsa). El resultado 0,

o sea - Falso en ambos casos.

OP ER AD OR F UN CI ÓN

&& Y

|| O

! NO

Page 19: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

OPERADORES DE MANEJO DE BITS

A diferencia de las operaciones lógicas que se realizan sobre los valores o expresiones,

las operaciones de manejo de bits se realizan sobre los bits de un operando. Se enumeran en

la siguiente tabla:

OP ER AD OR DE SC RI PC IÓ N EJ EM PL O RE SU LT AD O

~ Complemento a uno a = ~b b = 5 a = -5

<< Desplazamiento a la izquierda a = b << 2 b = 11110011 a =11001100

>> Desplazamiento a la derecha a = b >> 2 b = 11110011 a =00011110

& Y lógico para manejo de bits c = a & ba = 11100011

b = 11001100

c =11000000

| O lógico para manejo de bits c = a | ba = 11100011

b = 11001100

c =11101111

^ EXOR lógico para manejo debits c = a ^ b

a = 11100011

b = 11001100

c =00101111

Note que el resultado de la operación de desplazamiento a la derecha depende del signo de la variable. En caso de que el

operando se aplique a una variable sin signo o positiva, se introducirán los ceros en el espacio vacío creado por

desplazamiento. Si se aplica a un entero con signo negativo, se introducirá un 1 para mantener el signo correcto de la

variable.

¿CÓMO UTILIZAR LOS OPERADORES?

Aparte de los operadores de asignación, dos operadores no deben estar escritos uno

junto al otro.

x*%12; // esta expresión generará un error

Cada operador tiene su prioridad y asociatividad como se muestra en la tabla:

Similar a las expresiones aritméticas, los operadores se agrupan juntos por medio de

paréntesis. Primero se calculan las expresiones encerradas entre paréntesis. Si es

necesario, se pueden utilizar los paréntesis múltiples (anidados).

PR IO RI DA D O PE RA DO RE S AS OC IA TI VI DA D

Alta () [] -> . de izquierda a derecha

! ~ ++ -- +(unitario) -(unitario) *Puntero&Puntero de derecha a izquierda

* / % de izquierda a derecha

+ - de izquierda a derecha

< > de izquierda a derecha

< <= > >= de izquierda a derecha

Page 20: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

== != de izquierda a derecha

& de izquierda a derecha

^ de izquierda a derecha

| de izquierda a derecha

&& de izquierda a derecha

|| de derecha a izquierda

?: de derecha a izquierda

Baja = += -= *= /= /= &= ^= |= <= >= de izquierda a derecha

int a, b, res;a = 10;b = 100;res = a*(a + b); // resultado = 1100res = a*a + b; // resultado = 200

CONVERSIÓN DE TIPOS DE DATOS

Algunas operaciones implican conversión de datos. Por ejemplo, si divide dos valores

enteros, hay una alta posibilidad de que el resultado no sea un entero. El mikroC realiza

una conversión automática cuando se requiera.

Si dos operandos de tipo diferente se utilizan en una operación aritmética, el tipo de

operando de la prioridad más baja se convierte automáticamente en el tipo de operando de la

prioridad más alta. Los tipos de datos principales se colocan según el siguiente orden

jerárquico:

La autoconversión se realiza asimismo en las operaciones de asignación. El resultado de la

expresión de la derecha del operador de la asignación siempre se convierte en el tipo de la

variable de la izquierda del operador. Si el resultado es de tipo de la prioridad más alta,

se descarta o se redondea para coincidir con el tipo de la variable. Al convertir un dato

real en un entero, siempre se descartan los números que siguen al punto decimal.

int x; // A la variable x se le asigna el tipo integer (un entero)

x = 3; // A la variable x se le asigna el valor 3

x+ = 3.14; // El valor 3.14 se agrega a la variable x al

// realizar la operación de asignación

/* El resultado de la adición es 6 en vez de 6.14, como era de esperar.

Para obtener el resultado esperado sin descartar los números que siguen al

Page 21: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

punto decimal, se debe declarar x como un punto flotante. */

Para realizar una conversión explícita, antes de escribir una expresión o una variable hay

que especificar el tipo de resultado de operación entre paréntesis.

double distancia, tiempo, velocidad;

distancia = 0.89;

tiempo = 0.1;

velocidad = (int)(a/b); // c = (int)8.9 = 8.0

velocidad = ((int)a)/b; // c = 0/0.1 = 0.0

2.6 ESTRUCTURAS DE CONTROL

ESTRUCTURAS CONDICIONALES

Las condiciones son ingredientes comunes de un programa. Las condiciones permiten ejecutar

una o varias sentencias dependiendo de validez de una expresión. En otras palabras, ‘Si se

cumple la condición (...), se debe hacer (...). De lo contrario, si la condición no se cumple, se debe hacer (...)’. Los

operandos condicionales if-else y switch se utilizan en las operaciones condicionales. Una

sentencia condicional puede ser seguida por una sola sentencia o por un bloque de

sentencias a ser ejecutadas.

OPERADOR CONDICIONAL if-else

El operador if se puede utilizar solo o asociado al operador else (if-else).

Ejemplo del operador if:

if(expresión) operación;

Si el resultado de la expresión encerrada entre paréntesis es verdadero (distinto de 0) la

operación se realiza y el programa continúa con la ejecución. Si el resultado de la expresión

es falso (0), la operación no se realiza y el programa continúa inmediatamente con la

ejecución.

Como hemos mencionado, la otra forma combina tanto el operador if como el else:

if(expresión) operación1 else operación2;

Si el resultado de la expresión es verdadero (distinto de 0), se realiza operación1, de lo

contrario se realiza la operación2. Después de realizar una de las operaciones, el programa

continúa con la ejecución.

La sentencia if-else se parece a lo siguiente:

if(expresión)operación1else

Page 22: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

operación2

Si operación1 u operación2 está compuesta, escriba una lista de sentencias encerradas entre

llaves. Por ejemplo:

if(expresión) {... //... // operación1...} //elseoperación2

El operador if-else se puede sustituir por el operador condicional '?:':

(expresión1)? expresión2 : expresión3

Si el valor de la expresión1 es distinto de 0 (verdadero), el resultado de la expresión

entera será equivalente al resultado obtenido de la expresión2. De lo contrario, si la

expresión1 es 0 (falso), el resultado de la expresión entera será equivalente al resultado

obtenido de la expresión3. Por ejemplo:

maximum = (a>b)? a : b // A la variable maximum se le asigna el // valor de la variable mayor(a o b)

Operador Switch

A diferencia de la sentencia if-else que selecciona entre dos opciones en el programa, el

operador switch permite elegir entre varias opciones. La sintaxis de la sentencia switch

es:

switch (selector) // Selector es de tipo char o int{

case constante1: operación1 // El grupo de operadores que se ejecutan si ... // el selector y la constante1 son equivalentes break; case constante2:

operación2 // El grupo de operadores se ejecuta si ... // el selector y la constante2 son equivalentes

break; ... default: operación_esperada // El grupo de operadores que se ejecuta si ... // ninguna constante equivale al selector break;

}

Page 23: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

La operación switch se ejecuta de la siguiente manera: primero se ejecuta el selector y se

compara con la constante1. Si coinciden, las sentencias que pertenecen a ese bloque se

ejecutan hasta llegar a la palabra clave break o hasta el final de la operación switch. Si

no coinciden, el selector se compara con la constante2. Si coinciden, las sentencias que

pertenecen a ese bloque se ejecutan hasta llegar a la palabra clave break etc. Si el

selector no coincide con ninguna constante, se ejecutarán las operaciones que siguen al

operador default.

También es posible comparar una expresión con un grupo de constantes. Si coincide con

alguna de ellas, se ejecutarán las operaciones apropiadas:

switch (días) // La variable días representa un día de la semana.{ // Es necesario determinar si es un día laborable o no lo es case1:case2:case3:case4:case5: LCD_message = 'Día laborable'; break; case6:case7: LCD_message = 'Fin de semana'; break; default:LCD_message_1 = 'Elija un día de la semana'; break;}

La palabra clave de C ‘break’ se puede utilizar en cualquier tipo de bloques. Al utilizar ‘break’, es posible salir de un bloque

aunque la condición para su final no se haya cumplido. Se puede utilizar para terminar un bucle infinito, o para forzar un

bucle a terminar antes de lo normal.

BUCLES

A menudo es necesario repetir una cierta operación un par de veces en el programa. Un

conjunto de comandos que se repiten es denominado un bucle de programa. Cuántas veces se

ejecutará, es decir cuánto tiempo el programa se quedará en el bucle, depende de las

condiciones de salir del bucle.

Bucle While

El bucle while se parece a lo siguiente:

while(expresión){comandos...}

Los comandos se ejecutan repetidamente (el programa se queda en el bucle) hasta que la

expresión llegue a ser falsa. Si la expresión es falsa en la entrada del bucle, entonces el

bucle no se ejecutará y el programa continuará desde el fin del bucle while.

Un tipo especial del bucle de programa es un bucle infinito. Se forma si la condición sigue

sin cambios dentro del bucle. La ejecución es simple en este caso ya que el resultado entre

llaves es siempre verdadero (1=verdadero), lo que significa que el programa se queda en el

mismo bucle:

while(1){ // En vez de "while(1)", se puede escribir "while(true)"

... // Expresiones encerradas entre llaves se ejecutarán

... // repetidamente (bucle infinito)

Page 24: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

}

Bucle For

El bucle for se parece a lo siguiente:

for(expresión_inicial; expresión_de_condición; cambiar_expresión) { operaciones ...}

La ejecución de esta secuencia de programa es similar al bucle while, salvo que en este caso

el proceso de especificar el valor inicial (inicialización) se realice en la declaración.

La expresión_ inicial especifica la variable inicial del bucle, que más tarde se compara

con la expresión_ de_condición antes de entrar al bucle. Las operaciones dentro del bucle

se ejecutan repetidamente y después de cada iteración el valor de la expresión_inicial se

incrementa de acuerdo con la regla cambiar_expresión. La iteración continúa hasta que la

expresión_de_condición llegue a ser falsa.

for(k=0; k<5; k++) // La variable k se incrementa 5 veces (de 1 a 4) yoperación // cada vez se repite la expresión operación

La operación se ejecutará cinco veces. Luego, al comprobar se valida que la expresión k<5

sea falsa (después de 5 iteraciones k=5) y el programa saldrá del bucle for.

Bucle Do-while

El bucle do-while se parece a lo siguiente:

dooperaciónwhile (cambiar_condición);

La expresión cambiar_condición se ejecuta al final del bucle, que significa que operación

se ejecuta como mínimo una vez sin reparar en que si la condición es verdadera o falsa. Si

el resultado es distinto de 0 (verdadero), el procedimiento se repite.

Todos los siguientes ejemplos son equivalentes. Esta parte del código visualiza "hello" en

un LCD 10 veces con un retardo de un segundo. Note que en este ejemplo se utilizan

funciones predefinidas, que se encuentran en las librerías del compilador mikroC PRO for PIC.

No obstante le aconsejamos que no trate de entenderlas en detalle. Su comportamiento

general dentro del bucle se explica por medio de los comentarios.

i = 0; // Inicialización del contador

while (i<10) { // Condición Lcd_Out(1,3,"hello"); // Visualizar “hello” en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar el LCD Delay_ms(500); // Retardo de 500ms i++; // Contador se incrementa

Page 25: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

}for(i=0; i<10; i++) { // Inicialización, condición, incremento Lcd_Out(1,3,"hello"); // Visualizar “hello” en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar el LCD Delay_ms(500); // Retardo de 500ms}i = 0; // Inicialización del contadordo {

Lcd_Out(1,3,"hello"); // Visualizar “hello” en el LCDDelay_ms(1000); // Retardo de 1000 msLcd_Cmd(_LCD_CLEAR); // Borrar LCDDelay_ms(500); // Retardo de 500msi++; // Contador se incrementa

}while (i<10); // Condición

SENTENCIAS DE SALTO

SENTENCIA BREAK

A veces es necesario detener y salir de un bucle dentro de su cuerpo. La sentencia break se

puede utilizar dentro de cualquier bucle (while, for, do while) y en las sentencias switch

también. En éstas la sentencia break se utiliza para salir de las sentencias switch si la

condición case es verdadera. En este ejemplo, “Esperar” está parpadeando en la pantalla LCD

hasta que el programa detecte un uno lógico en el pin 0 del puerto PORTA.

while(1){ // Bucle infinito if(PORTA.F0 == 1) // Probar si el estado lógico del pin 0 del puerto break; // PORTA es 1; si equivale, salir del bucle Lcd_Out(1,3,"Esperar"); // Visualizar “Esperar” en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar LCD Delay_ms(500); // Retardo de 500ms}

SENTENCIA CONTINUE

La sentencia continue colocada dentro de un bucle se utiliza para saltar una iteración. A

diferencia de la sentencia break, el programa se queda dentro del bucle y las iteraciones

continúan.

// Si x=7, puede ocurrir una división por 0.// continue se utiliza aquí para evitar esta situación.x=1;while (x<=10) { if (x == 7) { // saltar x=7 para evitar división por 0 Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,3,"Division by 0"); Delay_ms(1000); x++; continue; // Después de esta línea, saltar a la sentencia while con x=8

Page 26: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

} a = 1/(x-7); // Esta división generará un error si x=7 /* Muchas operaciones pueden ocurrir aquí */ Lcd_Out(1,3,"Division is OK"); // Poner este mensaje en el LCD Delay_ms(1000); x++;}

SENTENCIA GOTO

La sentencia goto le permite hacer un salto absoluto al otro punto en el programa. Esta

característica se debe utilizar con precaución ya que su ejecución puede causar un salto

incondicional sin hacer caso a todos los tipos de limitaciones de anidación. El punto

destino es identificado por una etiqueta, utilizada como un argumento para la sentencia

goto. Una etiqueta consiste en un identificador válido seguido por un colon (:).

...if(CO2_sensor) goto aire acondicionado; // Si se consta que el valor... // de la variable CO2_sensor =1 // hacer salto a la línea de programa // Aire acondicionado...Aire acondicionado: // Desde aquí sigue la parte del código que se ejecutará // en caso de una concentración de CO2 demasiado alta... // en el ambiente

2.7 TIPOS DE DATOS AVANZADOS

MATRICES

Una matriz es una lista de elementos del mismo tipo colocados en localidades de memoria

contiguas. Cada elemento es referenciado por un índice. Para declarar una matriz, es

necesario especificar el tipo de sus elementos (denominado tipo de matriz), su nombre y el

número de sus elementos encerrados entre corchetes. Todos los elementos de una matriz

tienen el mismo tipo.

tipo_de_matriz nombre_de_matriz [nº_de_elementos];

Los elementos de una matriz se identifican por su posición. En C, el índice va desde 0 (el

primer elemento de una matriz) a N-1 (N es el número de elementos contenidos en una

matriz). El compilador tiene que “saber” cuántas localidades de memoria debe alojar al

declarar una matriz. El tamaño de una matiz no puede ser una variable. Por eso, se pueden

utilizar dos métodos:

// método 1int display [3]; // Declaración de la matriz display capaz de contener 3 enteros

Page 27: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

// método 2const DÍGITOS = 5;char Matriz_nueva[DÍGITOS]; // Declaración de la matriz Matriz_nueva // capaz de contener 5 enteros

Una matriz se puede inicializar a la vez que se declara, o más tarde en el programa. En

ambos casos, este paso se realiza al utilizar llaves:

int array_1[3] = {10,1,100};

Para leer o modificar un elemento de matriz del ejemplo anterior, basta con introducir su

índice encerrado entre corchetes:

/* Se supone que a ha sido declarado anteriormente como un entero */

a = array_1[0]; // A la variable a se le asigna el valor del miembro de matriz

// con índice 0 (a = 10)array_1[2] = 20; // Miembro de matriz array_1[2] es modificado (nuevo valor es 20)

El siguiente programa cambia el orden de los elementos de una matriz. Note que el índice se

puede expresar mediante variables y operaciones básicas.

void main() { const MUESTRAS_DE_AGUA = 4; // Valor de la constante MUESTRAS_DE_AGUA es 4 int i, temp; // Variables i y temp son de tipo int int profunidad_de_sonda [MUESTRAS_DE_AGUA] = {24,25,1,1987};// Todos // los miembros de la matriz profundidad // de sonda son de tipo int for(i=0;i<(MUESTRAS_DE_AGUA/2);i++){ // Bucle se ejecuta 2 veces temp = profundiad_de_sonda [i]; // temp se utiliza para guardar un valor // temporalmente profundiad_de_sonda [i] = profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i]; profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i] = temp; } // Aquí tenemos: profundidad_de_sonda [MUESTRAS_DE_AGUA] = {1987,1,25,24}}

MATRICES BIDIMENSIONALES

Aparte de las matrices unidimensionales que se pueden interpretar como una lista de

valores, el lenguaje C le permite declarar matrices multidimensionales. En esta parte vamos

a describir sólo las matrices bidimensionales, también denominadas tablas o matrices. Una

matriz bidimensional se declara al especificar el tipo de dato de matriz, el nombre de

matriz y el tamaño de cada dimensión.

tipo_de_matriz nombre_de_matriz [número_de_filas] [número_de_columnas];

Page 28: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

En la declaración de esta matriz número_de_filas y número_de_columnas representan el número

de filas y columnas en las que consiste una tabla, respectivamente. Vea la siguiente matriz

bidimensional:

int Tabla [3][4]; // Tabla se define de modo que tenga 3 filas y 4 columnas

Esta matriz se puede representar en la forma de una tabla.

tabla[0][0] tabla[0][1] tabla[0][2] tabla[0][3]

tabla[1][0] tabla[1][1] tabla[1][2] tabla[1][3]

tabla[2][0] tabla[2][1] tabla[2][2] tabla[2][3]

Similar a las matrices unidimesionales, es posible asignar los valores a los elementos de

una tabla en la línea de declaración. La asignación debe ser realizada línea a línea como

en el siguiente ejemplo. Como hemos visto anteriormente, esta matriz tiene dos filas y tres

columnas:

int Tabla [2][3]= { {3,42,1},{7,7,19} };

La matriz anterior se puede representar también en la forma de una tabla de valores:

3 42 1

7 7 19

PUNTEROS

Un puntero es una variable destinada a recibir una dirección. Un puntero “apunta” a una

localidad de memoria, referenciada por una dirección. En C, la dirección de un objeto se

puede obtener por medio un operador unitario &. Para acceder al contenido de la memoria en

una dirección específica (también llamado objeto apuntado), se utiliza un operador de

indirección (*).

'&n' es la dirección de la localidad de memoria 'n'.

'*(&n)' es el contenido de la dirección '(&n)', o sea de 'n'.

Para declarar un puntero, se debe que especificar el tipo de la variable apuntada:

tipo_de_variable *puntero;

En esta etapa, el puntero mi_puntero apunta al valor almacenado en esta localidad de

memoria, o sea, a un valor desconocido. Así que, una inicialización es muy recomendable:

puntero = &variable;

Ahora, puntero contiene la dirección de variable.

Page 29: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Para acceder al contenido de la variable apuntada, debe utilizar ‘*’. El siguiente ejemplo

muestra el contenido de memoria dependiendo de la acción realizada por medio del puntero.

Los punteros son muy útiles para manejar las matrices. En este caso, un puntero se

utilizará para apuntar al primer elemento de una matriz. Debido al hecho de que es posible

realizar operaciones básicas sobre los punteros (aritmética de punteros), es fácil manejar

los elementos de una matriz.

Fíjese en la diferencia entre ‘*v+1’ y ‘*(v+1)’ en el siguiente ejemplo:

short int voltio[3] = {0,5,10};short int *v;v = &(voltio[0]); // v contiene la dirección de voltio[0]*(v+1) = 2; // voltio[1] = 2voltio[2] = *v+1; // tab[2] = 1 (tab[0] + 1)*(v+2) = *(v+1); // voltio[2] = 2v++; // v contiene la dirección de voltio[1]*v = 1; // voltio[1] = 1

Los punteros también pueden ser declarados con el prefijo ‘const’. En este caso, su valor no puede ser modificado

después de la inicialización, similar a una constante.

A diferencia de C, el mikroC no admite alojamiento dinámico.

ESTRUCTURAS

Ya hemos visto cómo agrupar los elementos dentro de matrices. No obstante, al utilizar este

método todos los elementos deben ser del mismo tipo. Al utilizar estructuras, es posible

agrupar diferentes tipos de variables bajo el mismo nombre. Las variables dentro de una

estructura se le denominan los miembros de la estructura. Las estructuras de datos se

declaran al utilizar la siguiente sintaxis:

struct nombre_de_estructura { tipo1_de_miembro1 miembro1; tipo2_de_miembro2 miembro2; tipo3_de_miembro3 miembro3; ..};

No es posible inicializar variables dentro de la declaración de la estructura de datos:

Page 30: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

struct generador { int voltaje; char corriente;};

Entonces, podrá definir los objetos denominados ‘turbina’ en el código. A cada uno de estos

tres objetos (turbinas) se le asignan las variables ‘corriente’ y ‘voltaje’.

struct generadores turbina_1, turbina_2, turbina_3;

Para acceder a las variables, es preciso utilizar el operador '.'

turbina_3.voltaje = 150;turbina_3.corriente = 12;

Por supuesto, igual que al utilizar los punteros, todavía se le permite realizar

operaciones por medio de operadores y sentencias definidos en las partes anteriores.

Si está familiarizado con el lenguaje C, recuerde que mikroC no admite la inicialización de los miembros de estructura por

medio de las llaves. Por ejemplo, ‘conjunto_1 ={15,‘m’};’ devuelve un error en mikroC.

2.8 FUNCIONES

Una función es una subrutina que contiene una lista de sentencias a realizar. La idea

principal es dividir un programa en varias partes utilizando estas funciones para resolver

el problema inicial con más facilidad. Además, las funciones nos permiten utilizar las

destrezas y el conocimiento de otros programadores. Una función se ejecuta cada vez que se

llame dentro de otra función. En C, un programa contiene como mínimo una función, la

función main(), aunque el número de funciones es normalmente mayor. Al utilizar funciones

el código se hace más corto ya que es posible llamar una función tantas veces como se

necesite. En C, el código normalmente consiste en muchas funciones. No obstante, en caso de

que su programa sea muy corto y simple, puede escribir todas las sentencias dentro de la

función principal.

FUNCIÓN PRINCIPAL

La función principal main() es una función particular puesto que es la que se ejecuta al

iniciar el programa. Además, el programa termina una vez completada la ejecución de esta

función. El compilador reconoce automáticamente esta función y no es posible llamarla por

otra función. La sintaxis de esta función es la siguiente:

void main (void) {

/* el primer 'void' significa que main no devuelve ningún valor. El segundo'void' significa que no recibe ningún valor. Note que el compiladortambién admite la siguiente sintaxis: 'main()' o 'void main()' o'main(void)' */..

Page 31: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

/* --- Introduzca su programa aquí --- */};

Esto significa que f es una función que recibe un número real x como parámetro y devuelve

2*x-y.

La misma función en C se parece a lo siguiente:

float f (float x, float y) // variables flotantes x y y se pueden utilizar en f{ float r; // declarar r para almacenar el resultado r = 2*x - y; // almacenar el resultado del cálculo en r return r; // devolver el valor de r}

Cada función debe ser declarada apropiadamente para poder interpretarla correctamente

durante el proceso de compilación. La declaración contiene los siguientes elementos:

Tipo de resultado (valor devuelto): tipo de dato del valor devuelto

Nombre de función: es un identificador que hace posible llamar a una función.

Declaración de parámetros se parece a la declaración de variable regular (por

ejemplo: float x). Cada parámetro consiste en una variable, constante, puntero o

matriz, precedidos por la etiqueta de tipo de dato. Se utilizan para pasar la

información a la función al llamarla. Los parámetros diferentes están delimitados

por comas.

Cuerpo de función: bloque de sentencias dentro de llaves

Page 32: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Una función se parece a lo siguiente:

tipo_de_resultado nombre_de_función (tipo argumento1, tipo argumento2,...){ Sentencia; Sentencia; ... return ...}

Note que una función no necesita parámetros (función main() por ejemplo), pero debe estar entre paréntesis. En caso

contrario, el compilador malinterpretaría la función. Para hacerlo más claro, puede sustituir el espacio en blanco encerrado

entre paréntesis por la palabra clave void: main (void).

VALOR DEVUELTO

Una función puede devolver un valor (esto no es obligatorio) por medio de la palabra clave

return. Al llegar a return, la función evalúa un valor (puede ser una expresión) y lo

devuelve a la línea de programa desde la que fue llamada.

return r; // Devolver el valor contenido en rreturn (2*x - y); // Devolver el valor de la expresión 2*x-y

Una función no puede devolver más de un valor, pero puede devolver un puntero o una

estructura. Tenga cuidado al utilizar matrices y punteros. El siguiente ejemplo es un error

típico:

int *reverse(int *tab) // Esta función debe devolver una matriz r{ // cuyo contenido está en orden inverso con // respecto a la matriz tab int r[DIM]; // Declaración de una nueva matriz denominada r int i; for(i=0;i<DIM;i++) // Bucle que copia el contenido de tab en r r[i] = tab[DIM-1-i]; // al invertir el orden

return r; // Devolver el valor r}

En realidad, el compilador reserva memoria para el almacenamiento de variables de la

función reverse sólo durante su ejecución. Una vez completada la ejecución de reverse, la

localidad de memoria para la variable i o para la matriz r ya no está reservada. Esto

significa que la dirección que contiene los valores de i o r[] está libre para introducir

datos nuevos. Concretamente, la función devuelve sólo el valor &r[0], así que sólo el

primer elemento de la matriz tab será almacenado en la memoria. Las demás localidades de

memoria, tales como &tab[1], &tab[2], etc. serán consideradas por el compilador como

espacios en blanco, o sea, estarán listas para recibir los nuevos valores.

Para escribir esta función es necesario pasar la matriz r [] como parámetro (vea la

subsección Pasar los parámetros).

La función puede contener más de una sentencia return. En este caso, al ejecutar la primera

sentencia return, la función devuelve el valor correspondiente y se detiene la ejecución de

la función.

Page 33: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

float abs (float x, float y) // Devolver el valor absoluto de 2*x-y{ if ((2*x - y) >= 0) return (2*x - y); else return (-2*x + y);}

Si la función no devuelve ningún valor, la palabra void debe ser utilizada como un tipo de

resultado en la declaración. En este caso, la sentencia return no debe ser seguida por

ninguna expresión. Puede ser omitida como en el siguiente ejemplo:

void wait_1 (unsigned int a){ cnt ++; // Incremento de una variable global cnt Delay_ms(a) ; // Ejecución de la función Delay_ms} // Note que Delay_ms no devuelve nada

DECLARAR PROTOTIPOS DE FUNCIONES

Para utilizar una función, el compilador debe ser consciente de su presencia en el

programa. En la programación en C, los programadores normalmente primero escriben la

función main() y luego las funciones adicionales. Para avisar al compilador de la presencia

de las funciones adicionales, se requiere declarar los prototipos de funciones en el

principio de programa antes de la función main(). Un prototipo de función está compuesto por:

tipo de resultado

nombre de función

tipos de parámetros

un punto y coma (;)

El prototipo de la función main no necesita ser declarado.

float f (float, float);

/* no es obligatorio escribir los nombres de los parámetros. Este prototipoinforma al compilador: en el programa se utilizará la función f,que utiliza dos parámetros de tipo float y devuelve el resultado del tipofloat. */

LLAMAR UNA FUNCIÓN

Mientras una función es definida y su prototipo declarado, se puede utilizar en culquier

parte de programa. Sin embargo, como la función main es 'raiz' del programa, no puede ser

llamada de ninguna parte de programa. Para ejecutar una función, es necesario escribir su

nombre y los parámetros asociados. Vea los siguientes ejemplos:

float resultado,a,b; // resultado,a,b,time deben coincidir con los tipos // definidosint time = 100; // en la declaración de las funciones f y wait_1a = 10.54;b = 5.2;

Page 34: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

resultado = f(a,b); // Ejecutar la función f por medio de los parámetros a y b

// El valor devuelto se le asigna a la variable resultadopausa_1(tiempo); // Ejecutar la función pausa_1 por medio de la variable tiempofunciónX(); // Ejecutar la función funciónX (sin parámetros)

Cuando se llama una función, el programa salta a la función llamada, la ejecuta, después

vuelve a la línea desde la que fue llamada.

PASAR LOS PARÁMETROS

Al llamar una función, se le pasan los parámetros. En C existen dos formas diferentes para

pasar parámetros a una función.

El primer método, denominado ‘paso por valor’, es el más fácil. En este caso, los

parámetros se pueden considerar como variables locales de la función. Cuando se llama una

función, el valor de cada parámetro se copia a un nuevo espacio de memoria reservado

durante la ejecución de la función. Como los parámetros se consideran como variables

locales por el compilador, sus valores pueden ser modificados dentro de la función, pero

sus modificaciones no se quedan en la memoria una vez completada la ejecución de la

función.

Tenga en cuenta de que la función devuelve un valor, y no una variable. Además, se crean

copias de los valores de los parámetros, por lo que sus nombres en la función f pueden ser

diferentes de los parámetros utilizados en la main(). La mayor desventaja del ‘paso por el

valor’ es que la única interacción que una función tiene con el resto del programa es el

valor devuelto de un solo resultado (o la modificación de las variables globales).

El otro método, denominado 'paso por dirección' le permite sobrepasar este problema. En vez

de enviar el valor de una variable al llamar a función, se debe enviar la dirección de

memoria del valor. Entonces, la función llamada será capaz de modificar el contenido de

esta localidad de memoria.

// Función 'sort'ordena los miembros de la matriz por valor ascendente

// y devuelve el miembro con máximo valor

int sort(int *); // Prototipo de función

const SIZE = 5; // Número de miembros a ordenar

void main() {

int maximum, input[SIZE] = {5,10,3,12,0}; // Declaración de variables en la matriz

maximum = sort(input); // Llamar a función y asignarle el máximo

// valor a la variable maximum

Page 35: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

}

int sort(int *sequence) {

int i, temp, permut; // Declaración de variables

permut = 1; // Bandera de bit indica que se ha hecho una permutación

while(permut!=0) { // Quedarse en el bucle hasta reinicar la bandera

permut = 0; // Bandera reiniciada

for(i=0;i<SIZE-1;i++) { // Comparar y oredenar los miembros de la

// matriz (dos a dos)

if(sequence [i] > sequence[i+1]){

temp = sequence [i];

sequence[i] = sequence[i+1];

sequence[i+1] = temp;

permut = 1; // Se ha hecho una permutación, bandera de bit

//se pone a uno

}

}

}

return sequence[SIZE-1]; // Devolver el valor del último miembro

} // que es al mismo tiempo el miembro con el máximo valor

En este ejemplo, por medio de una función se realizan dos operaciones: ordena los miembros

de la matriz por valor asdendente y devuelve el máximo valor.

Para utilizar una matriz en una función es necesario asignar la dirección a la matriz (o a

su primer miembro). Vea el siguiente ejemplo:

float método_1(int[]); // Declaración de prototipo de la función Método_1

float método_2(int*); // Declaración de prototipo de la función Método_2

const NÚMERO_DE_MEDICIONES = 7; // Número de los miembros de la matriz

void main()

{

double promedio1, promedio2; // Declaración de las variables promedio1

// y promedio2

int voltaje [NÚMERO_DE_MEDICIONES] = {7,8,3,5,6,1,9}; // Declaración de la

Page 36: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

// matriz voltaje

promedio1 = método_1(&voltaje[0]); // Parámetro de la función es la dirección

// del primer miembro

promedio2 = método_2(voltaje); // Parámetro de la función es la dirección de

// la matriz

}

//××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

float método_1(int voltaje[]) // Inicio de la función método_1

{

int i, suma; // Declaración de las variables locales i y suma

for(i=0;i<NÚMERO_DE_MEDICIONES;i++) // Cálculo del valor promedio de voltaje

suma += voltaje[i]; // Es posible utilizar *(voltaje+i)en vez de voltaje[i]

return(suma/NÚMERO_DE_MEDICIONES);

}

//××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

float método_2 (int *voltaje) //Inicio de la función método_2

{

int i, suma; // Declaración de las variables locales i y suma

for(i=0;i<NÚMERO_DE_MEDICIONES;i++) // Cálculo del valor promedio de voltaje

suma += *(voltaje+i); // Es posible utilizar voltaje[i] en vez de *(voltaje+i)

return(suma/NÚMERO_DE_MEDICIONES);

}

Las funciones 'método_1' y 'método_2' son completamente equivalentes. Las dos devuelven el

valor promedio de la matriz 'voltaje[]'. Después de declararla, la dirección del primer

miembro se puede escribir como 'voltaje' o '&voltaje[0]'.

2.9 CARACTERÍSTICAS PRINCIPALES DEL PREPROCESADOR

El preprocesador es un programa que procesa el código antes de que pase por el compilador.

Funciona bajo el control de las líneas de comando del preprocesador denominadas directivas.

Las directivas del preprocesador se colocan en el código fuente, normalmente en el

principio del archivo. Antes de pasar por el compilador, el código fuente se examina por el

preprocesador que detecta y ejecuta todas las directivas del preprocesador. Las directivas

Page 37: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

del preprocesador siguen a una regla de la sintaxis especial, empiezan por un símbolo ‘#’ y

no requieren ningún punto y coma al final (;).

DIRECTIVAS DEL PREPROCESADOR

La siguiente tabla contiene un conjunto de directivas del preprocesador frecuentemente

utilizadas:

Las directivas del preprocesador se pueden dividir en tres categorías:

DI RE CT IV AS FU NC IO NE S

#define Define una sustitución de macro

#undef Quita una definición de nombre de macro

#define Especifica un archivo a ser incluido

#ifdef Prueba para definición de macro

#endif Especificar el final de #if

#ifndef Prueba si una macro no está definida

#if Prueba las condiciones de compilar

#else Especifica alternativas cuando la prueba de #if falla

#elif Especifica alternativas cuando más de dos condiciones se necesitan Definiciones de macro

Inclusiones de archivos

Control de compilación

Ahora, vamos a presentar sólo las directivas del preprocesador utilizadas con más

frecuencia. Sin embargo, no es necesario saber todas ellas para programar

microcontroladores. Sólo tenga en cuenta que el preprocesador es una herramienta muy

poderosa para los programadores avanzados en C, especialmente para el control de

compilación.

DIRECTIVAS DEL PREPROCESADOR PARA DEFINIR MACROS

Por medio de los macros es posible definir las constantes y ejecutar funciones básicas. Una

sustitución de macro es un proceso en el que un identificador del programa se sustituye por

una cadena predefinida. El preprocesador sustituye cada ocurrencia del identificador en el

código fuente por una cadena. Después de la sustitución, el código será compilado

normalmente.

Esto significa que el código sustituido debe respetar la sintaxis del mikroC. La acción se

realiza por medio de la directiva '#define'.

#define PI 3.14159 // Sustitución simple, PI será sustituido por

// el valor 3.14159 en todas las partes del programa

También puede utilizar los parámetros para realizar substituciones más complejas:

#define VOLUMEN (D,H) (((D/2)*(D/2)*PI))*H // Macro con parámetros

Page 38: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Entonces, en el código, la siguiente sentencia:

Tanque_1 = VOLUMEN (Diámetro,altura);

será sustituida por:

Tanque_1 = (((Diámetro/2)*(Diámetro/2)*PI)*altura;

Por medio de la directiva #undef es posible quitar una definición de nombre de macro. Así

se especifica que la substitución que se ha definido anteriormente ya no va ocurrir en el

siguiente código. Esto es útil cuando usted quiere restringir la definición sólo a una

parte particular del programa.

#undef TANQUE // Quitar la definición del macro VOLUMEN

INCLUSIÓN DE ARCHIVOS

La directiva de preprocesador #include copia un archivo específico en el código fuente. El

código incluido debe observar la sintaxis de C para ser compilado correctamente.

Hay dos formas de escribir estas directivas. En el primer ejemplo, sólo el nombre de

archivo se especifica, así que el preprocesador lo buscará dentro del archivo include. En

el segundo ejemplo, se especifica la ruta entera, así que el archivo estará directamente

incluido (este método es más rápido).

#include <nombre_de_archivo> // Se especifica sólo el nombre del archivo

#include "C:\Ruta\nombre_de_archivo.h" // Se especifica la localidad

// exacta del archivo

2.10 MIKROC PRO FOR PIC

Como ya hemos visto, hay varias divergencias entre los lenguajes mikroC y ANSI C. En este

capítulo vamos a presentar las características específicas del mikroC con el propósito de

facilitar la programación de los microcontroladores PIC.

ACCESO A LOS REGISTROS DE FUNCIONES ESPECIALES (SFR)

Como todos los microcontroladores, los de familia PIC tienen los registros de funciones

especiales (SFR). Para programar un PIC, es necesario acceder a estos registros (para

leerlos o escribir en ellos). Al utilizar el compilador mikroC PRO for PIC es posible de

acceder a cualquier SFR del microcontrolador de cualquier parte del código (los SFR se

consideran como variables globales) sin necesidad de declararlo anteriormente. Los

registros de funciones especiales se definen en un archivo externo e incluido dentro del

Page 39: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

compilador (archivo .def). Este archivo contiene todos los SFR del microcontrolador PIC a

programar.

TRISB = 0; // todos los pines del puerto PORTB se configuran como salidas

PORTB = 0; // todos los pines del PORTB se ponen a 0

ACCESO A LOS BITS INDIVIDUALES

El compilador mikroC PRO for PIC le permite acceder a los bits individuales de variables de 8

bits por su nombre o su posición en byte:

INTCON.B0 = 0; // Poner a 0 el bit 0 del registro INTCON

ADCON0.F5 = 1; // Poner a 1 el bit 5 del registo ADCON0

INTCON.GIE = 0; // Poner a 0 el bit de interrupción global (GIE)

Para acceder a un bit individual, se puede utilizar '.FX' así como '.BX' (X es un entero

entre 0 y 7 que representa la posición de bit).

TIPO SBIT

Si quiere declarar una variable que corresponde a un bit de un SFR, hay que utilizar el

tipo sbit. Una variable de tipo sbit se comporta como un puntero y se debe declarar como una

variable global:

sbit Botón_PARADA at PORTA.B7; // Botón_PARADA está definido

...

void main() { // Cualquier modificación de Botón_PARADA afectará a PORTA.B7

... // Cualquier modificación de PORTA.B7 afectará a Botón_PARADA

}

En este ejemplo, El Botón_PARADA es una variable declarada por el usuario, mientras que

PORTA.B7 (bit 7 del puerto PORTA) será automáticamente reconocido por el compilador.

TIPO BIT

El compilador mikroC PRO for PIC proporciona un tipo de datos bit que se puede utilizar

para declarar variables. No se puede utilizar en las listas de argumentos, punteros y los

valores devueltos de funciones. Además, no es posible declarar e inicializar una variable

de tipo bit en la misma línea. El compilador determina el bit en uno de los registros

disponibles para almacenar las variables.

bit bf; // Variable de tipo bit válida

bit *ptr; // Varibale de tipo bit inválida.

// No hay punteros a una variable de tipo bit

Page 40: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

bit bg = 0; // ERROR ; declaración con inicialización no está permitida

bit bg;

bg = 0; // Declaración e inicialización válidas

INSERTAR CÓDIGO ASM EN C

A veces el proceso de escribir un programa en C requiere las partes del código escritas en

ensamblador. Esto permite ejecutar las partes complicadas del programa de una forma

definida con precisión en un período de tiempo exacto. Por ejemplo, cuando se necesita que

los pulsos muy cortos (de unos microsegundos) aparezcan periódicamente en un pin del

microcontrolador. En tales casos la solución más simple sería utilizar el código

ensamblador en la parte del programa que controla la duración de pulsos.

Una o más instrucciones en ensamblador están insertadas en el programa escrito en C,

utilizando el comando asm:

asm{ instrucciones en ensamblador ...}

Los códigos escritos en ensamblador pueden utilizar constantes y variables anteriormente

definidos en C. Por supuesto, como el programa entero está escrito en C, sus reglas se

aplican al declarar estas constantes y variables.

unsigned char maximum = 100; // Declarar variables: maximum = 100asm{ // Inicio del código ensamblador MOVF maximum,W // W = maximum = 100

Page 41: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

...} // Final del código ensamblador

FUNCIÓN DE INTERRUPCIÓN

Una interrupción detiene la ejecución normal de un programa para ejecutar las operaciones

específicas. Una lista de sentencias a ejecutar debe estar escrita dentro de una función

particular denominada interrupt(). La sintaxis de una interrupción en mikroC se parece a lo

siguiente:

void interrupt() { cnt++ ; // Al producirse una interrupción // la cnt se incrementa en 1 PIR1.TMR1IF = 0; // Poner a 0 el bit TMR1IF}

A diferencia de las funciones estándar, no es necesario declarar el prototipo de la función

interrupt(). Además, como la ejecución de esta función no forma parte de la ejecución de

programa regular, no se debe llamar de ninguna parte de programa (se ejecutará

automáticamente dependiendo de las condiciones que el usuario ha definido en el programa).

En el siguiente capítulo vamos a dar una clara explicación de la ejecución y definición de

subrutinas de interrupción.

LIBRERÍAS

Usted probablemente ha notado que en los ejemplos anteriores hemos utilizado algunas

funciones como son 'Delay_ms', 'LCD_out', 'LCD_cmd' etc. Estas funciones están definidas en

las librerías contenidas en el compilador mikroC.

Una librería representa un código compilado, anteriormente escrito en mikroC, que contiene

un conjunto de variables y funciones. Cada librería tiene un propósito específico. Por

ejemplo, la librería LCD contiene funciones de visualización de la pantalla LCD, mientras

que C_math proporciona algunas funciones matemáticas.

Antes de utilizar alguna de ellas en el programa, es necesario comunicárselo al compilador

al marcarlas en la lista de las librerías del compilador existentes. Si el compilador

encuentra una función desconocida durante la ejecución de programa, primero va a buscar su

declaración en las librerías marcadas.

Page 42: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Aparte de las librerías existentes, es posible crear las librerías y luego utilizarlas en

el programa. El procedimiento de cómo crear librerías se describe en detalles en Help

(Ayuda) del compilador.

Page 43: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

El compilador mikroC incluye tres tipos de librerías:- librerías ANSI C estándar:

L I B R A R Í A D E S C R I P C I Ó N

ANSI C Ctype Library Utilizada principalmente para probar o para convertir los datos

ANSI C Math Library Utilizada para las operaciones matemáticas de punto flotante

ANSI C Stdlib Library Contiene las funciones de librerías estándar

ANSI C String Library Utilizada para realizar las operaciones de cadenas y de manipulación dememoria

- librerías misceláneas:L I B R A R Í A D E S C R I P C I Ó N

Button Library Utilizada para desarrollar los proyectos

Conversion Library Utilizada para la conversión de tipos de datos

Sprint Library Utilizada para formatear los datos con facilidad

PrintOut Library Utilizada para formatear los datos e imprimirlos

Time Library Utilizada para cálculos de tiempo (formato UNIX time)

Trigonometry Library Utilizada para la implementación de funciones trigonométricas fundamentales

Setjmp Library Utilizada para los saltos de programa

- librerías para el hardware:L I B R A R Í A D E S C R I P C I Ó N

ADC Library Utilizada para el funcionamiento del convertidor A/D

CAN Library Utilizada para las operaciones con el módulo CAN

CANSPI Library Utilizada para las operaciones con el módulo CAN externo (MCP2515 oMCP2510)

Compact Flash Library Utilizada para las operaciones con las tarjetas de memoria Compact Flash

EEPROM Library Utilizada para las operaciones con la memoria EEPROM incorporada

EthernetPIC18FxxJ60Library Utilizada para las operaciones con el módulo Ethernet incorporado

Flash Memory Library Utilizada para las operaciones con la memoria Flash incorporada

Graphic Lcd Library Utilizada para las operaciones con el módulo LCD gráfico con resolución128x64

I2C Library Utilizada para las operaciones con el módulo de comunicación serial I2Cincorporado

Keypad Library Utilizada para las operaciones con el teclado (botones de presión 4x4)

Lcd Library Utilizada para las operaciones con el LCD (de 2x16 caracteres)

Manchester Code Library Utilizada para la comunicación utilizando el código Manchester

Multi Media Card Library Utilizada para las operaciones con las tarjetas multimedia MMC flash

One Wire Library Utilizada para las operaciones con los circuitos utilizando lacomunicación serial One Wire

Port Expander Library Utilizada para las operaciones con el extensor de puertos MCP23S17

PS/2 Library Utilizada para las operaciones con el teclado estándar PS/2

PWM Library Utilizada para las operaciones con el módulo PWM incorporado

Page 44: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

RS-485 Library Utilizada para las operaciones con los módulos utilizando lacomunicación serial RS485

Software I2C Library Utilizada para simular la comunicación I2C con software

Software SPI Library Utilizada para simular la comunicación SPI con software

Software UART Library Utilizada para simular la comunicación UART con software

Sound Library Utilizada para generar las señales de audio

SPI Library Utilizada para las operaciones con el módulo SPI incorporado

SPI Ethernet Library Utilizada para la comunicación SPI con el módulo ETHERNET (ENC28J60)

SPI Graphic Lcd Library Utilizada para la comunicación SPI de 4 bits con el LCD gráfico

SPI LCD Library Utilizada para la comunicación SPI de 4 bits con el LCD (de 2x16caracteres)

SPI Lcd8 Library Utilizada para la comunicación SPI de 8 bits con el LCD

SPI T6963C Graphic LcdLibrary Utilizada para la comunicación SPI con el LCD gráfico

UART Library Utilizada para las operaciones con el módulo UART incorporado

USB Hid Library Utilizada para las operaciones con el módulo USB incorporado

2.11 PROGRAMAR LOS PIC UTILIZANDO MIKROC PRO FOR PIC

En las secciones anteriores hemos presentado el lenguaje mikroC, especialmente diseñado

para programar los PIC. Ahora, lo que hemos revisado es suficiente para empezar a

programar, es hora de presentar el software que utilizará para desarrollar y editar los

proyectos. Este software se le denomina Entorno de desarrollo integrado (Integrated

Developement Environment - IDE) e incluye todas las herramientas necesarias para

desarrollar los proyectos (editor, depurador etc.). Por extensión, IDE es a veces llamado

compilador. En esta sección le enseñaremos lo básico que debe saber para empezar a

desarrollar su primer proyecto en mikroC utilizando el IDE del compilador mikroC PRO for

PIC.

Aparte de todas las características comunes de cualquier IDE, mikroC PRO for PIC contiene

las informaciones de arquitectura de los microcontroladores PIC (registros, módulos de

memoria, funcionamiento de circuitos particulares etc.) para compilar y generar un archivo

legible por un microcontrolador PIC. Además, incluye las herramientas específicas para

programar los microcontroladores PIC.

El proceso de crear y ejecutar un proyecto contiene los siguientes pasos:

1. Crear un proyecto (nombre de proyecto, configuración de proyecto, dependencias entrearchivos)

2. Editar un programa3. Compilar el programa y corrección de errores4. Depurar (ejecutar el programa paso a paso para asegurarse de que se ejecutan las

operaciones deseadas).5. Programar un microcontrolador (cargar el archivo .hex generado por el compilador en

el microcontrolador utilizando el programador PICflash).

INSTALAR MIKROC PRO FOR PIC

Page 45: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Antes que nada, usted debe instalar el compilador (con su IDE) en la PC. La instalación del

mikroC PRO for PIC es similar a la instalación de cualquier programa en Windows. Todo el

procedimiento se lleva a cabo por medio de los wizards (asistentes de instalación):

Basta con seguir las instrucciones y pulsar sobre Next, OK, Next, Next... En general, es el

mismo procedimiento menos la última opción: 'Do you want to install PICFLASH v7.11

programmer?'. ¿Para qué sirve este software? De eso vamos a hablar más tarde. Por ahora,

basta con saber que es un software autónomo utilizado para cargar el programa en el

microcontrolador.

Una vez más: Next, OK, Next, Next...

Una vez completada la instalación del PICflash, el sistema operativo le preguntará a

instalar otro programa similar, un software para programar un grupo especial de los

microcontroladores PIC que funcionan en modo de bajo consumo (3.3 V). Salte este paso...

El último paso - ¡la instalación del controlador (driver)!

Page 46: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Pulse sobre Yes.

Un controlador es un programa que permite al sistema operativo comunicar con un periférico.

En este caso, este dispositivo es el programador (hardware) del sistema de desarrollo.

El controlador a instalar depende del sistema operativo utilizado. Seleccione el

controlador correspondiente al SO (sistema operativo) utilizado (por medio de abrir la

carpeta correspondiente) e inicie la instalación. Otra vez, Next, OK, Next, Next... Bueno,

¡todo está instalado para iniciar a programar!

CARACTERÍSTICAS PRINCIPALES DEL MIKROC PRO FOR PIC

Al iniciar el IDE del compilador mikroC PRO for PIC por primera vez, aparecerá una ventana

como se muestra a continuación:

Page 47: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Desgraciadamente, una descripción detallada de todas las opciones disponibles de este IDE

nos tomaría mucho tiempo. Por eso vamos a describir sólo lo más importante del compilador

mikroC PRO for PIC. De todos modos, para obtener más informacion presione el botón de Ayuda

(Help) [F1].

MANEJAR LOS PROYECTOS

Antes de empezar a escribir el código, usted debe crear un proyecto. Un programa escrito en

el compilador mikroC PRO for PIC no es un archivo fuente autónomo, sino que forma parte de un

proyecto que incluye un código hex, un código ensamblador, cabecera y otros archivos.

Algunos de ellos se requieren para compilar el programa, mientras que otros se crean

durante el proceso de compilación. Un archivo con extensión .mcppi le permite abrir

cualquiera de estos proyectos.

Para crear un proyecto, basta con seleccionar la opción Project/New Project, y un wizard

aparecerá automáticamente. ¿Qué hacer entonces? Siga las instrucciones...

PROJECT MANAGER (ADMINISTRADOR DEL PROYECTO)

Una vez creado el proyecto, es posible manejar todos los archivos que contiene al utilizar

la ventana Project Manager. Basta con pulsar con el botón derecho del ratón sobre una

carpeta y seleccionar la opción que necesita para su proyecto.

Page 48: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

PROJECT SETTINGS (CONFIGURACIÓN DE PROYECTOS)

Al compilar un proyecto, el compilador genera el archivo .hex que se cargará en el

microcontrolador. Estos archivos serán diferentes lo que depende del tipo del

microcontrolador así como del propósito de la compilación. Por esta razón es necesario

ajustar algunos parámetros de proyectos utilizando la ventana Project Settings.

Device (dispositivo):

Al seleccionar el tipo de microcontrolador a utilizar permite al compilador extraer el

archivo de definición (archivo .def) asociado. El archivo de definición de un

microcontrolador contiene las informaciones específicas de sus registros SFR, de sus

direcciones de memoria y algunas variables de programación específicas a ese tipo del

microcontrolador. Es obligatorio crear un archivo .hex compatible.

Oscillator (oscilador):

Se debe especificar la velocidad de operación del microcontrolador. Por supuesto, este

valor depende del oscilador utilizado. El compilador la necesita para compilar rutinas, lo

que requiere información del tiempo (por ejemplo, la función Delay_ms). Más tarde, el

programador necesitará esta información también. La velocidad de operación se configura de

Page 49: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

modo que permita al oscilador interno del microcontrolador funcionar a una frecuencia

seleccionada.

Build/Debugger Type:

Todo el proceso de compilar (building) está compuesto por análisis sintáctico (parsing),

compilar, enlazar (linking) y generar los archivos .hex. El tipo de compilación le permite

ajustar el modo de compilación. Dependiendo del modo seleccionado, difieren los archivos

generados a cargar en el microcontrolador.

Release: Al elegir esta opción , el compilador no puede afectar más a la ejecución de

programa después de la compilación. El programa a cargar en el microcontrolador no será

modificado de ninguna manera.

ICD debug: Al elegir esta opción, una vez completado el proceso de la compilación y cargado

el programa en la memoria del microcontrolador, el compilador se queda conectado al

microcontrolador por medio del cable USB y el programador, y todavía puede afectar a su

funcionamiento. El archivo .hex generado contiene los datos adicionales que permiten el

funcionamiento del depurador. Una herramienta denominada mikroICD (Depurador en circuito -

In Circuit Debugger) permite ejecutar el programa paso a paso y proporcionar un acceso al

contenido actual de todos los registros de un microcontrolador real.

El simulador no utiliza los dispositivos reales para simular el funcionamiento del

microcontrolador, así que algunas operaciones no pueden ser reproducidas (por ejemplo,

interrupción). De todos modos, resulta más rápido depurar un programa por medio de un

simulador. Además, no se requiere ningún dispositivo destino.

Note que es posible modificar cualquier configuración en cualquier momento mientras se

edita el programa. No se olvide de recompilar y reprogramar su dispositivo después de

modificar una configuración.

LIBRARY MANAGING (EDITOR DE LIBRERÍAS)

El compilador tiene que conocer todas las dependencias de su archivo fuente en mikroC para

compilarlo apropiadamente. Por ejemplo, si las librerías forman parte de su proyecto, debe

especificar cuáles de ellas se utilizan.

Las librerías contienen un gran número de funciones listas para ser utilizadas. Las

librerías en mikroC proporcionan muchas facilidades para escribir programas para los

microcontroladores PIC. Abra la ventana Library Manager, y marque las que quiere utilizar en

el programa. Al marcar una librería, se añade automáticamente al proyecto y se enlaza

durante el proceso de la compilación. Así, no necesita incluir las librerías manualmente en

sus archivos del código fuente por medio de la directiva del preprocesador #include.

Por ejemplo, si su programa utiliza un LCD no hace falta

escribir nuevas funciones ya que al seleccionar la librería

Lcd, usted podrá utilizar funciones listas para ser

utilizadas de la librería LCD (Lcd_Cmd, LCD_Init...) en su

programa. Si esta librería no está seleccionada en la

Page 50: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

ventana Library Manager, cada vez que intente utilizar una

función de la librería LCD, el compilador le informará de un

error. Una descripción de cada librería está disponible al

pulsar con el botón derecho del ratón sobre su nombre y

seleccionar la opción Help.

Page 51: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

EDITAR Y COMPILAR PROGRAMAS

CODE EDITOR (EDITOR DE CÓDIGO)

El proceso de editar programas se debe realizar dentro de la ventana principal del IDE

denominada Code Editor. Al escribir el programa no se olvide de los comentarios. Los

comentarios son muy importantes para depurar y mejorar el programa. Además, aunque el

compilador no tenga las restricciones de formateo, siempre debe seguir a las mismas reglas

de editar (como en los ejemplos proporcionados en este libro). Como no hay limitaciones de

tamaño, no vacile en utilizar los espacios en blanco para hacer su código más legible.

Al escribir un programa, no espere que termine la redacción del programa para compilarlo.

Compile su código de forma regular con el propósito de corregir cuánto más errores de

sintaxis. Asimismo usted puede compilar su programa cada vez que se complete la redacción

de una nueva función así como probar su comportamiento al utilizar modo de depuración (ver

la próxima sección). De este modo, resulta más fácil solucionar los errores de programa

para no “tomar un camino erróneo” en redactar su programa. De lo contrario, usted tendrá

que editar el programa entero.

CODE EXPLORER (EXPLORADOR DEL CÓDIGO)

La ventana Code Explorer le permite localizar funciones y procedimientos dentro de los

programas largos. Por ejemplo, si usted busca una función utilizada en el programa, basta

con pulsar dos veces sobre su nombre en esta ventana, y el cursor estará automáticamente

posicionado en la línea apropiada en el programa.

COMPILAR Y SOLUCIONAR LOS ERRORES

Para compilar su código, pulse sobre la opción Build en el menú Project. En realidad, el

proyecto entero se ha compilado, y si la compilación se ha realizado con éxito, se

generarán los archivos de salida (asm, .hex etc.). Una compilación se ha realizado con

éxito si no se ha encontrado ningún error. Durante el proceso de compilación se generan

muchos mensajes que se visualizan en la ventana Messages. Estos mensajes consisten en

información, advertencia y errores. Cada error encontrado se asocia con su línea de

programa y su descripción.

Page 52: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Como un error en su código puede generar mucho más errores, simplemente debe intentar

solucionar el primer error en la lista y después recompile su programa. En otras palabras,

es recomendable solucionar los errores uno a uno.

En el ejemplo anterior hay dos errores y una advertencia: faltan un punto y coma y una

declaración de variable La advertencia le informa que falta el tipo del valor devuelto de

la función main.

La compilación le permite corregir su programa por medio de solucionar todos los errores en

mikroC. Cuando todos los errores se solucionen, su programa está listo para ser cargado en

el microcontrolador. De todas formas, su tarea todavía no está terminada, porque aún no

sabe si su programa se comporta como se esperaba o no.

DEPURAR EL PROGRAMA

La depuración es un paso muy importante ya que permite probar el programa después de una

compilación realizada con éxito, o solucionar los errores descubiertos mientras se ejecuta

el programa. Como ya hemos visto, hay dos modos de depurar: un depurador software que

simula el funcionamiento del microcontrolador (modo por defecto) y depurador hardware

(mikroICD) que lee directamente el contenido de la memoria del microcontrolador. El

procedimiento de depuración es el mismo sin reparar en el modo elegido. En caso de elegir

la opción ICD debug, hay que cargar el programa en el microcontrolador antes de depurarlo.

Para iniciar la depuración, pulse sobre la opción Start debugger del menú Run. El editor del

código será ligeramente modificado automáticamente y aparecerá una ventana denominada Watch

Values. El principio de depuración se basa en ejecutar el programa paso a paso y monitorear

el contenido de los registros y los valores de las variables. De este modo, es posible

comprobar el resultado de un cálculo y ver si algo inesperado ha ocurrido. Al ejecutar el

programa paso a paso, podrá localizar los problemas con facilidad.

Durante una depuración el programa será modificado, por lo que usted siempre debe

recompilar el programa después de cada corrección, y reiniciar el depurador para comprobar

qué ha sido modificado.

COMANDOS DEL DEPURADOR

Hay varios comandos disponibles para depurar el código:

Page 53: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Step Into - Ejecuta una sola instrucción. Cuando la instrucción es una llamada a una

rutina, el depurador hará un salto a la rutina y se detendrá después de ejecutar la

primera instrucción dentro de la rutina.

Step Over - Se ejecuta una sola instrucción. Cuando la instrucción es una llamada a

una rutina, el depurador no hará un salto a la rutina, sino que se ejecutará toda la

rutina. El depurador se detiene a la primera instrucción después de la llamada a la

rutina.

Run To Cursor - El programa se ejecuta hasta la línea en la que se encuentre el

cursor.

Step out - Se ejecutan las demás instrucciones dentro de la rutina. El depurador se

detiene inmediatamente al salir de la rutina.

PUNTOS DE RUPTURA (BREAKPOINTS)

Los puntos de ruptura hacen el proceso de depurar los programas de una manera más

eficiente, puesto que permiten ejecutar el programa a toda velocidad y detenerlo

automáticamente en una línea específica (punto de ruptura). Eso resulta muy útil,

permitiéndole comprobar sólo las partes críticas del programa y no perder el tiempo

probando todo el programa línea a línea. Para añadir o quitar un punto de ruptura basta con

pulsar sobre la línea apropiada en el lado izquierdo del editor del código, o presionar

[F5]. Una pequeña ventana denominada Breakpoints muestra dónde están los puntos de ruptura.

Note que las líneas designadas como puntos de ruptura están marcadas en rojo.

La línea que se está ejecutando actualmente está marcada en azul. Es posible leer el

contenido de registros y variables seleccionados en la ventana Watch Values en cualquier

momento. Para ejecutar la parte de programa desde la línea en la que está el cursor hasta

el punto de ruptura, utilice el comando Run/Pause Debugger.

Page 54: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

VENTANA WATCH VALUES

El depurador software y hardware tienen la misma función de monitorear el estado de los

registros durante la ejecución del programa. La diferencia es que el depurador software

simula ejecución de programa en una PC, mientras que el depurador ICD (depurador hardware)

utiliza un microcontrolador real. Cualquier cambio de estado lógico de los pines se indica

en el registro (puerto) apropiado. Como la ventana Watch Values permite monitorear el

estado de todos los registros, resulta fácil comprobar si un pin está a cero o a uno. La

última modificación está marcada en rojo en la ventana Watch Values. Esto le permite

localizar la modificación en la lista de variables y registros durante el proceso de la

depuración.

Page 55: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Para visualizar esta ventana es necesario seleccionar la opción View/Debug Windows/Watch Values.

Entonces usted puede hacer una lista de registros/variables que quiere monitorear y la

manera de visualizarlos.

STOPWATCH (CRONÓMETRO)

Si quiere saber cuánto tiempo tarda un microcontrolador en ejecutar una parte del programa,

seleccione la opción Run/View Stopwatch. Aparecerá una ventana como se muestra en la figura

a la derecha. ¿Cómo funciona un cronómetro? Eso es pan comido... El tiempo que tarda un

comando (step into, step over, run/pause etc.) en ejecutarse por el depurador se mide

automáticamente y se visualiza en la ventana Stopwatch. Por ejemplo, se mide tiempo para

ejecutar un programa, tiempo para ejecutar el último paso etc.

PROGRAMAR EL MICROCONTROLADOR

Si ha solucionado todos los errores en su código y cree que su programa está listo para ser

utilizado, el siguiente paso es cargarlo en el microcontrolador. El programador PICflash se

utiliza para este propósito. Es una herramienta diseñada para programar todos los tipos de

microcontroladores PIC. Está compuesto por dos partes:

La parte hardware se utiliza para introducir un código hexadecimal (el programa a ser

cargado en el microcontrolador) y para programar el microcontrolador por medio de

niveles de voltaje específicos. Durante el proceso de la programación, un nuevo

Page 56: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

programa se escribe en la memoria flash del microcontrolador, mientras que el

programa anterior se borra automáticamente.

La parte de software se encarga de enviar el programa (archivo .hex ) a la parte

hardware del programador por medio de un cable USB. A la interfaz de usuario de este

software se le puede acceder desde IDE al pulsar sobre la opción mE_Programmer del

menú Tools o al pulsar [F11]. Por consiguiente, es posible modificar algunas

configuraciones del programador y controlar el funcionamiento de la parte hardware

(Cargar, Escribir, Verificar...).

Se puede reprogramar el microcontrolador tantas veces como se necesite.

Page 57: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

OTRAS HERRAMIENTAS DEL COMPILADOR

El compilador mikroC PRO for PIC proporciona herramientas que en gran medida simplifican el

proceso de escribir el programa. Todas estas herramientas se encuentran en el menú Tools.

En la siguiente sección vamos a darle una breve descripción de todas ellas.

TERMINAL USART

El terminal USART representa una sustitución para la estándar Windows Hyper Terminal. Se

puede utilizar para controlar el funcionamiento del microcontrolador que utiliza la

comunicación USART. Tales microcontroladores están incorporados en un dispositivo destino y

conectados al conector RS232 de la PC por medio de un cable serial.

La ventana USART terminal dispone de opciones para configurar la comunicación serial y

visualizar los datos enviados/ recibidos.

EDITOR EEPROM

Al seleccionar la opción EEPROM Editor del menú Tools, aparecerá una ventana como se

muestra en la siguiente figura. Así es cómo funciona la memoria EEPROM del

microcontrolador. Si quiere cambiar de su contenido después de cargar el programa en el

microcontrolador, ésta es la forma correcta de hacerlo. El nuevo contenido es un dato de un

tipo específico (char, int o double), primero debe seleccionarlo, introducir el valor en el

campo Edit Value y pulsar sobre Edit. Luego, pulse sobre el botón Save para guardarlo como

un documento con extensión .hex. Si la opción Use EEPROM in Project está activa, los datos

se cargarán automáticamente en el microcontrolador durante el proceso de la programación.

Page 58: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

VENTANA ASCII CHART

Si necesita representar numéricamente un carácter ASCII, seleccione la opción ASCII chart

del menú Tools. Aparecerá una tabla, como se muestra en la figura que está a continuación.

Usted probablemente sabe que cada tecla de teclado está asociada con un código (código

ASCII). Como se puede ver, los caracteres que representan los números tienen valores

diferentes. Por esta razón, la instrucción de programa para visualizar el número 7 en un

LCD no visualizará este número, sino el equivalente a la instrucción BEL. Si envía el mismo

número en forma de un carácter a un LCD, obtendrá el resultado esperado - número 7. Por

consiguiente, si quiere visualizar un número sin convertirlo en un carácter apropiado, es

necesario añadir el número 48 a cada dígito en el que consiste el número a visualizar.

Page 59: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

EDITOR DE SIETE SEGMENTOS

Un editor de siete segmentos le permite determinar con facilidad el número a poner en un

puerto de salida con el propósito de visualizar un símbolo deseado. Por supuesto, se da por

entendido que los pines del puerto deben estar conectados a los segmentos del visualizador

de manera apropiada. Basta con colocar el cursor en cualquier segmento del visualizador y

pulsar sobre él. Se visualizará inmediatamente el número a introducir en el programa.

LCD CUSTOM CHARACTER (CARACTERES LCD DEFINIDOS POR EL USUARIO)

Además de los caracteres estándar, el microcontrolador también puede visualizar los

caracteres creados por el programador. Al seleccionar la herramienta LCD custom character,

se evitará un pesado trabajo de crear funciones para enviar un código apropiado a un

visualizador. Para crear un símbolo, pulse sobre los cuadros pequeños en la ventana LCD

Page 60: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

custom character, luego seleccione la posición y la fila y pulse sobre el botón GENERATE.

El código apropiado aparece en otra ventana. No es necesita pulsar más. Copy to Clipboard

(copiar al portapapeles) - Paste (pegar)...

GENERADOR DE MAPA DE BITS PARA UN LCD GRÁFICO

El generador de mapa de bits para un LCD gráfico es una herramienta insustituible en caso

de que el programa que escribe utilice el visualizador LCD (GLCD). Esta herramienta le

permite visualizar un mapa de bits con facilidad. Seleccione la opción Tools/Glcd Bitmap

Editor aparecerá la ventana apropiada. Para utilizarlo, seleccione el tipo de visualizador

a utilizar y cargue un mapa de bits. El mapa de bits debe ser monocromático y tener la

resolución apropiada del visualizador (128 x 64 píxeles en este ejemplo). El procedimiento

a seguir es igual que en el ejemplo anterior: Copy to Clipboard...

Page 61: CAPITULO 2 -PROGRAMACIÓN DE LOS MICROCONTROLADORES

Un código generado que utiliza herramientas para controlar los visualizadores LCD y GLCD contiene funciones de la librería

Lcd. Si las utiliza en el programa, no se olvide de marcar la caja de chequeo junto a esta librería en la ventana Library

Manager. Así el compilador será capaz de reconocer estas funciones correctamente.