Soy nuevo aquí como OP, pero he estado visitando este sitio durante años. Esta vez, solo mirar otros problemas no me ha ayudado. Por lo tanto, me inscribo y solo pregunto!
Estoy creando un temporizador de cuenta regresiva con 30 luces que se apagan una tras otra durante un tiempo ajustable (para la escuela primaria de mi novia). Estoy usando pic16f628a y MPLAB con el compilador XC8. El hardware no es un problema, he tenido bastante práctica. El software por otro lado ..
El temporizador funciona, ya que puedo usar los botones para aumentar el tiempo establecido, presionar inicio, todas las luces se encienden y ver las luces lentamente (o, a veces, rápidamente) haciendo una cuenta regresiva. Sin embargo, no puedo arreglar el tiempo. Por ejemplo, 2 minutos establecidos duran 3 minutos, 4 minutos duran 5. Lo que he hecho con todas las variables relevantes, no funciona. El tiempo cambia, pero nunca correctamente. Por ejemplo, duplicar el número de interrupciones por luz no duplica (¡ni siquiera casi!) El tiempo y nunca lo hago bien. He calculado y probado docenas de variables y medidas correctivas. La precisión absoluta no es necesaria. He estado en este problema por más de 2 semanas y me estoy desesperando. ¡Por favor ayuda! Aquí está mi código (creo relevante):
include <xc.h>
pragma config FOSC = INTOSCIO // Oscillator Selection bits
pragma config WDTE = OFF // Watchdog Timer Enable bit
pragma config PWRTE = OFF // Power-up Timer Enable bit
pragma config MCLRE = ON // RA5/MCLR/VPP pin function is MCLR
pragma config BOREN = ON // Brown-out Detect Enable bit
pragma config LVP = OFF // Low-Voltage Programming Enable bit
pragma config CPD = OFF // Data EE Memory Code Protection bit
pragma config CP = OFF // Flash Program Memory Code Protection bit
define _XTAL_FREQ 4000000
volatile int intr = 0; //number of interrupts
void interrupt TimerOverflow(void)
{
if(TMR0IE && TMR0IF)
{
TMR0 = 0; //clear timer 0
TMR0IF=0; //clear flag
intr++; //count 1 interrupt
}
}
void buzzer() // this part just buzzes on start and on end, not included for cleanliness
void display2(int c) //multiplexing, this function displays the last sections' digits. Working so not included. int c is the number of minutes, as received from display()
void display(int b) //multiplexing, this function displays the first sections. Working so not included. int b is the number of minutes, as received from init() and teller()
void teller(int a) //a is the number of minutes as received from init(), 'teller' is counter in dutch
{
int perlight = a*67 //number of minutes times a variable (now 67) to calculate number of interrupts per light-shut-off
PS0 = 1; // Prescaler (1:256) is assigned to the timer TMR0
PS1 = 1;
PS2 = 1;
T0CS = 0; //internal clock selector
PSA = 0; //assign prescalar
TMR0IE = 1; //timer0 interrupt active
PEIE = 1; //peripheral interrupt active
GIE = 1; //global interrupt active
TMR0IF = 0; //clear timer0 flag
TMR0 = 0; // clear timer0
int d = 30; //turn all lights on starting the count
while(1) //endless loop
{
if (intr>=perlight) //if number of interrupts is more than 'needed' for one-light-shutoff
{
intr = 0; //reset interrupts
d--; //decrease count (turn one light off)
}
display(d); //send count to display
if(d==0) //if count is done
{
buzzer(); //beep 3 times
__delay_ms(500);
buzzer();
__delay_ms(500);
buzzer();
break;
}
}
}
void init()
{
int min = 0; //number of minutes that the clock needs to run
while(1) //endless loop
{
display(min); //send number of minutes to display function
if(RA2==0) //if 'add minute' button has been pressed
{
__delay_ms(50); //debouncer
if(RA2==0)
{
min++; //add minute to count
display(min); //send to display
}
}
if(RA3==0) //if start is pressed
{
__delay_ms(50); //debouncer
if(RA3==0)
{
if(min!=0) //if start is pressed, buzz and start teller()
{
buzzer();
teller(min);
}
if(min==0) // if start is pressed without timing set, buzz 3 times
{
buzzer();
__delay_ms(500);
buzzer();
__delay_ms(500);
buzzer();
}
}
}
}
}
void main()
{
TRISB = 0b00000000; //RB as Output PIN
TRISA = 0b00101100; //RA as Input/Output PIN
CMCON = 0b00000111; //disable comparators
while(1)
{
init(); //start init()
}
}
Realmente espero que alguien pueda ayudar a este C-amateur total ..
¡Gracias de antemano!
EDITAR: También he intentado usar timer2 con un contador de interrupciones cambiado. Esto fue incluso más extraño que antes, con 1 y 2 minutos de juego terminados en menos de un segundo, y 3 minutos y mucho más tiempo.
EDIT2 He intentado reemplazar la variable 'perlight' por un número entero (61 (2 minutos), segunda vez 122 (4 minutos)). ¡Tiempo perfecto! Pero ahora no es ajustable, ¿así que me imagino que algo está mal con 'perlight'?