Tabla de contenido
En el diseño de sistemas basados en microcontroladores, es común la necesidad de introducir retardos de tiempo para sincronizar y controlar procesos. Esto se vuelve especialmente relevante en aplicaciones donde se requiere la interacción con dispositivos externos o la generación de señales temporizadas.
Los microcontroladores ejecutan sus instrucciones a velocidades extremadamente altas, lo que puede dificultar la percepción visual de ciertos procesos para el ojo humano. Por lo tanto, es necesario introducir retardos de tiempo, también conocidos como “delays”, para ajustar el ritmo de ejecución y permitir que el usuario observe y comprenda los eventos que ocurren.
Los microcontroladores suelen proporcionar funciones específicas para generar retardos de tiempo internos. Una de las bibliotecas más comunes utilizadas para este propósito es <util/delay.h>
, que ofrece la función _delayMs()
para introducir retardos en milisegundos. Por ejemplo:
#include <avr/io.h>
// Velocidad del oscilador interno para dispositivo atmega328p
#define F_CPU 1000000UL
// Velocidad del oscilador externo para Tarjeta de desarrollo Arduino UNO
//#define F_CPU 16000000UL
/* Incluye la biblioteca que proporciona funciones para generar retardos de tiempo */
#include <util/delay.h>
_delayMs(1000); // Esta instrucción provoca un retardo de 1000 milisegundos (1 segundo)
Otra forma de introducir retardos es mediante la implementación de funciones personalizadas que utilizan bucles for
para esperar un cierto número de ciclos de reloj del microcontrolador. Por ejemplo:
//--Ejemplo de una Funcion delay
/* Declaración de una variable de tipo unsigned int (entero sin signo) y volátil para
asegurar que no sea optimizada por el compilador*/
/* Bucle FOR que se ejecuta hasta que la variable cnt alcance el valor de 55555,
aproximadamente 1 segundo a una frecuencia de reloj de 1 MHz*/
void delay1s(void)
{
volatile unsigned int cnt;
for (cnt = 0; cnt < 55555; cnt++);
}
//--Ejemplo de una Funcion delay
/* Declaración de una variable de tipo unsigned int (entero sin signo) y volátil para
asegurar que no sea optimizada por el compilador */
/* Bucle FOR que se ejecuta hasta que la variable cnt alcance el valor de 27777, aproximadamente 0.5 segundos a una frecuencia de reloj de 1 MHz*/
void delayMs(void)
{
volatile unsigned int cnt;
for (cnt = 0; cnt < 27777; cnt++);
}
Estas funciones permiten introducir retardos personalizados en función de la frecuencia de reloj del microcontrolador y el número de iteraciones del bucle for
. Es importante tener en cuenta que el valor del retardo puede variar dependiendo de la frecuencia de reloj del microcontrolador y las optimizaciones del compilador.
//" ¡No copies y pegues el código, analízalo e inspirate en el! "
/*************************************************************************
* Copyright (C) 2024 Jesús Camarena *
* [email protected] *
* Licencia: Attribution-NonCommercial-ShareAlike 3.0(CC-BY-NC-SA 3.0) *
* <https://creativecommons.org/licenses/by-nc-sa/3.0/> *
* *
* Ejemplo: *
* Dispositivo: Atmega328p *
* Lenguaje: C *
* Rev: 1.0 *
* Fecha: 13/02/24 *
************************************************************************/
// Incluye la biblioteca que proporciona el control de los registros del AVR
#include <avr/io.h>
// Velocidad del oscilador interno para dispositivo atmega328p
#define F_CPU 1000000UL
// Velocidad del oscilador externo para Tarjeta de desarrollo Arduino UNO
//#define F_CPU 16000000UL
// Incluye la biblioteca que proporciona funciones para generar retardos de tiempo
#include <util/delay.h>
int main(void) // Función principal
{
// Configuración del puerto D como salida
DDRD = 0b11111111; // Configura todos los pines del puerto D como salida
// Secuencia de encendido de los pines del puerto D
PORTD = 0b00000001; // Enciende el bit 0
_delay_ms(500); // Espera 500 milisegundos
PORTD = 0b00000010; // Enciende el bit 1
_delay_ms(500); // Espera 500 milisegundos
// Bucle infinito
while (1) // Bucle principal
{
// El programa permanece aquí de forma indefinida
}
}
/*****Encabezado*****/
;//Directivas se escriben con un punto al inicio
;//.INCLUDE "m328pdef.inc" //Archivo ya cargado en el sistema
.CSEG ; Inicia el segmento de código en memoria flash
.ORG $00 ; Establece la dirección de inicio en hexadecimal 00
/*****Configuración*****/
; Configuración de registros
LDI R16, 0b11111100 ; Carga el número binario 11111111 en R16
OUT DDRD, R16 ; Configura todos los pines del puerto D como salida
/*****Ejecución*****/
start: ; Etiqueta donde se ejecuta el programa (bucle)
; Enciende el bit 0 en PORTD
LDI R16, 0b1111_1100 ; Carga el número binario 00000001 en R16
OUT PORTD, R16 ; Enciende el pin 0 en el puerto D
; Delay aproximado de 500ms (ajustar si es necesario)
LDI R18, 31 ; Cargar 31 en R18 (número de iteraciones)
delay_loop1:
LDI R19, 250 ; Cargar 250 en R19
delay_loop2:
LDI R20, 250 ; Cargar 250 en R20
delay_loop3:
DEC R20 ; Decrementa R20
BRNE delay_loop3 ; Si R20 no es cero, repite el bucle
DEC R19 ; Decrementa R19
BRNE delay_loop2 ; Si R19 no es cero, repite el bucle externo
DEC R18 ; Decrementa R18
BRNE delay_loop1 ; Si R18 no es cero, repite el bucle externo
; Apaga todos los bits en PORTD
LDI R16, 0b00000000 ; Carga el número binario 00000000 en R16
OUT PORTD, R16 ; Apaga todos los pines en el puerto D
; Delay aproximado de 500ms (ajustar si es necesario)
LDI R18, 31 ; Cargar 31 en R18 (número de iteraciones)
delay_loop4:
LDI R19, 250 ; Cargar 250 en R19
delay_loop5:
LDI R20, 250 ; Cargar 250 en R20
delay_loop6:
DEC R20 ; Decrementa R20
BRNE delay_loop6 ; Si R20 no es cero, repite el bucle
DEC R19 ; Decrementa R19
BRNE delay_loop5 ; Si R19 no es cero, repite el bucle externo
DEC R18 ; Decrementa R18
BRNE delay_loop4 ; Si R18 no es cero, repite el bucle externo
RJMP start ; Salta a la etiqueta 'start' de nuevo, creando un bucle infinito
//" ¡No copies y pegues el código, analízalo e inspirate en el! "
/*************************************************************************
* Copyright (C) 2024 Jesús Camarena *
* [email protected] *
* Licencia: Attribution-NonCommercial-ShareAlike 3.0(CC-BY-NC-SA 3.0) *
* <https://creativecommons.org/licenses/by-nc-sa/3.0/> *
* *
* Ejemplo: *
* Dispositivo: Atmega328p *
* Lenguaje: C *
* Rev: 1.0 *
* Fecha: 13/02/24 *
************************************************************************/
// Incluye la biblioteca que proporciona el control de los registros del AVR
#include <avr/io.h>
// Velocidad del oscilador interno para dispositivo atmega328p
#define F_CPU 1000000UL
// Velocidad del oscilador externo para Tarjeta de desarrollo Arduino UNO
//#define F_CPU 16000000UL
// Incluye la biblioteca que proporciona funciones para generar retardos de tiempo
#include <util/delay.h>
#define TIME 500
int main(void) // Función principal
{
// Configuración del puerto D como salida
DDRD = 0b11111111; // Configura todos los pines del puerto D como salida
// Bucle infinito
while (1) // Bucle principal
{
// Secuencia de encendido de los pines del puerto D
PORTD = 0b00000001; // Enciende el bit 0
_delay_ms(TIME); // Espera el tiempo que vale TIME
PORTD = 0b00000010; // Enciende el bit 1
_delay_ms(TIME); // Espera el tiempo que vale TIME
PORTD = 0b00000100; // Enciende el bit 2
_delay_ms(TIME); // Espera el tiempo que vale TIME
PORTD = 0b00001000; // Enciende el bit 3
_delay_ms(TIME); // Espera el tiempo que vale TIME
PORTD = 0b00010000; // Enciende el bit 4
_delay_ms(TIME); // Espera el tiempo que vale TIME
PORTD = 0b00100000; // Enciende el bit 5
_delay_ms(TIME); // Espera el tiempo que vale TIME
}
}