Sunteți pe pagina 1din 41

LENGUAJE C ORIENTADO A CONTROLADORES Un programa codificado en lenguaje C resulta muy til en la aplicacin de Controladores, dado que su compilacin es bastante

eficiente y ptima acercndose a la codificacin de lenguaje de mquina. Lo descriptivo de la sintaxis permite elaborar de mejor forma los algoritmos olvidndose de los molestos push y pop usados en el lenguaje de mquina cuando se usan saltos a subrutinas. En la primera parte se plantean elementos genricos de lenguaje C, pero siempre mirando las posibles aplicaciones con Controladores. Elementos bsicos Comentario, este permite la documentacin del cdigo y se usa de acuerdo a la siguiente sintaxis /* Este es un comentario */ o // Este es un comentario Inicio y fin de bloque, permite agrupar un nmero de instrucciones las que pueden ser ejecutadas con cierta prioridad. Se usa {para iniciar bloque y } para finalizar bloque. { // Inicio de bloque // Instrucciones } // Final de bloque Identificador, es el nombre que se le da a una variable o funcin por lo general asociado al tipo de dato que ha de contener la variable o al tipo de procedimiento que ha de realizar la funcin. Tipo, es una palabra reservada definida que indica el tipo de variable que se ha de definir y su alcance numrico, esto de acuerdo a la Tabla 1. Tabla 1. Tipo Char Int Long Float Cdigo Entero de 8 bit Entero de 16 bit Entero de 32 bit Real de codificado en 32 bit Tipo de compilador C Estndar Estndar Estndar Estndar

Doubl uns16 uns32

Real codificado en 64 bit Entero sin signo 16 bit Entero sin signo 32 bit

Estndar CCS CCS

As, la definicin de las variables se hace usando el tipo y un identificador que da el nombre de la variable finalizado por un punto y coma (;). Tambin puede definir varias variables con un solo tipo. En esta caso son separadas por coma (,) pero siempre se finaliza con punto y coma. Char i; // define variable tipo char de 8 bits Char j,i; Float x,r; Long a,b,c,d; Int i,j; // define dos enteros Estructura bsica de un programa La estructura de un programa bsico en lenguaje C se indica en el esquema de la Fig. 1, el cual muestra un bloque principal llamado main () y bloques de funciones. Puede ser, dependiendo de la aplicacin, que solo se requiera del bloque principal.
Void funcin_1 ( ) { } Void main ( ) {

Void funcin_2 ( ) { }

Fig.1. Esquema de un programa

El siguiente cdigo fuente contempla la declaracin de las variables y el mdulo principal. // Ejemplo de programa sin funciones // Aqu se definen las variables globales Void main () { // Aqu se definen las variables locales // Aqu van las instrucciones } Una variacin permite incorporar la declaracin de las variables y el mdulo principal y la zona donde se recomienda se escriban las funciones. // Ejemplo de programa con funciones // Aqu se definen las variables globales // Aqu se Escriben las funciones Void main () { // Aqu se definen las variables locales // Aqu van las instrucciones y llamados a funciones } Void main ( ) { } Void funcion_1 ( ) {

} Void funcion_2 ( ) { } Instrucciones bsicas Estos son los elementos ms bsicos para la generacin de un programa, se considera: asignacin, operaciones matemticas, operaciones lgicas. Asignaciones Consiste en asignarle un valor a una determinada variable. En el ejemplo se declaran dos variables de 8 bits y luego se le asignan los valores respectivos. Char i, j; // Declaracin de variables Void main ( ) { i=10; j=20; // Aqu van otras instrucciones } Los valores asignados a las variables tipo char o int pueden tener distintos formatos ya sea decimal, octal, hexadecimal o binario. Esto es muy til dado que en el ms bajo nivel siempre se trabaja en binario. Independencia de la representacin A nivel de un Controlador, todas las instrucciones de traba jan en binario, por lo tanto, los datos tambin, es decir, se puede representar un valor en un formato numrico, ya sea hexadecimal, decimal o tipo carcter, pero a bajo nivel es siempre binario. Por ejemplo, sea la variable dato, la cual se le asigna el valor 49. Este valor ser almacenado en memoria en formato binario como 00110001, lo que representado en formato hexadecimal corresponde al 31H.

Void main ( ) { Char dato; Dato = 49; } Dato 0 0 1 1 0 0 0 1

Fig.2. Almacenamiento del dato en memoria. En el caso de trabajar con 16 bit, el formato hexadecimal quedar 0x0031. Formatos de asignacin La asignacin puede ser hecha en decimal, hexadecimal, binario o carcter (si es que se conoce). La Tabla 2, indica el formato binario para el compilador CC5X. 1Tabla 2. Decimal 10 125 49 65 Binario(*) 0b00001010 0b01111101 0b00110001 0b01000001 hexadecimal 0x0a 0x0A 0x7D 0x7d 0x31 0x41 ASCII LF } 1 A

Note que el nmero codificado hexadecimal comienza con 0x, es decir 31H ser 0x31 y el binario comienza con 0b, es decir, 00110001 ser 0b00110001 (este segundo formato corresponde al entregado por el compilador CCS. El caso de las variables tipo char se tiene el siguiente ejemplo, se inicializa una variable con el valor 1 ASCII, sin embargo esto se puede realizar de varias formas. Char c; Void main ( ) { c=0x31; // en hexa

c=49; // en decimal c=1; // en carcter ASCII } Int d; Long x; Void main() { d=0xA031; // en hexa x=49000L; // en long } Operaciones Matemticas Se tienen la suma, resta multiplicacin y divisin, divisin entera ms las operaciones de incremento y decremento. Char i,j, k; Void main ( ) { i=10; j=20; k=i+j; //suma de 2 enteros k=i-j; // resta de 2 enteros k=i*j; // multiplicacin de 2 enteros k=i%j; // Division entera (debe dar el resto) k++; // incremento k=k+1 k--; // decremento k=k-1; }

Operaciones Lgicas Se realizan con variables enteras y afectan directamente al bit del dato, se tienen los operadores lgicos y los desplazamientos a la Izquierda y a la derecha. Char i,j, k; Void main ( ) { k=i&j; // operacin AND entre i y j bit a bit k=i|j; // operacin OR entre i y j bit a bit k=~i; // operacin negacin de i asignado a k k=i<<1; // i desplazado en un bit a izquierda k=i<<2; // i desplazado en 2 bit a izquierda k=i>>1; // i desplazado en un bit a la derecha k=i<<2; // i desplazado en 2 bit a la derecha } Sentencias de control Permiten definir las funciones a ejecutar dependiendo de ciertas condiciones que se deben evaluar. Estas condiciones pueden ser tipo lgicas, tipo mayor, menor o igual o ambas. Por lo general se agrupan entre parntesis para definir la prioridad de la evaluacin de la condicin. Tabla 3. Operador de condicin == != >< >= =< && || Descripcin Igual Distinto Mayor, menor Mayo o igual, Menor o igual Operador Y Operador O

La condicin verdadera puede ser tambin de la siguiente forma: Si se quiere preguntar por una variable que es mayor que cero solo se coloca la variable si se quiere preguntar si es falsa entonces se niega, usando el operador !. Sentencia if-else Puede usarse el if solo o el if-else. Si la condicin es verdadera entonces se ejecuta una instruccin o un grupo de instrucciones en caso contrario se ejecuta la que sigue. Char i,j,k,h; Void main ( ) { i=10; j=20; if(i==j) k=1; // si i=j entonces k=1 sino k=2 else k=2; // s i=10 entonces k=20,j=10 sino k=40,j=20,h=60 if(i==10) { k=20; j=10; } else { k=40; j=20; h=k+j; } // Si i=10 y j=20 entonces...

if((i==10) && (j==20)) { k=20; j=10; } if(i) k=20; // si i es mayor que cero if(!i) k=20; // si i es cero } Sentencia while Esta evala la condicin al inicio, si sta es verdadera, entonces se ejecuta el bloque que viene a continuacin en caso contrario lo salta. El formato es el siguiente: While (condicin) instruccin; While (condicin) { instruccin_1; ... Instruccin_n; } En el siguiente cdigo fuente se muestra que el ciclo while se realiza ya que i siempre sea mayor que 0. Sin embargo en algn momento i ser menor que 0, dado que k se va decrementando y se hace igual a i dentro del ciclo. Char i,j,k,h; Void main ( ) { i=1; k=40; j=10; While (i>0) // Solo mientras i>0 hace lo que viene a cont. {

h=k+j; k--; i=k; } } En el ejemplo slo se evala la condicin verdadera, pero nunca sele del ciclo. Char i,j,k,h; Void main() { i=1; // Solo mientras i mayor que cero hace lo que viene a cont. While (i) // Puede usarse while(1) { k=40; j=20; h=k+j; } } Para salir de un ciclo donde no existe posibilidad de que la condicin sea alterada, se puede usar la sentencia break. Char i,j,k,h; Void main ( ) { i=0; While (1)

{ i++; if(i==5)break; // Sale cuando i=5 } } La sentencia do-while se evala la condicin al final, por ejemplo Hgalo mientras se cumpla la condicin. Void main () { Char i; i=10; do { i--; } While (i!=5); // Sale cuando i=5 } Sentencia switch - case Esta instruccin se usa cuando se deben seleccionar entre varias opciones tipo numricas. Es bsicamente un selector. Char c; Void main () { // se le debe asignar el valor a la var. c Switch(c)

{ Case 1: // debe saltar a funcin Break; Case 2: // debe saltar a funcin Break; Case 3: // debe saltar a funcin Break; } } Sentencia for Permite el uso de los clsicos ciclos for. El formato es el siguiente: For(expr_1;expr_2;expr_3)instruccin; For(expr_1;expr_2;expr_3) { instruccin_1; ... Instruccin_n; } Tabla 4. Descripcin expr_1 Condicin de comienzo, pueden haber varias inicializaciones separadas por coma. Se efectuar el bucle mientras se cumpla esta condicin, se evala la condicin antes de entrar al bucle. Indica lo que hay que hacer cada vez que se termina el bucle, puede haber varias instrucciones separadas por una coma.

expr_2

expr_3

El cdigo fuente muestra que la variable i se inicializa en cero, una vez realizadas las instrucciones dentro del bloque, en este caso, hacer j igual a cero, se ejecuta la instruccin incremento en uno para la variable i. Char i,j; Void main ( ) { For(i=0;i<10;i++) // inc. i desde 0 mientras sea menor que 10 { j=10; // lo repite tantas veces de acuerdo a la condicin } } Funciones y Llamados a funciones Las funciones permiten agrupar cdigo y optimizar el tamao de ste. Se tienen distintos tipos de funciones: Las que solo ejecutan tareas y no devuelven valor. Las que ejecutan y devuelven un valor. Las que reciben parmetros y no devuelven. Las que reciben parmetros y devuelven informacin. El traspaso de informacin a una funcin se realiza a travs de sus argumentos. Por lo general se conoce como paso de parmetros por valor, esto quiere decir que se puede pasar el nmero o dato en forma explcita o a travs de una variable. Cuando el valor se pasa a travs de alguna variable, si el contenido de sta es modificado en el interior de la funcin, el valor de la variable fuera de la funcin no es modificado. El paso de parmetros por referencia solo se puede realizar usando punteros, en este caso, si el dato es pasado mediante una variable a la funcin, y ste es modificado al interior de ella, su modificacin se ver reflejada fuera de la funcin. El uso de punteros en este caso como argumento permite manejar dicha situacin,

ya que lo que se est transfiriendo a la funcin es la direccin donde se encuentra el dato. Funciones que no usan argumentos Estas funciones son identificadas con un nombre de acuerdo a la tarea que realizan, el identificador utilizado obedece al mismo esquema en el cual se declaran las variables. Sin embargo, el identificador de las funciones lleva parntesis (). Habitualmente son declaradas antes del main () antes de ser utilizadas, pero para ahorrarse este proceso por lo general se escriben sobre el Void main(). Las funciones que no devuelven valor son declaradas usando la palabra Void junto al nombre de sta, los parntesis y el punto y coma ;. Son llamadas directamente a travs del nombre o identificador correspondiente. La siguiente funcin primero se declara para luego ser llamada desde el programa principal no recibe argumento ni tampoco retorna un valor. Void activar_sensores (); // Declaracin Void main ( ) { activar_sensores ( ); // salta a la funcin correspondiente } Void activar_sensores ( ) { // Instrucciones } En el caso de no recurrir a la declaracin, es escribe la funcin sobre el Void main ( ). Void activar_sensores ( ) { // Instrucciones }

Void main() { activar_sensores ( ); // salta a la funcion correspondiente } Las que devuelven valor deben ser llamadas a travs de una asignacin, en donde el nombre de la funcin es asignado a una variable que recibir el resultado devuelto por la funcin. La funcin en este caso debe ser declarada (o definida) considerando el tipo de valor que ha de retornar o devolver. La siguiente funcin es declarada tipo char, retorna el valor correspondiente, por lo tanto al ser llamada, la funcin inmediatamente debe ser asignada a una variable del mismo tipo a ser retornada. Char lee_sensores ( ); Void main ( ) { Char sensor; Sensor=lee_sensores(); // salta a la funcin y retorna el valor en la variable sensor } Char lee_sensores ( ) { Char x; // Instrucciones // Se debe asignar el valor de x en alguna parte Return (x); // devuelve el valor de x tipo char } Se repite el procedimiento, pero esta vez se omite la declaracin, pero se escribe la variable antes del main ( ).

Char lee_sensores ( ) { Char x; // Instrucciones // Se debe asignar el valor de x en alguna parte Return (x); // devuelve el valor de x tipo char } Void main ( ) { Char sensor; Sensor=lee_sensores (); // salta a la funcin y retorna el valor en la variable sensor } Para el paso de los argumentos, estos son definidos entre los parntesis de la funcin considerando el tipo de la variable requerida. La siguiente funcin recibe un parmetro tipo char por valor y no retorna valor. Void activa motor (char num_motor) { // Instrucciones } Void main() { Char sensor; activa_motor (1); // pasa el valor 1 haciendo ref. al nm. de motor }

El siguiente ejemplo muestra una funcin que recibe parmetros y retorna un valor. El valor retornado a su vez puede ser usado por una sentencia de control para tomar alguna decisin. Char enviar (char dato) { Char status; // cdigo Return (status); } Void main() { Char estado_com; While (1) { estado_com=enviar (0xaa); if(estado_com!=1) break; } } Punteros Los punteros son variables que almacenan la direccin de una variable, el contenido de dicha variable es accesado en forma indirecta. La variable tipo puntero se define en forma similar a una variable que almacena datos, pero se agrega un *. Char *p; //p es un puntero a un char Char i, *p; // i es un char y p es un puntero a char Int j, *p; // j es una var entera y p es un puntero a entero Qu quiere decir puntero a char o puntero a int ?. Simple, cuando un puntero a char se incrementa, la direccin almacenada en la variable se incrementa en una

posicin de memoria en cambio en un puntero a int se incrementa de 2 posiciones. En el caso de que fuera a una variable tipo long, la direccin se incrementara en 4 posiciones de memoria. Para saber la direccin de memoria de una variable y asignarla a un puntero se usa el operador & y el nombre de la variable o solo el nombre de la variable. Char i, *p; // i es un char y p es un puntero a char Void main ( ) { p=&i; // p almacena la direccin de memoria donde esta i } Para saber el contenido de la variable apuntada por el puntero se usa el operado *. char i, j, *p; // i y j char y p es un puntero a char void main() { i=10; // i contiene el valor 10 p=&i; // p almacena la direccin de memoria donde esta i j=*p; //El contenido de p es almacenado en j } i=10; i 0200h j 0201h p 0202h
10

p=&I I 0200h j 0201h p 0202h


0200 10

j=*p I 0200h j 0201h p 0202h


10

10
0200

Fig.3. Manejo de puntero. Uno de los usos de los punteros es para el paso de variables por referencia a una funcin, es decir, el valor de la variable que se pasa como argumento a la funcin cambia si es que en el interior de la funcin cambia.

Esto ocurre a que en vez de pasar el valor del argumento a la funcin, se pasa su direccin. Esto se podr realizar si se utiliza un puntero. El siguiente ejemplo es solo ilustrativo, ya que si se va a devolver un valor, puede usar la instruccin Return (). Void duplicar (char *p) { *p=(*p)*2; } Void main ( ) { Char dato, *pdato; Dato =10; Pdato =&dato; Duplicar (pdato); } Arreglos y matrices Los arreglos son vectores unidimensionales (llamados string o cadenas) o bidimensionales (Matrices). Su formato es el siguiente: Tipo ident_arreglo [num_elementos]; Tipo ident_arreglo [num_fila][num_col]; A continuacin se muestran ejemplos de arreglos unidimensionales y bidimensionales Char cadena [10];// define una var string llamada cadena de 10 char Int datos [15]; // define una var string llamada datos de 15 int Char cad [2][3]; // define una matriz cad de 2 filas y 3 col Los arreglos pueden contener nmeros o caracteres, pueden ser usados para manejo de cadenas de caracteres o string. Es conveniente siempre inicializar con

un valor los arreglos. El primer elemento del arreglo corresponder al almacenado en la posicin 0 y el n-simo elemento corresponder al almacenado en la posicin n-1 del arreglo. Cuando se definen los arreglos, estos ocupan zonas completas de memoria, con direcciones consecutivas. Inicializacin de arreglos Los arreglos pueden inicializarse elemento a elemento si es que es pequeo, o a travs de la inicializacin usando la cadena completa. Char data [5],i; Void main () { For (i=0;i<5;i++) data[i]=0; // rellena con 0s } Los arreglos pueden ser inicializados con mensajes, estos son formados por cadenas de caracteres llamados cadenas o string. Habitualmente, se usan las comillas para establecer o limitar el mensaje. // Esta inicializacin corresponde al Turbo C Char msg [10]={"HOLA"}; // C estndar Char x [7]={"Juan\xd"}; Char c[]={"popo"}; En los compiladores C estndar, cada cadena termina con el carcter 0x00 a continuacin del ltimo carcter. De esta forma en el ejemplo de la cadena msg, el elemento 5 de la cadena debe llevar un carcter 0x00.
H O L A 0X00

msg[0]
0X48

msg[1]
0X4C

msg[2] msg [3]


0X41 0X00

msg[4]
? ? ? ?

Las funciones ms usadas en el manejo de cadenas son la copia de cadenas o la concatenacin de cadenas. Las cadenas comnmente pueden ser usadas con caracteres de control tales como el 0x0d (CR) o el 0x0a (LF). Estos caracteres pueden ser incorporados al final de la cadena en forma directa en la posicin correspondiente o de la siguiente forma: Char msg [10]={ "HOLA\xd\xa"};
0X48 0X4F 0X4C 0X41 0X0d 0X0a 0X00 0X48 ?

Arreglos y punteros Los punteros pueden ser inicializados con la direccin inicial del arreglo, de esta forma se tiene Char cad [10], *pcad; //Formas equivalentes Pcad=&cad [0]; Pcad=&cad; Pcad=cad; Los punteros pueden usarse para apuntar al primer elemento de una cadena y se pueden inicializar de acuerdo al siguiente ejemplo. Char *p="chao"; Pasando cadenas a funciones Habitualmente se utilizan punteros, debido a que se pasa la direccin del primer elemento de la cadena, evidentemente, el puntero debe ser del mismo tipo del dato apuntado, de tal forma que cuando se incremente el puntero, se incremente en una posicin dentro del arreglo. En C estndar se tiene que se asigna un puntero al primer elemento de la cadena, esto permite pasar filas completas. El siguiente ejemplo permite traspasar un mensaje ASCII a una cadena. Este ejemplo compila en C estndar y CCS. Void copy_msg (char *pdest, const char *porig)

{ Char x; While (1) { x=*porig; *pdest=x; If (*porig==0x00) Break; Pdes t++; Porig ++; } } Void main ( ) { Char msg [8]; copy_msg (msg,HOLA); // Copia en la variable msg la cadena HOLA } Copiando del contenido de una cadena en otra, est codificado para CCS Void copy_str (char *pd, char *po) { Char x; While (1) { x=*po;

*pd=x; if(*po==0x00) break; pd++; po++; } } Void main ( ) { Char msg [8],cad[8]; Cad [0]='C'; Cad [1]='H'; cad [2]='A'; cad [3]='O'; copy_str (msg,cad); } Pudiera el quinto caracter no ser 0x00, para evitar esto, se agrega en la inicializacin. Char msg *10+=,HOLA\x0-; // Este es para C estndar Char *pcad=HOLA\x0; El ejemplo siguiente permite traspasar una cadena a una funcin. Void enviar_msg (char *p) { Char i; i=0; While (i)

{ } } Void main ( ) { Char msg*10+=,HOLA-; Char *pm; pm=&msg[0]; enviar_msg (pm); }

El Controlador y el compilador CCS Arquitectura del C Para las aplicaciones se utilizar un C basado en la familia 16F87Xa de microchip. Este C contiene registros, mdulos ADC, comunicacin serial, temporizadores y manejo de interrupciones. Adems posee un memoria de programa de entre 4 y 8Kbytes, su reloj puede ser de entre 4 y 20MHz. (ver data C16F87xA). Un esquema simplificado es el de la Fig. 4.
PORT A RAM ARCHIVOS REGISTROS CPU PCL MEMORIA FLASH DE PROGRAMAS PORT C PORT B

TIMER 0

TIMER 1

TIMER 2

10 BITS - ADC

REF VOLTAJE

COMPARADOR

EEPROM

CCP1,2

USART

Fig. 4. Esquema simple del C 16F87XA.

PUERTO SERIAL SINCRONO ADC

Es bastante sencillo de hacer funcionar, solo basta un par de capacitores, el cristal ms un resistor, de acuerdo a la Fig. 5. En dicho circuito, el terminal 28 correspondiente al bit ms significativo del puerto B, se usar como monitor del funcionamiento. La tarea bsica a implementar ser poner en 1 y en 0

alternadamente el bit mencionado de tal forma de visualizarlo mediante un instrumento.

U1 X1
CRYSTAL 9 10 2 3 4 5 6 7 1 OSC1/CLKIN OSC2/CLKOUT RB0/INT RB1 RB2 RB3/PGM RB4 RB5 RB6/PGC RB7/PGD 21 22 23 24 25 26 27 28 11 12 13 14 15 16 17 18

C1
22uF

C2
22uF

R1
R

RA0/AN0 RA1/AN1 RA2/AN2/VREF-/CVREF RA3/AN3/VREF+ RA4/T0CKI/C1OUT RA5/AN4/SS/C2OUT RC0/T1OSO/T1CKI MCLR/Vpp/THV RC1/T1OSI/CCP2 RC2/CCP1 RC3/SCK/SCL RC4/SDI/SDA RC5/SDO RC6/TX/CK RC7/RX/DT PIC16F873A

Fig.5. Esquema de para funcionamiento bsico. Entorno de desarrollo El entorno de desarrollo MPLAB permite el trabajo con el C incorporando al editor y herramientas de simulacin y un compilador proporcionado por otro fabricante, en este caso el compilador C CCS desarrollado por B. Knudsen (ver www.bknudsen.com). Al trabajar con el compilador CCS, se debe incorporar el archivo cabecera 16F873a.h, esto automticamente permite configurar el entorno de trabajo, quedando definido todos los recursos de la CPU, registros y mdulos con los nombres identificados en la referencia tcnica del C (ver datasheet). Se sugiere revisar el archivo de cabecera y contrastarlo con los nombres de los registros y direcciones asociadas descritas en el manual. Los registros de C vienen definidos en el archivo de cabecera, estos pueden ser accesados directamente al igual que tambin sus bits individuales. En algunos casos los registros ya tienen definidos algunos bits internos usando otros identificadores, esto no es incompatible entre s.

Como ejemplo se tiene el caso del puerto B, llamado PORTB por el compilador CCS, el cual est definido en el archivo de cabecera como una variable entera de 8 bits. Manejo de Puertos de E/S El C posee al menos 3 puertos que pueden ser usados como entradas-salidas digitales o como entradas anlogas (si corresponde). Los Puertos son bsicamente registros de 8 bits basados en Flip-Flops Tipo D, que pueden ser usados como entrada o salida. Los nombres de los puertos corresponden a los especificados en la data del C, as se tiene el PORTB de 8 bits, el PORTC de 8 bit y el PORTA de 5 bits. Dichos bits se configuran como entrada o salida a travs de un registro llamado TRIS. Para el caso del Puerto A ser TRISA, para el puerto B, se usa el TRISB, etc. Los puertos sealados poseen ms de una funcin. Estos puertos del C se usan como si fueran variables enteras de 8 bit y pueden accesarse nivel de bit o en forma de bytes. Primero se debe especificar si el bit es de entrada o salida, esto se hace definiendo el bit correspondiente como salida, esto se hace con el registro TRISx (x es el puerto A, B o C) mediante el set o reset de dicho registro. Cada bit del registro TRISx maneja la entrada o salida del bit correspondiente del PORTx. TRISB.0=0; // Bit 0 del puerto B se define como salida TRISC.7=1; // Bit 7 del puerto C se define como entrada Puede definirse todo el puerto como entrada o salida o mezcla de ambas situaciones usando un byte completo sobre el registro TRIS correspondiente. TRISB=0x00; // los 8 bit del PORTB como salida TRISC=0xFF; // los 8 bits del PORTC como entrada TRISB=0x0f; // Los 4 bit ms significativos de entrada, // los 4 bit menos significativos como salida La Fig. 6 muestra un diagrama funcional del terminal PORTB.0, el cual es controlado por el bit 0 del TRISB (TRISB.0).

Fig.6. Esquema funcional del PORTB.0.

PRACTICA #1
(Prender y Apagar un LED) -Antes de empezar a escribir el programa debemos crear un archivo nuevo. 1. Todo programa inicia con la misma instruccin, #include <xxxxxx.h>, esta instruccin es la que nos indica que Microcontrolador vamos a utilizar y siempre debe ir seguido de la extensin .h; en este programa usaremos el Microcontrolador 18f2550 por lo tanto la instruccin quedara as: #include <18f2550.h>. Ya tenemos nuestra primera instruccin. 2. Ahora debemos indicarle al programa el valor del cristal que vamos a utilizar esto se hace en la siguiente instruccin: #use delay(clock=xxxxxx), en nuestro caso el cristal ser de 8Mhz por lo tanto la instruccin queda de la siguiente manera: #use delay(clock=8000000), ya tenemos dos instrucciones. #include <18f2550.h> #use delay(clock=8000000)

3. Despus de escoger el micro y el valor del cristal empezamos con la funcin principal, se denomina funcin principal porque es el inicio de todo programa; al iniciar una rutina el programa siempre va a buscar esta funcin y a empezar desde la primera instruccin que este contenga, esta funcin se escribe de la siguiente manera: void main (void), y lo que se escriba dentro de esta funcin tiene que ir dentro de unos corchetes { }, mas adelante se explicara un ejemplo. #include <18f2550.h> #use delay(clock=8000000) void main (void) { } 4. Ya todo est listo ahora encendamos el led; podemos escoger cualquier puerto y cualquier pin, nosotros usaremos el puerto B y el pin B0, usamos la instruccin output_high(pin_b0); , esta instruccin nos enciende el led; output significa salida, high significa alto, y pin_b0 es el pin que vamos a utilizar; unindola significa que a la salida del pin_b0 hay un alto (voltaje positivo), que permite encender el led. #include <18f2550.h> #use delay(clock=8000000) void main (void) { output_high(pin_b0); }

-Pero antes de apagar el led debemos darle un retardo de encendido, un retardo se escribe de la siguiente forma: delay_ms(xxxx); , un retardo se puede dar en milisegundos (ms) o en microsegundos(us), nosotros colocaremos el retardo de un segundo: delay_ms(1000); . #include <18f2550.h> #use delay(clock=8000000) void main (void)

{ output_high(pin_b0); delay_ms(1000); }

-Ahora si apaguemos el led se hace de la misma forma en que lo encendimos solo cambia una palabra en ves de indicarle un alto le indicamos un bajo: outout_low(pin_b0); , ahora a la salida del pin_b0 hay un bajo (un voltaje igual a cero), con esto nuestro led se apago, y enseguida le damos otro retardo pero esta ves es de apagado. #include <18f2550.h> #use delay(clock=8000000) void main (void) { output_high(pin_b0); delay_ms(1000); outout_low(pin_b0); delay_ms(1000); } -Y ese es nuestro programa de encender y apagar un led, pero tenemos un problema, el led solo se va a prender y apagar una sola vez; debemos darle la orden al micro para que siempre haga esta rutina indefinidamente, esto lo logramos de la siguiente manera: 5. Para que nuestro micro no se desborde y se pierda le agregamos la siguiente instruccin para indicarle al micro que el programa nunca se acaba y que siempre este trabajando: while(true), esta instruccin hace que lo que esta dentro de ella siempre se va a hacer hasta que la condicin sea falsa, pero como nosotros le dimos la orden de que la condicin es verdadera siempre me va a repetir la rutina de prender y

apagar el led; y lo que se escriba dentro de este while tambin debe ir dentro de unos corchetes { }. Ya solucionamos nuestro problema y el programa queda as: #include <18f2550.h> #use delay(clock=8000000) void main (void) { while(true) { output_high(pin_b0); delay_ms(1000); outout_low(pin_b0); delay_ms(1000); } }

-Este ya es nuestro programa final. *Nota: -Una vez terminado el programa se recomienda presionar la tecla f9 para comprobar que este no contenga errores, si el programa contiene algn error aparecer un aviso de color rojo en la parte inferior de la pantalla indicando donde se encuentra el error.

PRACTICA #2
(Secuencia de 8 Leds) *Forma 1 -En este programa haremos que 8 leds prendan consecutivamente y se apaguen de la misma forma, este programa se puede hacer de dos formas diferentes que a continuacin las explicaremos. 1. Iniciamos indicando que micro vamos a trabajar y el valor del cristal a utilizar. #include <18f2550.h> #use delay(clock=8000000) 2. Seguimos con la funcin principal que ya conocemos. Le recuerdo que no se debe olvidar abrir y cerrar los corchetes. #include <18f2550.h> #use delay(clock=8000000) void main (void) { } 3. Ahora empezamos a escribir nuestro programa, es muy sencillo y muy parecido al anterior lo nico que tenemos que hacer es repetir el encendido y apagado 8 veces sin olvidar los retardos; pero no podemos conectar todos los led al mismo pin, por lo tanto tenemos que conectar cada led en un pin diferente, por este motivo vamos a necesitar todo el puerto B. Como recordaremos un led se enciende y apaga de la siguiente manera: output_high(pin_b0); delay_ms(1000); outout_low(pin_b0); delay_ms(1000);

Pero nosotros necesitamos hacerlo 8 veces y lo nico que vamos a cambiar es el pin, por ejemplo: pin_b0, pin_b1, pin_b2.. y esto lo haremos hasta llegar al pin b7. -Por lo tanto esto quedara as: #include <18f2550.h> #use delay(clock=8000000) void main (void) { output_high(pin_b0); delay_ms(1000); outout_low(pin_b0); delay_ms(1000); output_high(pin_b1); delay_ms(1000); outout_low(pin_b1); delay_ms(1000); output_high(pin_b2); delay_ms(1000); outout_low(pin_b2); delay_ms(1000); output_high(pin_b3); delay_ms(1000); outout_low(pin_b3); delay_ms(1000); output_high(pin_b4); delay_ms(1000);

outout_low(pin_b4); delay_ms(1000); output_high(pin_b5); delay_ms(1000); outout_low(pin_b5); delay_ms(1000); output_high(pin_b6); delay_ms(1000); outout_low(pin_b6); delay_ms(1000); output_high(pin_b7); delay_ms(1000); outout_low(pin_b7); delay_ms(1000); } 4. Ya esta listo el programa solo que tenemos el mismo problema que se nos presento en el programa pasado, y como recordaremos solo le tenemos que agregar un while y se soluciona este problema. #include <18f2550.h> #use delay(clock=8000000) void main (void) { While(true) { output_high(pin_b0); delay_ms(1000);

outout_low(pin_b0); delay_ms(1000); output_high(pin_b1); delay_ms(1000); outout_low(pin_b1); delay_ms(1000); output_high(pin_b2); delay_ms(1000); outout_low(pin_b2); delay_ms(1000); output_high(pin_b3); delay_ms(1000); outout_low(pin_b3); delay_ms(1000); output_high(pin_b4); delay_ms(1000); outout_low(pin_b4); delay_ms(1000); output_high(pin_b5); delay_ms(1000); outout_low(pin_b5); delay_ms(1000); output_high(pin_b6); delay_ms(1000); outout_low(pin_b6);

delay_ms(1000); output_high(pin_b7); delay_ms(1000); outout_low(pin_b7); delay_ms(1000); } } Nota: -Recordamos que este es un ejemplo de cmo prender y apagar varios leds, pero se puede hacer cualquier tipo de secuencia todo es cuestin de creatividad. *Esa es una forma de realizar una secuencia de leds ahora vamos a aprender otra forma de hacer la misma secuencia. *Forma 2 1. Iniciamos de la misma forma que siempre: #include <18f2550.h> #use delay(clock=8000000) 2. Antes de empezar a escribir la funcin principal tenemos que declarar las variables que vamos a usar, pero antes vamos a definir que es una variable: -Una variable es donde podemos almacenar ciertos valores que a medida que el programa avance estos van a ir cambiando su valor, una variable se puede llamar de cualquier forma, existen varios tipos de variables, de 8 bits, de 16 bits, y variables decimales; estas variables se declaran de la siguiente forma: *int xxxx; (esta es una variable de 8 bits). *int16 xxxx; (esta es una variable de 16 bits). *float xxxx; (esta es la nica variable que trabaja con nmeros decimales, aunque tambin puede trabajar con nmeros enteros, y trabaja cualquier cantidad de bits). Si se requiere trabajar con mas de una variable se agrega enseguida de la otra separadas de una coma y al final se debe poner un punto y coma ( ; ), ejemplo: int x,y,z; donde -x- es una variable -y- es otra y -z- otra variable.

Ya que tenemos claro que es una variable seguimos con el programa, nosotros utilizaremos 2 variables ( x y aux ), pero las vamos a escribir de la siguiente forma: int x=1,aux[15]; Una variable automticamente no tiene inicio, puede empezar desde cualquier numero por este motivo se recomienda iniciarla desde 0 o 1 para que no haya problemas en el programa, aunque le podemos dar cualquier valor de inicio pero en este caso la iniciamos en 1. La otra variable aux utiliza vectores en este caso son 14 vectores que se van a usar pero tenemos que escribir una mas (15) para que el programa no marque error. Nuestro programa va de la siguiente forma: #include <18f2550.h> #use delay(clock=8000000) int x=1,aux[15]; 3. Empezamos a escribir la funcin principal y la iniciamos escribiendo el valor de cada uno de los vectores de la variable aux y se puede hacer de dos formas: aux[1]=0b00000001; (esta es la forma binaria, se identifica porque el cdigo empieza por 0b que significa que el cdigo esta escrito en binario, recordemos que es una variable de 8 bits por lo tanto solo podemos tener 8 nmeros). aux[1]=0x01; (esta es la forma hexa, se identifica porque empiezan por 0x que significa que el cdigo esta escrito en hexadecimal). Entre las llaves se escribe el numero del vector, en nuestro caso son 14 vectores por lo tanto van a haber 14 combinaciones diferentes. En lo personal prefiero el cdigo binario ya que se puede ver la secuencia que uno est realizando. Nosotros vamos a encender del led 1 al 8 y los apagaremos del 8 al 1; nuestros vectores quedan de la siguiente forma:

aux[1]=0b00000001; aux[2]=0b00000010; aux[3]=0b00000100; aux[4]=0b00001000; aux[5]=0b00010000; aux[6]=0b00100000; aux[7]=0b01000000; aux[8]=0b10000000; aux[9]=0b01000000; aux[10]=0b00100000; aux[11]=0b00010000; aux[12]=0b00001000; aux[13]=0b00000100; aux[14]=0b000000010; Aclaro que un 1 significa un alto y un 0 un bajo. Por ahora nuestro programa va de la siguiente forma: #include <18f2550.h> #use delay (clock=8000000) int x=1,aux[15]; void main (void) { aux[1]=0b00000001; aux[2]=0b00000010; aux[3]=0b00000100; aux[4]=0b00001000;

aux[5]=0b00010000; aux[6]=0b00100000; aux[7]=0b01000000; aux[8]=0b10000000; aux[9]=0b01000000; aux[10]=0b00100000; aux[11]=0b00010000; aux[12]=0b00001000; aux[13]=0b00000100; aux[14]=0b000000010; } 4. Seguimos el programa con un while para evitar el desborde o prdida del micro ahora vamos a utilizar un for, for es un condicional que nos sirve para realizar una secuencia determinada las veces que nosotros le indiquemos al for y luego contine con el programa, por ejemplo podemos hacer que cada led se prenda y apague 5 veces y luego hacer una secuencia; en palabras resumidas podemos decir que el for es un contador. En un for debemos indicar en que numero iniciamos la cuenta, hasta que numero debe contar, y si queremos aumentar o disminuir. Recordemos que estos nmeros debemos almacenarlos en una variable. Vamos a iniciar el for en 1, que cuente hasta 14 y que aumente; esto queda as: for (x=1;x<=14;++x) { } El x<=14 es una condicin: si x es menor o igual a 14 se hace lo que este dentro del for si no cumple esa condicin se sale del for. Continuemos completando el for, ahora vamos a escribir la secuencia que tiene que seguir el for: for (x=1;x<=14;++x)

{ output_b(aux[x]); delay_ms(1000); } Aqu utilizamos nuestro aux, le indicamos al programa que a la salida del puerto B ponga el valor del vector y el valor del vector est determinado por la variable x, por lo tanto cada vez que se repita un for la x va aumentando de uno en uno y cada repeticin va siendo un vector diferente ya que cada vez la x va a tener un valor diferente y siempre la salida al puerto B va cambiando prendiendo y apagando los leds indicados. Se inici con el vector 1 (aux[1]=0b00000001;) al x cambiar de valor pasamos al segundo vector (aux[2]=0b00000010;) as hasta llegar al 14, cuando ya haya llegado al 14 acaba el for y sigue a la siguiente instruccin; pero nosotros no tenemos ms instrucciones por ese motivo fue que colocamos el while antes del for, por lo tanto cuando el for llegue a 14 este vuelve y se reinicia colocando la x en 1 y repitiendo la secuencia. Y el programa final es el siguiente: #include <18f2550.h> #use delay (clock=8000000) #define retardo delay_ms (10) int x=1,aux[15]; void main (void) { aux[1]=0b00000001; aux[2]=0b00000010; aux[3]=0b00000100; aux[4]=0b00001000; aux[5]=0b00010000; aux[6]=0b00100000;

aux[7]=0b01000000; aux[8]=0b10000000; aux[9]=0b01000000; aux[10]=0b00100000; aux[11]=0b00010000; aux[12]=0b00001000; aux[13]=0b00000100; aux[14]=0b000000010; while (true) { for (x=1;x<=14;++x) { output_b(aux[x]); delay_ms(1000); } } }

S-ar putea să vă placă și