- Diagrama de circuito:
- Microcontrolador PIC PIC16F877A Código de secuencia intermitente de LED y explicación de funcionamiento:
En nuestro tutorial anterior, aprendimos sobre el parpadeo de un LED usando el microcontrolador PIC y construimos el mismo circuito en la placa Perf. Luego usamos PICkit 3, ICSP y MPLAB IPE para descargar el programa en nuestra placa Perf. Ahora, en este tutorial avanzaremos para usar más pines en el microcontrolador PIC. Usaremos 7 salidas (LED) y una entrada. Para este tutorial usaremos la antigua placa Perf (que se muestra a continuación) y agregaremos palos de té para sacar los pines necesarios en la segunda placa LED. Al final de este tutorial, generaremos una secuencia de LED parpadeantes usando el microcontrolador PIC PIC16F877A y aprenderemos a usar múltiples entradas y salidas, algunos conceptos básicos sobre el bucle 'for' y la llamada de funciones.
La placa de LED no es más que otra placa de perforación, en la que soldaremos los LED con una resistencia limitadora de corriente (que se muestra a continuación). También agregaremos un pulsador para iniciar la secuencia de parpadeo del LED.
Diagrama de circuito:
Microcontrolador PIC PIC16F877A Código de secuencia intermitente de LED y explicación de funcionamiento:
A continuación se proporciona el código completo (marque al final), aquí lo obtendremos línea por línea. Este código comenzará a iluminar los LED de manera secuencial cuando se presione el botón. Para comprender las secuencias, mire el video al final del tutorial. Le recomendaría que compare la salida que se muestra en el video con el código a continuación e intente comprender el programa.
Veamos el código línea por línea. Las primeras líneas son para configurar los bits de configuración que se explicaron en el tutorial anterior, así que los estoy omitiendo por ahora. La mejor manera de entender cualquier programa es comenzar desde la función main ( void main () ), así que hagámoslo
TRISB0 = 1; // Indique al MCU que el pin 0 de PORTB se usa como entrada para el botón. TRISD = 0x00; // Indique a la MCU que todos los pines salen PORTD = 0x00; // Inicializa todos los pines a 0
La palabra TRIS se usa para definir si el pin se usa como entrada / salida y la palabra PORT se usa para hacer un pin High / Low. La línea TRISB0 = 1 hará que el pin 0 del PUERTO B sea la entrada. Este será nuestro pulsador. Las líneas TRISD = 0x00; PORTD = 0x00; convertirá todos los pines del puerto D como Salida y asignará un valor inicial de BAJO a esos pines.
Como dijimos que B0 se usa como entrada, conectaremos un extremo del pulsador al pin B0 y el otro extremo a tierra. Para entonces, cada vez que presionemos el botón, el pin se mantendrá a tierra como se muestra en el diagrama de conexión anterior. Pero para que esto suceda, tenemos que usar una resistencia pull up para que el pin se mantenga alto cuando no se presione el botón. Una resistencia pull up es algo como esto.
Pero nuestro PIC MCU tiene una resistencia de extracción débil interna que se puede activar mediante software de esa manera, lo que ahorra muchas molestias (cuando se deben conectar más botones).
¿Qué es una resistencia pull-up débil?
Hay dos tipos de resistencia pull up, uno es Weak Pull Up y otro es Strong Pull Up. Las resistencias pull up débiles son de alto valor y, por lo tanto, permiten que fluya una corriente débil y las resistencias pull up fuertes son de bajo valor, lo que permite que fluya una corriente fuerte. Todos los MCU utilizan principalmente resistencias pull-up débiles. Para activar esto en nuestro PIC MCU, tenemos que buscar en nuestra hoja de datos OPTION_REG (registro de opciones) como se muestra en la instantánea a continuación.
Como se muestra, el bit 7 se ocupa de la resistencia de extracción débil. Debe ponerse a cero para activarlo. Esto se hace con OPTION_REG <7> = 0 . Esto trata específicamente con el bit 7 dejando los otros bits a sus valores predeterminados. Con esto entramos en nuestro bucle while, donde verifica si se presiona el botón usando if (RB0 == 0). Si se cumple la condición, llamamos a nuestra función con los parámetros 1, 3, 7 y 15.
parpadeo (1); // LLAMADA A FUNCIÓN 1 con parámetro 1 sblink (3); // FUNCTION CALL 3 con parámetro 3 sblink (7); // FUNCTION CALL 7 con parámetro 7 sblink (15); // FUNCTION CALL 4 con parámetro 15
¿Por qué usamos funciones?
Las funciones se utilizan para reducir el número de líneas en nuestro código. Esto es lo que la mayoría de nosotros habría sabido. Pero, ¿por qué tenemos que reducir la cantidad de líneas, especialmente cuando se trata de la programación de MCU? La razón es el espacio limitado en nuestra memoria del programa. Si no optimizamos el código correctamente, podríamos quedarnos sin espacio de memoria. Esto será útil cuando escribamos largas páginas de códigos.
Cualquier función tendrá una Definición de función ( sblink (int get) en nuestro caso) y una función Call ( sblink (1) en nuestro caso). Es opcional tener una declaración de función, para evitarlo he colocado la definición de mi función antes de llamar a la función en mi función principal.
Los parámetros de función son el valor que se pasará de la llamada a la función a la definición de la función. En nuestro caso, los valores enteros (1, 3, 7, 15) son los parámetros que se pasan de la llamada a la función y la variable "get" obtiene el valor de los parámetros en la definición de la función para procesarlos. Una función puede tener más de un parámetro.
Una vez que se llama a la función, se ejecutarán las siguientes líneas en la definición de la función.
para (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED mueve la secuencia a la izquierda __delay_ms (50); } para (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED mueve la secuencia a la izquierda __delay_ms (50); }
Ahora esta línea parece ser extraña: PORTD = get << i . Explicaré lo que realmente está sucediendo aquí.
"<<" es un operador de desplazamiento a la izquierda que desplaza todos los bits a su posición izquierda. Ahora, cuando llamamos a la función sblink (int get) con el parámetro '1' como sblink (1), hará que el valor de 'get' sea 1, que en binario es 0b00000001. Por lo tanto, esta línea será como PORTD = 0b00000001 << i .
El valor de "i" variará de 0 a 7 ya que hemos usado un 'bucle for ' para (int i = 0; i <= 7 && RB0 == 0; i ++). El valor de 'i' de 0 a 7 cambiará el resultado de la siguiente manera:
Como puede ver, hemos encendido un LED a la vez (de izquierda a derecha) manteniendo el resto APAGADO. El siguiente 'for loop' para (int i = 7; i> = 0 && RB0 == 0; i--) , también hará lo mismo, pero esta vez el LED se encenderá de derecha a izquierda en una secuencia, ya que partimos de 7 y bajamos a 0. Hemos utilizado un retardo de 200ms para que podamos visualizar el LED encendido y apagado.
Ahora, cuando pasamos el valor 3 en la función sblink (int get) , se ejecutará la función sblink (3) , lo que hace que el valor de 'get' sea 0b00000011, por lo que el resultado en PORTD será:
Así que ahora, esta vez, dos LED se encenderán en un momento dado usando sblink (3). De manera similar, para sblink (7) y sblink (15), tres y cuatro LED estarán ENCENDIDOS en una secuencia. Una vez completado esto, haremos que todos los LED estén encendidos usando la línea PORTD = 0xFF . Consulte el video a continuación para ver una demostración completa.
Espero que haya entendido el código y, por lo tanto, haya aprendido a usar las funciones, el ciclo 'for' y 'while' para obtener los resultados deseados. Ahora puede modificar el código para que su secuencia diferente de LED parpadee. Continúe compilando su código y volcarlo en su MCU y disfrute del resultado. Puede usar la sección de comentarios si se queda atascado en algún lugar. También he adjuntado los archivos de simulación y programa aquí.
Eso es todo por ahora en nuestro próximo tutorial aprenderemos cómo usar los temporizadores PIC16F877A en lugar de usar funciones de retardo. Puede navegar por todos los tutoriales del microcontrolador PIC aquí.