microcontroladores parte 1

50

Upload: wilmer-planchez

Post on 06-Mar-2016

235 views

Category:

Documents


4 download

DESCRIPTION

Parte 1 del curso de programación de microcontroladores en lenguaje C.

TRANSCRIPT

Page 1: Microcontroladores Parte 1
Page 2: Microcontroladores Parte 1

1

Autor: Wilmer Planchez Febrero, 2013.

1.- ESTRUCTURA DE UN PROGRAMA EN C

Todo programa en C orientado a microcontroladores cumple con la siguiente estructura:

1.1.- CABECERA.

En la cabecera se incluyen características importantes para el manejo del PIC,

las cuales son:

- Código del microcontrolador.

- Configuración de Fusibles.

- Frecuencia de oscilación.

- Renombramiento de pines.

1.1.1.- CÓDIGO DEL MICROCONTROLADOR.

Para incluir el microcontrolador con el cual se va a trabajar se debe hacer uso de

la directiva #include.

Archivos (conocidos como header File) que posean extensión .h. Estos archivos

contienen información sobre funciones sus argumentos, el nombre de los pines de un

modelo determinado de PIC o cualquier otra herramienta que con frecuencia en nuestros

programas.

Page 3: Microcontroladores Parte 1

2

Autor: Wilmer Planchez Febrero, 2013.

Sintaxis:

#include <archivo>

Ejemplo #1:

#include <16f84A.h>

Donde “<16f84A.h>” es el microcontrolador que queremos utilizar. Por convención,

se utiliza la extensión .h para los archivos de cabecera. Algunos de los

microcontroladores más usados y comunes en el mercado son:

- PIC 12F629 (8 Pines).

- PIC 16F628A (16 Pines).

- PIC 16F873A (28 Pines).

- PIC 16F877A (40 Pines).

- PIC 18F4550 (40 Pines).

1.1.2.- CONFIGURACIÓN DE FUSIBLES.

Los fusibles son características, que posee cada microcontrolador y varían de un

modelo a otro. Todos los microcontroladores tienen 2 tipos de configuraciones

comunes, y que son indispensables que aparezcan, las cuales son:

- Tipo de oscilador.

- Configuracion del Wathcdog.

1.1.2.1.- TIPOS DE OSCILADOR:

a) LP: Oscilador LP (Low Power). Se usa cuando el PIC va a trabajar con un

cristal de baja potencia. (Fosc < 200 Khz).

b) XT: Oscilador XT. Debe utilizarse cuando el PIC Trabajará con un cristal o

resonador de frecuencias iguales o menores a 4Mhz. (Fosc <= 4Mhz).

c) HS: Oscilador HS (High Speed). Para cristales o resonadores con frecuencias

mayores a 10Mhz. (Fosc >10Mhz)

d) RC: Oscilador RC (Resistor/Capacitor). Se usa cuando el PIC va a operar con

un circuito RC.

Page 4: Microcontroladores Parte 1

3

Autor: Wilmer Planchez Febrero, 2013.

1.1.2.2.- CONFIGURACIÓN WATCHDOG.

¿Qué es el Watchdog?

El Watchdog (“Perro Guardian”) o WDT es un temporizador que una vez

alcanzado su tiempo límite puede provocar un reset en el PIC. El Watchdog cuenta cada

ciertos pulsos de reloj en un determinado tiempo, esperando algún evento generado por

el programa, si este evento no ocurre el Watchdog se activa y hace que todo empiece de

nuevo debido a que el programa a realizado una acción no prevista.

Para activar o desactivar el Watchdog se usan las siguientes sentencias:

NOWDT: No Watch Dog Timer. Deshabilitación del Watchdog.

WDT: Watch Dog Timer. Habilitación del Watchdog.

Las sentencias para indicar el tipo de oscilador y la configuración del Watchdog

se escriben en una sola línea, escribiendo la directiva #fuses.

#fuses: Permite modificar el Valor de los fusibles del microcontrolador que

estamos utilizando. Los valores posibles dependen de cada microcontrolador en

particular.

Sintaxis:

#fuses Opciones

Opciones es una lista de las opciones posibles separadas mediante comas. Algunos

valores comunes son:

Tipo de oscilador: LP, XT, HS, RC.

WatchDog Timer: WDT, NOWDT.

Protección de código: PROTECT, NOPROTECT.

Page 5: Microcontroladores Parte 1

4

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo #2:

#fuses XT,NOWDT

Indica que el tipo de oscilador utilizado es del tipo XT (Fosc <= 4Mhz) y el

Watchdog está deshabilitado.

1.1.3.- FRECUENCIA DE OSCILACIÓN.

Las instrucciones en el microcontrolador necesitan de un ciclo de máquina para

ejecutarse y este depende de la frecuencia de oscilación del cristal externo, o una fuente

de reloj interna. Se recomienda usar Cristales o resonadores para tener precisión, es muy

útil cuando se desea trabajar con más de un microcontrolador y se desea que estén

sincronizados.

1 Ciclo de Maquina = 4 Ciclos de reloj

Tcm = 4 / Fosc = 4 * Tosc

Donde:

Tcm : Ciclo de máquina.

Fosc: Frecuencia de oscilación del cristal, resonador, o circuito RC.

Tosc: Periodo de oscilación del cristal , resonador, o circuito RC.

Ejemplo #3:

Calcular el ciclo de máquina para una frecuencia de oscilación de 4Mhz.

Fosc = 4Mhz

Tosc = 1 / 4Mhz = 0,25us = 0,26 x 10-6 segundos

Tcm = 4 * 0,25us = 1us

Cada instrucción en el microcontrolador se ejecutará en 1us.

Para incluir la frecuencia de oscilación con la que se va a trabajar se usa la

directiva #use delay. Esta directiva indica al compilador la frecuencia del procesador, en

ciclos por segundo, a la vez que habilita el uso de las funciones delay_ms() y

Page 6: Microcontroladores Parte 1

5

Autor: Wilmer Planchez Febrero, 2013.

delay_us(), las cuales se usan para hacer retardos en milisegundos y microsegundos

respectivamente.

Sintaxis:

#use delay (clock= Frecuencia)

Ejemplo #3:

#use delay (clock=4000000)

En este caso se indica que la frecuencia de oscilación con la que se va a trabajar es de

4Mhz.

1.1.3.1.- FUNCIONES DE RETARDOS

DELAY_MS(time)

Esta función realiza retardos del valor especificado en time. Dicho valor de

tiempo es milisegundos y el rango es 0 – 65535.

Ejemplo #4a:

delay_ms(1000); //retardo de 1 segundo

DELAY_US(time)

Esta función realiza retardos del valor especificado en time. Dicho valor de

tiempo es microsegundos y el rango es 0 – 65535.

Ejemplo #4b:

delay_us(50); //retardo de 50 microsegundos

1.1.4.- RENOMBRAMIENTO DE PINES.

Para el renombramiento de pines se usa la directiva #define. La instrucción #define

tiene la siguiente forma:

#define <Label> value

<Label> es la etiqueta que usaremos en nuestro programa. Y value es el valor que

estamos asignando a la etiqueta.

Page 7: Microcontroladores Parte 1

6

Autor: Wilmer Planchez Febrero, 2013.

Sintaxis: (Cambiar el nombre de un pin)

#define Nombre pin_xn

Donde:

x: Letra que indica el puerto

n: Número de pin (0 a 7)

Ejemplo #5:

#define led1 pin_b0 // El pin B0 ahora se llama Led1

1.2.- PROGRAMAS O FUNCIONES.

Las funciones son un conjunto de instrucciones. Pueden existir muchas

funciones las cuales deben ser definidas antes de ser usadas, siempre existirá una

función principal llamada main(). La función principal Siempre debe existir, e indica el

punto en el que comenzara a funcionar el programa.

1.3.- INSTRUCCIONES

Las instrucciones o sentencias indican como se debe comportar el PIC, este

realizará solo aquello que se le indique.

1.4.- COMENTARIOS

Los comentarios facilitan la comprensión del programa, describiendo el

funcionamiento de cada línea de código. Los comentarios son ignorados cuando se

compila el código. Existen dos formas de hacer comentarios:

1.4.1.- COMENTARIOS DE UNA LINEA

Para escribir comentarios que ocupen una sola line se hace uso del doble Slash (//)

Ejemplo #6:

// Este comentario ocupa una sola línea

Page 8: Microcontroladores Parte 1

7

Autor: Wilmer Planchez Febrero, 2013.

1.4.2.- COMENTARIOS QUE OCUPAN MÁS DE UNA LINEA.

Los comentarios que ocupan más de una línea se escriben de la siguiente manera:

/* Linea de comentario 1

Linea de comentario N */

/*: Indica que se inicia el comentario

*/: Cierre del comentario

Ejemplo #7: Estructura de un programa en C.

#include <16f84A.h> //Microcontrolador a utilizar

#fuses xt,nowdt //Oscilación del cristal <= 4mhz

//Whatchdog desactivado

#use delay (clock=4000000) //Frecuencia del cristal de 4Mhz

void main(){ // Inicio Función Principal

Sentencias; // Instrucciones. Estructuras de control

} // Fin de la Función Principal

Seguramente se estará preguntando el significado de “void”, las llaves { }, y para que

sirve el punto y coma (;).

Void es una palabra reservada en lenguaje C. En nuestro caso tenemos lo siguiente:

void main() quiere decir que la función main() no devolverá parámetros o

valores. Más Adelante se explicaran en detalle aspectos importantes sobre las funciones.

USO DE LAS LLAVES {. . .}

C es un lenguaje estructurado o modular en el que un programa está formado por

“bloques”. Los elementos que componen un bloque deben estar relacionados entre sí.

Lo que indica que lo encerramos entre llaves.

{ // INICIO DEL BLOQUE

} // FINAL DEL BLOQUE

Page 9: Microcontroladores Parte 1

8

Autor: Wilmer Planchez Febrero, 2013.

USO DEL PUNTO Y COMA (;)

El punto y coma indica el final de una sentencia en C. En el Ejemplo #7

generalizamos las instrucciones escribiendo:

Sentencia 1;

Sentencia 2;

O también se pudo haber escrito:

Sentencia 1; Sentencia 2;

Ambas formas son validas, el final de una sentencia y el inicio de la otra son

indicados con el punto y coma (;).

2. DATOS. TIPOS DE DATOS

Un dato es toda información que almacena el ordenador.

2.1 TIPOS DE DATOS

En cualquier lenguaje de programación siempre existirán 4 tipos de datos

fundamentales, estos son:

i) Numéricos.

ii) Reales.

iii) Alfanuméricos.

a. Letras.

b. Números.

c. Caracteres especiales.

d. Una mezcla de todo lo anterior.

iv) Booleanos. Solo pueden tener 2 valores, verdadero o falso.

El compilador CCS C acepta los siguientes tipos de datos.

Page 10: Microcontroladores Parte 1

9

Autor: Wilmer Planchez Febrero, 2013.

3.- CONSTANTES

4.- VARIABLES.

Las variables son zonas de la memoria RAM que se utilizan para almacenar datos; se

deben declarar antes de ser utilizadas; para ello se debe indicar el nombre y el tipo de

dato que se manejará.

Sintaxis:

Tipo_Dato Nombre_variable;

Ejemplo #8:

int Numero;

Float Voltaje;

Page 11: Microcontroladores Parte 1

10

Autor: Wilmer Planchez Febrero, 2013.

Al declarar las variables se le pueden asignar valores iniciales, de no hacerlo, estas

tendrán un valor por defecto igual a cero (0).

int Valor = 25;

Float Presion = 4.5;

Podría darse el caso, en el cual se declaren variables del mismo tipo, el lenguaje C nos

brinda una forma elegante de hacerlo.

Int Numero_1, Numero_2 , Valor = 25;

Float Voltaje, Presion = 4.5;

4.1.- IDENTIFICADORES.

Los identificadores o nombres de variables pueden estar formados por letras números o

guion bajo ( _ ) y deben comenzar por letra o guion bajo. No deben tener espacios. El

guión bajo es el único carácter especial permitido para asignar el nombre de una

variable o función, no se permite la letra “ñ” ni las letras acentuadas. Lenguaje C

diferencia entre mayúsculas y minúsculas, esto quiere decir que una variable llamada

“Numero” será diferente de una llamada “numero”.

A continuación unos ejemplos de Nombres no válidos para las variables.

Ejemplos #9:

Int 2Caras; // Empieza por un numero (Error)

Float Primer Numero; // Contiene un espacio (Error)

Int16 Año; // La letra “ñ” (Error)

Long Más_Personas; // Tiene una vocal acentuada (Error)

Page 12: Microcontroladores Parte 1

11

Autor: Wilmer Planchez Febrero, 2013.

5.- OPERADORES

5.1- ASIGNACIÓN.

5.1- ARITMÉTICOS.

5.1.1- INCREMENTO Y DECREMENTO.

Sintaxis:

Forma 1: Notación normal.

A = A + 1;

A = A – 1;

Page 13: Microcontroladores Parte 1

12

Autor: Wilmer Planchez Febrero, 2013.

Forma 2: Notación compacta.

A++;

A--;

En resumen:

A++ es lo mismo que A = A + 1.

A-- es lo mismo que A = A - 1.

5.1.1.1- Postincremento.

B = A++;

Se asigna a B el valor de A y se incrementa el valor de A tras asignar su valor. Por lo

tanto si A = 1, entonces:

B=1; // Se asigna el valor de A (B = A = 1)

A=2; // Se incrementa el valor de A

5.1.1.2- Preincremento.

B = ++A;

Primero se incrementa el valor de A y después asigna su valor. Por lo tanto si A = 1,

entonces:

A = 2; // Se incrementa el valor de A

B = 2; // Se asigna el valor de A (B = A = 2)

El Predecremento y el Postdecremento funcionan de la misma manera.

Page 14: Microcontroladores Parte 1

13

Autor: Wilmer Planchez Febrero, 2013.

5.2 RELACIONALES.

5.3 LÓGICOS.

5.4 DE BITS.

Page 15: Microcontroladores Parte 1

14

Autor: Wilmer Planchez Febrero, 2013.

6.- FUNCIONES.

Las funciones tienen la siguiente forma:

Nombre_funcion() { // Cuerpo de la función

Instrucción 1;

Instrucción 2;

.

.

Instrucción n;

}

Las funciones terminan y regresan automáticamente al procedimiento que las llamó

cuando se encuentra la ultima llave}.Se deben declarar las funciones antes de utilizarlas

de igual manera como se hace con las variables.

6.1.- PROTOTIPOS DE FUNCIONES

Un prototipo es una declaración de una función. Consiste en una presentación de la

función con la misma estructura que la definición, pero sin cuerpo y termina con un “;”.

El prototipo le indicara al compilador el tipo de datos que la función regresara y el tipo

de parámetros que la función espera.

Sintaxis:

Tipo_Funcion nombre_funcion();

Donde “Tipo” es cualquiera de los tipos de variables soportados en CCS.

Ejemplo #10:

Long Ejemplo();

Page 16: Microcontroladores Parte 1

15

Autor: Wilmer Planchez Febrero, 2013.

6.2.- PARÁMETROS.

Además de determinar el tipo de resultado que devolverá la función, en el prototipo

podemos especificar que parámetros recibirá. Y de que tipo serán. La forma de hacerlo

es la siguiente:

Tipo_Funcion nombre funcion(Tipo variable1,Tipo variable2,…);

6.3.- DEFINICION DE UNA FUNCIÓN.

Luego de haber indicado el prototipo de la funcion, esta debe ser definida luego de la

función principal. Una función con parámetros podría ser la siguiente:

double Division(float x,float y){ // Cuerpo de la funcion

double Resultado;

x = 10;

y = 250;

resultado = x/y;

return resultado /* la función retorna el valor de

de la variable resultado*/

}

6.4.- VOID

Significa que la función no devolverá ningún parámetro. Supongamos que la función

Ejemplo_x() no debe regresar ningún valor luego de ser llamada. Su prototipo debería

ser como sigue:

void Funcion_1();

Además, podemos usar void para indicar que la función no recibe parámetros, ni

devuelve ningún valor.

void Funcion_2(void);

ó

void Funcion_2();

Page 17: Microcontroladores Parte 1

16

Autor: Wilmer Planchez Febrero, 2013.

6.5.- LLAMADA DE UNA FUNCIÓN.

Cuando un programa llama a una función, la ejecución del programa se trasfiere a dicha

función el programa retorna a la sentencia posterior a la llamada cuando se acaba la

función.

Sintaxis:

Nombre(Parámetros); /* Los parámetros son opcionales

Dependen de la función*/

Nombre es el identificador con el que es definida la función a la que queremos llamar.

Parámetros es la lista de valores que se asigna a cada parámetro de la función(en caso

de que tenga, estos se separan por comas).

Ejemplo #11:

Tiempo(); /*Llamada de la función Tiempo la cual no recibe

Parámetros*/

Page 18: Microcontroladores Parte 1

17

Autor: Wilmer Planchez Febrero, 2013.

7.- ESTRUCTURAS DE CONTROL.

Las estructuras de control se utilizan para tomar decisiones, realizar tareas repetitivas o

de bucle; son la base de cualquier lenguaje de programación, por lo tanto, su dominio es

fundamental. El inicio y el cierre de las estructuras de control se indica haciendo uso de

las llaves { }, de forma idéntica como se hace con las funciones. Las estructuras o

declaraciones de control que admite CCS son:

If - Else.

While.

Do-While

For.

Switch - Case.

Continue-Break-Goto.

7.1.- ESTRUCTURAS ALTERNATIVAS.

7.1.1.- IF: (“Si. . . entonces. . .”).

Con esta estructura se pueden tomar decisiones.

Sintaxis:

If(Condición){ // Inicio de la estructura IF

Sentencias;

} // Fin del IF

Ejemplo #12:

If(B1 == 0){ // Si B1 es igual a 0 entonces . . .

B2 = 10;

B3 = 5;

}

Haciendo uso de los operadores lógicos podemos escribir cosas como:

If((B1 == 0)&&(C==1)){ //Operación AND: Se deben cumplir

Sentencias; //Las 2 condiciones*/

}

Page 19: Microcontroladores Parte 1

18

Autor: Wilmer Planchez Febrero, 2013.

O también:

If((B1 == 0)||(C==1)){ // Operación Or: Se debe cumplir

Sentencias; // Alguna de las 2 condiciones

}

7.1.2.- ELSE : (“En Caso contrario . . .”)

Esta estructura se usa siempre con un if la cual indica que si la condición del if no es

verdadera entonces se ejecutan las sentencias del bloque else.

Sintaxis:

If(Condición){ // Inicio de la la estructura IF

Sentencias;

}// Fin del IF

Else{ // Inicio de la la estructura Else

Mas_Sentencias;

}// Fin del else

Ejemplo #13:

If(A == 1){ // Si A es igual a 1 entonces . . .

B = 2;

C = 7;

}

Else{ En caso contrario: A no es igual a 1 entonces . . .

B = 0;

C = 0;

}

Page 20: Microcontroladores Parte 1

19

Autor: Wilmer Planchez Febrero, 2013.

7.1.2.- ELSE IF.

Se pueden enlazar los if usando else para decir, si no se cumple esta condición, ve si se

puede ejecutar esta otra.

Sintaxis:

If(Condición){ // Inicio de la la estructura IF

Sentencias;

}// Fin del IF

Else if(Condición){ // Inicio del Else If

Sentencias;

} // Fin Else If

Else{ // Ninguna de las condiciones se cumple.

Sentencias;

} // Fin del else

Page 21: Microcontroladores Parte 1

20

Autor: Wilmer Planchez Febrero, 2013.

7.1.1.- SWITCH – CASE.

Si queremos preguntar por varias condiciones, sería muy pesado tener que hacerlo con

muchos if seguidos.

Sintaxis:

switch(Variable){

Case valor1:

Sentencias;

break;

Case valor2:

Sentencias;

break;

Case valor3:

Sentencias;

break;

default:

Sentencias;

}

Donde Variable es la variable por la cual vamos a preguntar, valor1, valor2 y valor3

son los posibles valores de las variables. La palabra reservada break indica que cuando

el compilador ejecute esa línea, se saldrá automáticamente de la estructura switch, de no

escribir esa sentencia, el programa seguirá preguntando por el resto de las condiciones y

ejecutando las instrucciones hasta que finalice la estructura, se cumpla una condición , o

se encuentre con la instrucción break.

La sentencia default es opcional (no es necesario colocarla) y es la opción que se

ejecutará si ninguno de los valores coincide, por lo tanto default, es la opción que se

ejecutara por defecto.

Page 22: Microcontroladores Parte 1

21

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo #14:

switch(X){

Case 5:

Y = 1;

break;

Case 10:

Y = 2;

break;

Case 15:

Y = 3;

break;

default:

break;

}

7.2.- ESTRUCTURAS REPETITIVAS.

7.2.1.- FOR.

For se usa para repetir sentencias un número determinado de veces.

Sintaxis:

For(inicialización ; condición de finalización ; inc. ó dec.){

Sentencias;

}

Inicialización es una variable que definirá el punto desde el cual comenzará a

incrementarse la estructura. La condición de finalización, indica hasta donde se

ejecutará el bucle. Por último, la expresión de incremento o decremento modifica la

variable de control después de ejecutar el bucle.

Si se ejecuta la siguiente expresión se consigue un bucle sin fin.

Page 23: Microcontroladores Parte 1

22

Autor: Wilmer Planchez Febrero, 2013.

For( ; ; ){

Sentencias;

}

Ejemplo #15:

For(i=0;i<=15;i++){

Printf(“%u”,i); /* Imprime en pantalla los números del 0 al 15.*/

}

7.2.2.- WHILE / DO-WHILE.

WHILE se utiliza para repetir sentencias, hasta que una determinada condición se

cumple.

Sintaxis:

while(condición){

Sentencias;

}

La condición se evalúa y la sentencia se ejecuta mientras la expresión sea verdadera,

cuando es falsa se sale del While. Si la expresión es verdadera desde un principio, el

bucle While no ejecuta las sentencias ni una sola vez.

DO-WHILE se diferencia del WHILE y del FOR en la condición de finalización, la

cual se evalúa al final del bucle, por lo que las sentencias se ejecutan al menos una vez.

Sintaxis:

}do

Sentencias;

}while(condición);

Si se ejecuta la siguiente expresión se consigue un bucle sin fin.

while(1){

Page 24: Microcontroladores Parte 1

23

Autor: Wilmer Planchez Febrero, 2013.

Sentencias;

}

ó

}do

Sentencias;

}while(1);

Ejemplo #16:

while(i<=9){

j=4;

K=0;

}

Ejemplo #17:

}do

j=4;

K=0;

}while(i<=9);

Un bucle WHILE puede comportarse como un bucle FOR, la forma de lograrlo es la

siguiente.

i=0;

while(i<=9){

sentencias;

i++;

}

Page 25: Microcontroladores Parte 1

24

Autor: Wilmer Planchez Febrero, 2013.

Lo anterior es equivalente a escribir:

for(i=0;i<=9;i++){

sentencias;

}

7.3.- OTROS.

7.3.1.- BREAK.

Podemos salir de un bucle antes de tiempo con la orden BREAK.

Ejemplo #18:

For(i=0;i<=10;i++){

If(i == 4){

break; // Sale del bucle

}

}

7.3.1.- CONTINUE.

Podemos saltar alguna repetición de un bucle con la orden CONTINUE.

For(i=0;i<=10;i++){

If(i == 4){

Continue; /* El bucle se salta el numero 4

Y continua la ejecución del bucle*/

}

}

7.3.1.- GOTO: (“Ir a...”)

GOTO permite hacer saltos incondicionales, asignando una etiqueta en algún lugar del

código, y cuando se desee regresar al lugar de la etiqueta se hace uso del GOTO la

siguiente manera:

Inicio: // Etiqueta

Goto inicio;

Page 26: Microcontroladores Parte 1

25

Autor: Wilmer Planchez Febrero, 2013.

Se debe evitar el uso del GOTO en lo posible, ya que genera malos hábitos de

programación, se recomienda su uso, cuando se tengan un anidamiento de estructuras

repetitivas, de donde es difícil salir con una sola instrucción como BREAK. El siguiente

ejemplo muestra un caso en el que es muy útil usar GOTO.

Ejemplo#19:

for(i=1;i<=100;i++){ // Inicio del For1

for(j=0;j<=50;j++){ // Inicio del For2

for(K=0;K<=9;K++){ // Inicio del For3

if(Z==1){ // Inicio del If

goto Seguir;

} // Fin del If

} // Fin del For3

} // Fin del For2

} // Fin del For1

Seguir:

Sentencias;

En las estructuras anidadas, el bucle mas interno es el que primero termina, en este caso

el bucle mas interno es el For3, para poder salir de la estructura se debe salir primero del

bucle For3, luego del For2 y finalmente del For1 que es el principal, obviamente con

escribir la sentencia break en el bucle for3 solo se conseguiría salir de este, y quedar

atrapado en los otros 2 bucles, y es aquí donde la sentencia GOTO se torna realmente

útil ya que nos redirige a la zona deseada de nuestro código de un solo salto.

NOTA: Jamás se debe usar un GOTO dentro de una función hacia un punto fuera de

esta, ya que toda función debe retornar, para continuar su ejecución desde el lugar de

donde se llamó.

Page 27: Microcontroladores Parte 1

26

Autor: Wilmer Planchez Febrero, 2013.

8.- DIRECTIVAS DE MANIPULACION DE PUERTOS.

El compilador CCS posee funciones predefinidas para trabajar con puertos, y pines

específicos del microcontrolador.

Funciones Para el manejo de puertos:

output_X(valor): Saca por el puerto un valor de 8 bits (0 – 255).

input_X( ): Función para la lectura del puerto correspondiente.

set_tris_X(valor): Carga el registro TRISx con un valor de 8 bits, en esta

función se indican las entradas y las salidas del puerto. Indicando las entradas con 1 y

las salidas del puerto con 0.

Donde la X es la inicial del puerto correspondiente (A, B, C , D, E).

Funciones Para el manejo de pines.

output_low(pin*): Coloca el estado lógico del pin a 0.

output_high(pin*): Coloca el estado lógico del pin a 1.

output_bit(pin*,Valor): Pin al valor especifico. (Valor puede ser 0 o 1).

output_toggle(pin*): Complementa el valor del pin.

input(pin*) : Lee el valor del pin.

Las funciones input_x() y output_x() dependen de la directiva #USE *_IO que este

activa. Las directivas mas utilizadas son:

#USE FAST_IO(PUERTO)

Con la función output_x() se saca un valor de 8 bit por el puerto indicado y con la

función input_x() se lee el valor del puerto. La directiva no modifica el registro TRIS

correspondiente.

#USE STANDARD_IO(PUERTO)

Con la función output_x() el compilador se asegura de que el terminal, o terminales

correspondientes, sean de salida mediante la modificación del registro TRIS

Page 28: Microcontroladores Parte 1

27

Autor: Wilmer Planchez Febrero, 2013.

correspondiente. Con la función input_x() ocurre lo mismo pero asegurando el terminal

como entrada.

9.- DISEÑO DE CIRCUITOS CON ISIS DE PROTEUS.

Proteus es un poderoso software de simulación y diseño electrónico, de la compañía

Labcenter Electronics. El ISIS permite la simulación de las familias de

microcontroladores mas conocidas como la: 12F (Gama baja), 16F (Gama media), 18F

(Gama alta). Proteus puede simular una gran cantidad de dispositivos digitales y

analógicos. En la siguiente imagen se puede apreciar la apariencia del entorno de trabajo

de ISIS:

Figura 9-1

Page 29: Microcontroladores Parte 1

28

Autor: Wilmer Planchez Febrero, 2013.

9.1.- CARACTERISTICAS BÁSICAS PARA SIMULAR.

Se debe identificar la paleta de dispositivos, que está a la izquierda de la pantalla, en

esta paleta el diseñador debe identificar el botón P como se muestra en la imagen.

Figura 9-2

Al presionar el botón P, el programa abre una nueva ventana que permite la búsqueda

de dispositivos por medio de la referencia comercial, o bajo la clasificación que el

mismo ISIS tiene.

Figura 9-2

Page 30: Microcontroladores Parte 1

29

Autor: Wilmer Planchez Febrero, 2013.

El programa genera una lista en la parte derecha de la ventana con los dispositivos

relacionados con la solicitud del usuario. Para seleccionar un dispositivo de esta lista se

da doble clic sobre cada uno de los numerales de la lista. Para comenzar busque los

siguientes dispositivos: PIC16F877A, RES(220ohm), CAP(22pf), CRYSTAL, LED-

GREEN. El cristal no es necesario en la simulación, pero es recomendable su uso en el

montaje en físico.

Figura 9-3

El paso siguiente es buscar los terminales de GROUND (tierra) y POWER (Vcc). La

terminal de Vcc tiene una diferencia de potencial por defecto de 5v. Para colocar estas

terminales en le área de trabajo se presionan los ítems en la paleta de terminales y

posteriormente en el área de trabajo, después de esta acción en el área de trabajo se

debe ver lo siguiente:

Figura 9-4

Page 31: Microcontroladores Parte 1

30

Autor: Wilmer Planchez Febrero, 2013.

El siguiente paso es unir los componentes en el área de trabajo, para esto se debe

presionar el botón COMPONENT MODE (El símbolo es un amplificador operacional

amarillo) de la paleta de herramientas a la izquierda. Para unir los dispositivos en el

área de trabajo se sigue el mismo procedimiento de las terminales, al finalizar se debe

tener la siguiente vista:

Figura 9-5. El circuito más simple con un Microcontrolador.

10.- CREACION DE UN PROYECTO CON CCS.

1) Crear una carpeta donde se guardara el programa y el esquema electrónico diseñado en Proteus.

2) Abrir el compilador CCS.

Figura 10-1. Entorno de Trabajo de CCS.

Page 32: Microcontroladores Parte 1

31

Autor: Wilmer Planchez Febrero, 2013.

3) En la barra de herramientas dar clic a la pestaña Proyect.

Figura 10-2

4) Click en New/Source File.

Figura 10-3. Creación de un nuevo proyecto.

Page 33: Microcontroladores Parte 1

32

Autor: Wilmer Planchez Febrero, 2013.

5) En la carpeta creada escribir el nombre del Programa. Se recomienda que el

programa tenga el mismo nombre de la carpeta.

Figura 10-4

6) Finalmente Guardar.

Figura 10-5. Proyecto creado listo para Programar.

Con nuestro proyecto creado procedemos a escribir nuestro primer Programa, el “Hola

Mundo” de los microcontroladores.

Page 34: Microcontroladores Parte 1

33

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo#20: Programa que encienda y apague un led durante un tiempo indefinido. El

Parpadeo debe durar 1 segundo. (500ms encendido y 500ms apagado).

// Program_00_Apagar_Encender_Led

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

#define led1 pin_b1 // El pin B1 ahora se llamará led1

void main(){ // Funcion Principal

set_tris_b(0b00000000); // Config. del puerto B como Salida

output_b(0b00000000); // Apaga todos los Pines del puerto B

while(1){ // Bucle infinito

output_bit(led1,1); // Enciende el Led

delay_ms(500); // Espera 500ms

output_bit(led1,0); // Apaga el Led

delay_ms(500); // Espera 500ms

} // Fin del While

} // Fin de la función principal

7) Para compilar el programa en la barra de herramientas seleccione La pestaña

Compile y luego la opción Compile.

Figura 10-6. Compilación.

Page 35: Microcontroladores Parte 1

34

Autor: Wilmer Planchez Febrero, 2013.

Si la compilación fue exitosa deberá aparecer una imagen como la siguiente.

Figura 10-7. Compilación Exitosa.

En la compilación se generan archivos con diferentes extensiones, utilizaremos los

archivos de extensión *.HEX y *.COF, los cuales se pueden utilizar para trabajar con el

entorno PROTEUS.

8) Dar doble clic en el microcontrolador para abrir la ventana de edición.

Figura 10-8

Page 36: Microcontroladores Parte 1

35

Autor: Wilmer Planchez Febrero, 2013.

7) En el item Processor Clock Frequency se debe colocar la frecuencia de reloj

especificada en la programación, para nuestro caso será de 4Mhz.(Figura 10-8).

8) Incluir el archivo de trabajo en el ítem Program File dando clic al símbolo de

la carpeta. (Figura 10-8).

´

Figura 10-9

9) Seleccionar el archivo de extensión *.HEX o *.COF.

10) Ahora se puede proceder a la simulación del circuito empleando la barra de

simulación. Esta opción se compone de la opción MARCHA, PASO A PASO,

PAUSA y PARADA.

Figura 10-10

Page 37: Microcontroladores Parte 1

36

Autor: Wilmer Planchez Febrero, 2013.

11.- PROYECTOS CON LEDS

Ejemplo#21: Se desea programar un semáforo, de 2 intersecciones que cumpla la

siguiente función: La luz roja del semáforo 1 y la luz verde deben activarse por 9

segundos, luego se debe activar la luz amarilla del semáforo 2 por 3 segundos mientras

la luz roja del otro semáforo sigue activa, debe completarse el ciclo para ambos

semáforos.

Componentes ISIS: PIC16F877A, RX8 (Pack de 8 resistencias), LED-GREEN, LED-

RED, LED-YELLOW, CRISTAL, CAP (22pf).

Figura 11-1. Semáforo De 2 Intersecciones con leds.

// Program_01_Semaforo

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

void main(){ // Funcion Principal

set_tris_b(0b00000000); // Config. del puerto B como Salida

Page 38: Microcontroladores Parte 1

37

Autor: Wilmer Planchez Febrero, 2013.

output_b(0b00000000); // Apaga todos los Pines del puerto B

while(1){ // Bucle infinito

output_b(0b00100001); // Rojo_1 = ON / Verde_2 = ON

delay_ms(9000);

output_b(0b00010001); // Rojo_1 = ON / Amarillo_2 = ON

delay_ms(3000);

output_b(0b00001100); // Verde_1 = ON / Rojo_2 = ON

delay_ms(9000);

output_b(0b00001010); // Amarillo_1 = ON / Rojo_2 = ON

delay_ms(3000);

} // Fin del While

} // Fin de la funcion Principal

Ejemplo#22: Diseñar un contador binario de 8 bits que cuente de 0 a 255, al llegar a 255 la cuenta debe reiniciarse. Entre un cambio y otro debe haber un retarde de 300 milisegundos.

Componentes ISIS: PIC16F877A, RX8 (Pack de 8 resistencias), LED-BARGRAPH-

GREEN (Barra de 10 Leds verdes), CRISTAL, CAP (22pf).

Figura 11-2

Page 39: Microcontroladores Parte 1

38

Autor: Wilmer Planchez Febrero, 2013.

// Program_02_Contador_8_Bits

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

void main(){ // Funcion Principal

set_tris_b(0b00000000); // Config. del puerto B como Salida

output_b(0b00000000); // Apaga todos los Pines del puerto B

while(1){ // Bucle infinito

for(i=0;i<=255;i++){ // Bucle for de 0 a 255

output_b(i); // saca Por el Pto.B el valor de i

delay_ms(300); // Retardo de 300milisegundos

} // Fin del Bucle For

} // Fin del While

} // Fin de la funcion Principal

Page 40: Microcontroladores Parte 1

39

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo#23: Diseñar un programa que sea capaz de desplazar un bit desde el LSB de un puerto al MSB (de derecha a izquierda) al llegar al MSB este debe realizar un desplazamiento en sentido contrario (De izquierda a derecha), el proceso debe repetirse infinitamente. Mostrar las salidas con leds. Se utilizará el esquema electrónico del Ejercicio #22 (Ver Figura 11-2).

// Program_03_Desplazamiento

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

int i,j=1;

void main(){ // Funcion Principal

set_tris_b(0b00000000);

output_b(0b00000000);

delay_ms(500);

while(1){

for(i=1;i<=7;i++){ // Desplazamiento a la Izquierda

output_b(j); // Saca por el pto B el valor de j

j <<= 1; // <<= indica desplazamiento a la izq.

delay_ms(500);

} // Fin del For de despl. A la izquierda

for(i=1;i<=7;i++){ //Desplazamiento a la Derecha

output_b(j);

j >>= 1; // >>= indica desplazamiento a la Derecha

delay_ms(500);

} // Fin del For de despl. A la derecha

} // Fin del While

} // Fin del main

Al ejecutarse el programa es necesario que el bit menos significativo del puerto este activado. Se han declarado 2 variables:

Page 41: Microcontroladores Parte 1

40

Autor: Wilmer Planchez Febrero, 2013.

int i,j=1;

i: se utiliza para indicar la cantidad de veces que se va a desplazar el valor de j (j=1) desde el LSB hasta el MSB, en este caso se desplazara 7 veces (como se indica en el bucle For) hasta llegar a su objetivo, para luego regresar a su punto de origen.

j: es la variable que ira tomando los valores que vamos a sacar por el puerto B.

for(i=1;i<=7;i++){ // Desplazamiento a la Izquierda

output_b(j); // Saca por el pto B el valor de j

j <<= 1; // <<= indica desplazamiento a la izq.

delay_ms(500);

}

En el bucle For indicamos la cantidad de veces que se desplazará el valor de j, que por defecto es 1 (00000001 binario) es decir tendremos 7 posibles valores de j al comenzar el desplazamiento.

00000010 (binario) = 2 (decimal)

00000100 (binario) = 4 (decimal)

00001000 (binario) = 8 (decimal)

00010000 (binario) = 16(decimal)

00100000 (binario) = 32 (decimal)

01000000 (binario) = 64(decimal)

10000000 (binario) = 128 (decimal)

Podemos darnos cuenta que el desplazamiento a la izquierda no es más que una multiplicación por 2, es decir en realidad lo que se ejecuta es lo siguiente:

j = j*2;

Quiere decir que el valor que se tenga en j justo en ese instante, se va a multiplicar por 2, esto se traduce en el desplazamiento de un bit a la izquierda (cuando se saca el valor por el puerto), y se asigna ese nuevo valor a la variable.

El desplazamiento a la derecha es una división entre 2.

j = j/2;

Como ejercicio reemplace j <<= 1 por j = j*2 y j >>= 1 por j = j/2, y observe lo que sucede.

Page 42: Microcontroladores Parte 1

41

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo#24: usando las 8 salidas de un puerto generar una secuencia, similar a las luces de una discoteca, al inicio deben estar en estado alto el bit 0 y el bit 7 del puerto, se desea que estos bits se desplacen hacia su extremo opuesto correspondiente, generando un efecto de cruce cuando pasan por el centro, el proceso debe repetirse indefinidamente. Mostrar las salidas con leds. Se utilizará el esquema electrónico del Ejercicio #22 (Ver Figura 11-2).

// Program_04_Luces_Para_Discoteca

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

Int Tiempo = 100; // Argumento de la función delay_ms(Valor)

void main(){ // Inicio de la funcion principal

set_tris_b(0b00000000); // Config. Del pto.B como salida

output_b(0b00000000); // Saca un cero por los pines del pto.B

while(1){ // Bucle infinito

output_b(0b10000001);

delay_ms(Tiempo);

output_b(0b01000010);

delay_ms(Tiempo);

output_b(0b00100100);

delay_ms(Tiempo);

output_b(0b00011000);

delay_ms(Tiempo);

output_b(0b00100100);

delay_ms(Tiempo);

output_b(0b01000010);

delay_ms(Tiempo);

} // Fin del bucle infinito

} // Fin de la función principal

Page 43: Microcontroladores Parte 1

42

Autor: Wilmer Planchez Febrero, 2013.

Este programa muestra otra de las posibilidades que nos ofrece la función delay_ms(valor), donde valor podría ser una constante(como se había trabajado en los programas anteriores), o puede ser una variable, la cual podría cambiar su valor en cualquier momento, permitiendo generar temporizaciones de diferente duración.

La razón por la cual se usa como argumento una variable es sencilla, simplemente para poder variar la temporización de la secuencia, sin modificar muchas líneas de código. Para este ejemplo el cambio entre una secuencia y otra es de 100ms, pero supongamos que deseamos una temporización de 50ms, en lugar de escribir delay_ms(50); 6 veces basta con modificar el valor de int Tiempo = 50; que es la variable para controlar la temporización, permitiéndonos ganar tiempo valioso, sin hacer que programar secuencias con la misma duración sea tedioso.

12.- PROYECTOS CON PULSADORES

Los pulsadores permiten al microcontrolador comunicarse con el mundo exterior, estos mandan valores digitales al PIC permitiendo tomar decisiones en base a ellos. Existen 2 tipos de conexiones para los pulsadores Pull-Up y Pull- Down.

Pull-Up: Siempre está en 1 lógico (5V), y cuando se presiona el pulsador este cambia su estado mandando un cero lógico (0V).

Pull-Down: Siempre está en 0 lógico (0V), y cuando se presiona el pulsador este cambia su estado mandando un 1 lógico (V).

Figura 12-1

Page 44: Microcontroladores Parte 1

43

Autor: Wilmer Planchez Febrero, 2013.

Ejemplo#25: Se desea encender un led durante 1 segundo al presionar un pulsador, al pasar este tiempo el led debe apagarse, hasta que se vuelva a presionar el pulsador.

Componentes ISIS: PIC16F877A, BUTTON (Pulsador), RES(220ohm), LED-

GREEN , CRISTAL, CAP (22pf).

Figura 12-2

// Program_05_Pulsador_Led

#include <16f877A.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

#define Led pin_b1 // El Pin B1 se llamara Led

#define Pulsador pin_b0 // El Pin B0 se llamara Pulsador

void main(){ // Funcion principal

set_tris_b(0b00000001); // Config del pin B0 como entrada

// y el resto de lo pines como salida

output_b(0b00000000);

while(1){ // Bucle infinito

if (input(Pulsador)==0){ // Si se presiona el pulsador

output_bit(Led,1); // Ecender Led

Page 45: Microcontroladores Parte 1

44

Autor: Wilmer Planchez Febrero, 2013.

delay_ms(1000); // retardo de un segundo

output_bit(Led,0); // Apagar Led

} // Fin del If

} // Fin del bucle infinito

} // Fin de la funcion principal

En el esquema electrónico se hace uso de un pulsador del tipo Pull - up por lo tanto al ser presionado su estado lógico cambia de uno a cero, razón por la cual se pregunta por cero en el if y no por uno.

if (input(Pulsador)==0){ // Si el pulsador es Pull-up

if (input(Pulsador)==1){ // Si el pulsador es Pull-Down

Ejemplo#26: Diseñar un programa que permita controlar 3 salidas con un pulsador se debe alternar el funcionamiento de las 3 salidas activando 1 a la vez de forma secuencial es decir, activar la salida 1 luego la 2 y finalmente la 3, el ciclo debe repetirse.

Componentes ISIS: PIC16F877A, BUTTON (Pulsador), RES(220ohm), LED--GREEN , CRISTAL, CAP (22pf).

Figura 12-3

Page 46: Microcontroladores Parte 1

45

Autor: Wilmer Planchez Febrero, 2013.

// Program_06_1Pulsador_3Salidas

#include <16f877a.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(b)

#define Pulsador pin_b0

int Flag=1;

void main(){

set_tris_b(0b00000001); output_b(0b00000000);

while(1){

if (input(Pulsador)==0){

delay_ms(250); // Retardo anti-rebote

switch(Flag){

case 1:

output_b(0b00000010); // Activo el pin B1

Flag++; // Incremento la badera

break;

case 2:

output_b(0b00000100); // Activo el pin B2

Flag++; // Incremento la badera

break;

case 3:

output_b(0b00001000); // Activo el pin B3

Flag = 1 ;

break;

} // Fin del Switch

} //Fin del If

} // Fin del While

} // Fin de la funcion Principal

Page 47: Microcontroladores Parte 1

46

Autor: Wilmer Planchez Febrero, 2013.

En este programa se hace uso de la estructura Switch la cual nos permite preguntar por los posibles valores que podría tener una variable, y en función de estos, generar acciones, en este caso hemos asociado al pulsador una variable de nombre Flag (Bandera), que será la variable por la cual vamos a preguntar cada vez que se pulse el botón.

Para las siguientes sentencias:

case 1:

output_b(0b00000010); // Activo el pin B1

Flag++; // Incremento la badera

break;

En este caso estamos preguntando si la variable es igual a uno (Flag = 1, notese que inicialmente cuando se declaro la variable Flag, se le asigno el valor de 1), de cumplirse esta condición entonces se activa la primera salida ubicada en el pin B1, luego se incrementa la variable en uno (Flag = 2), de forma tal, que cuando se presione el pulsador nuevamente, el programa sepa cuál es el siguiente caso , y que salida debe activar. Con la sentencia break salimos inmediatamente de la estructura switch, de no colocarse, el programa seguiría preguntando por cada una de las condiciones hasta llegar al final de la estructura, haciendo más lenta la ejecución del programa.

case 3:

output_b(0b00001000); // Activo el pin B3

Flag = 1;

break;

Cuando se ha activado la salida 3 en el pin B3 se necesita que cuando se presione el pulsador se active la salida 1, para lograr esto colocamos nuevamente la variable a su valor inicial (Flag = 1).

Ejemplo#27: Diseñar un Programa que permita controlar 8 salidas con 3 pines del microcontrolador, utilice un decodificador 74LS138, las salidas deben activarse una a una cada vez que se pulse un botón.

Componentes ISIS: PIC16F877A, RX8 (Pack de 8 resistencias), LED-BARGRAPH-

GREEN (Barra de 10 Leds verdes), 74LS138, CRISTAL, CAP (22pf).

Page 48: Microcontroladores Parte 1

47

Autor: Wilmer Planchez Febrero, 2013.

Figura 12-4

// Program_07_PIC_y_Decodificador

#include <16f877a.h>

#fuses xt,nowdt

#use delay (clock=4000000)

#use fast_io(a)

#use fast_io(b)

#use fast_io(c)

//Redefinicion de Puertos

#define Pulsador pin_a0

//Definicion de variables

int valor;

void main(){

set_tris_b(0b00000000); // Conf. Del puerto B como salida

set_tris_a(0b00000001); // Conf Del pin A0 como entrada

set_tris_c(0b00000000); // Conf. Del puerto C como salida

output_b(0b00000000);

output_c(0b00000000);

Page 49: Microcontroladores Parte 1

48

Autor: Wilmer Planchez Febrero, 2013.

while(1){

if (input(Pulsador)== 0){ // Si se presiono el pulsador

output_c(0b00000001) // Actica el enable del 74LS138

delay_ms(250); // retarde de 250ms

if(valor>7){ // si valor es mayor que 7

valor=0; //Coloca a cero la variable

}

output_b(valor); // saca por el puerto B el contenido Valor

valor++; // Incrementa la variable

} // Fin del If

} // Fin del bucle infinito

} // Fin de la funcion principal

El decodificador 74LS138 es un demultiplexor que con 3 pines nos permite controlar 8 salidas, este es capaz de activar una de las 8 salidas dependiendo de la combinación binaria en sus entradas, si desea conocer mejor el funcionamiento de este circuito integrado consulte su hoja de datos (Datasheet).

Inicialmente el decodificador esta desactivado, el Enable en el pin c0 está en estado bajo, cuando se presiona el pulsador este es habilitado y se activa la salida correspondiente.

La condición:

if(valor>7){

valor=0;

}

Indica que si la variable es mayor que 7 entonces, esta volverá a su valor inicial. De 0 a 7 se tendrán 8 posibles valores (Ya que controlaremos 8 salidas), esa es la razón por la cual se pregunta por 7 y no por otro número.

output_b(valor);

valor++;

Se ejecuta siempre y cuando se presione el pulsador, en este caso saca el valor de la variable por el puerto y luego incrementa su valor.

Page 50: Microcontroladores Parte 1

49

Autor: Wilmer Planchez Febrero, 2013.

PROYECTOS PROPUESTOS CON LEDS.

1. Encienda un led conectado en el pin RB0 durante 1 segundo, luego apáguelo por 500ms. El proceso debe repetirse 4 veces, luego el led debe permanecer apagado.

2. Encienda 2 leds conectados en RB0 y RB1 alternamente, es decir mientras un led esta encendido el otro permanece apagado. Los tiempos de transición son de 500ms, entre encendido y apagado. El proceso debe continuar indefinidamente.

3. Genere 5 parpadeos de un led con intervalos de 400ms, luego haga 2 parpadeos de 1 segundo con un segundo led, luego haga que los 2 leds parpadeen 3 veces, repita el proceso indefinidamente.

PROYECTOS PROPUESTOS CON PULSADORES.

4. Haga un proyecto en el que al presionar un botón este encienda un led intermitente de 8 repeticiones de 100ms.Luego el led permanezca apagado, y el programa vuelve a sensar el pulsador.

5. Con un pulsador haga que 8 leds conectados en el puerto B, se enciendan, de derecha a izquierda uno a la vez, empezando de RB0 a RB7, al final este ultimo permanece encendido, con otro pulsador haga que los leds se desplacen uno a uno hacia la derecha, es decir, de RB7 que fue el ultimo y que está actualmente encendido se desplace hasta RB0 las pausas son de 200ms.