Pues me ha costado un rato, pero aquí os he subido el ejercicio que ha propuesto Pacala con su simulación Proteus:
http://miarroba.com/foros/ver.php?foroid=348538&temaid=2665537
Este es el código:
Codigo:
#include <16F876.h>
#fuses XT,NOWDT,NOPROTECT
#use delay(clock=4000000)
#byte port_b = 6
#define INTS_POR_50ms 49 // (4000000/(4*4*256))/20
#define PASOS_LED1 20 // 1 seg = 50 ms * 20 pasos
#define PASOS_LED2 6 // 300 ms = 50 ms * 6 pasos
BYTE ms50; // Contador de tramos de 50ms
BYTE cuenta_ints; // Contador de interrupciones
BYTE cuenta_led1; // Contador ciclos LED1: 1 segundo
BYTE cuenta_led2; // Contador ciclos LED2: 300 ms
#int_rtcc
void interrupcion() { // aquí entra 49 veces cada 50ms
if(--cuenta_ints==0) { // decrementamos el contador y si es 0 entramos
cuenta_ints=INTS_POR_50ms; // volvemos a setear el contador
if (--cuenta_led1==0) { // decrementamos el contador de LED1 y si es 0 entramos
cuenta_led1=PASOS_LED1; // volvemos a setear el contador de LED1
output_bit (PIN_B0,!bit_test(port_b,0)); // e invertimos su estado
}
if (--cuenta_led2==0) { // decrementamos el contador de LED2 y si es 0 entramos
cuenta_led2=PASOS_LED2; // volvemos a setear el contador de LED2
output_bit (PIN_B1,!bit_test(port_b,1)); // e invertimos su estado
}
output_bit(PIN_B2,!bit_test(port_b,3)); // si se ha pulsado, encendemos LED3
}
}
void main() {
cuenta_ints=INTS_POR_50ms; // se inicializan los contadores
cuenta_led1=PASOS_LED1;
cuenta_led2=PASOS_LED2;
set_timer0(0); // se arranca el timer
setup_counters( RTCC_INTERNAL, RTCC_DIV_4 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while (TRUE){}; // y se deja el micro rulando
}
Pocher, le he hecho usando una base de tiempos de 50ms siguiendo tu sugerencia, pero no entiendo porque esa base de tiempos es clave. Creo que también podría funcionar con cualquier divisor de ambos periodos: 1000ms y 300ms
Siguiendo los consejos del amigo Modulay, he modificado el código descargando de trabajo a la interrupción y trasladando el mismo al bucle principal del programa:
Codigo:
#include <16F876.h>
#fuses XT,NOWDT,NOPROTECT
#use delay(clock=4000000)
#byte port_b = 6
#define INTS_POR_50ms 49 // (4000000/(4*4*256))/20
#define PASOS_LED1 20 // 1 seg = 50 ms * 20 pasos
#define PASOS_LED2 6 // 300 ms = 50 ms * 6 pasos
BYTE ms50; // Contador de tramos de 50ms
BYTE cuenta_ints; // Contador de interrupciones
BYTE cuenta_led1; // Contador ciclos LED1: 1 segundo
BYTE cuenta_led2; // Contador ciclos LED2: 300 ms
#int_rtcc
void interrupcion() { // aquí entra 49 veces cada 50ms
--cuenta_ints; // decrementamos el contador y si es 0 entramos
}
void main() {
cuenta_ints=INTS_POR_50ms; // se inicializan los contadores
cuenta_led1=PASOS_LED1;
cuenta_led2=PASOS_LED2;
set_timer0(0); // se arranca el timer
setup_counters( RTCC_INTERNAL, RTCC_DIV_4 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while (TRUE){
if(cuenta_ints==0) { // decrementamos el contador y si es 0 entramos
cuenta_ints=INTS_POR_50ms;
if (--cuenta_led1==0) { // si es 0 entramos
cuenta_led1=PASOS_LED1; // volvemos a setear el contador de LED1
output_bit (PIN_B0,!bit_test(port_b,0)); // e invertimos su estado
}
if (--cuenta_led2==0) { // si es 0 entramos
cuenta_led2=PASOS_LED2; // volvemos a setear el contador de LED2
output_bit (PIN_B1,!bit_test(port_b,1)); // e invertimos su estado
}
}
output_bit(PIN_B2,!bit_test(port_b,3)); // si se ha pulsado, encendemos LED3
};
}
Editado: se reduce aún más la carga de la interrupción