Hola de nuevo
Pues ahora me encuentro realizando un programa para generar una señal cuadrada con frecuencia variable. Mi problema está en que no me está pelando los cambios de estado, solo me manda una señal con frecuencia constante por el pin A0. Lo que estoy haciendo es utilizar tres push buttons en los pines B4,B5 y B6, controlando incremento, decremento y posición numérica (unidad, decena, centena y millar) respectivamente. Pero no se que estoy haciendo mal, este es el código que hice:
Codigo:
#include <16f874A.h>
#fuses HS,NOWDT,NOPROTECT //define los fusibles que se deben poner en al parte al momento de programar
#use delay(clock=20000000) //le dice al compilador la velocidad del procesador y habilita el uso de las funciones delay_ms() and delay_us(). La velocidad es en ciclos por segundo
int cuenta=0;
int valor=9;
int u=0;
int d=0;
int c=0;
int m=0;
void flash_led_up()
{
output_low(PIN_A0);
delay_ms(u);
delay_ms(d*10);
delay_ms(c*100);
delay_ms(m*1000);
output_high(PIN_A0);
delay_ms(u);
delay_ms(d*10);
delay_ms(c*100);
delay_ms(m*1000);
}
main()
{
set_tris_a(0x00);
set_tris_b(0xFF);
port_b_pullups(TRUE);
while (TRUE)
{
flash_led_up();
if (!input(PIN_B4))
{
delay_ms(50);
if (valor==9)
{
valor=0;
}
valor=valor+1;
}
else if (!input(PIN_B5))
{
delay_ms(50);
if (valor==0)
{
valor=9;
}
valor=valor-1;
}
else if (!input(PIN_B6))
{
delay_ms(50);
cuenta=cuenta+1;
if (cuenta==1)
{
u=valor;
}
else if (cuenta==2)
{
d=valor;
}
else if (cuenta==3)
{
c=valor;
}
else if (cuenta==4)
{
m=valor;
}
else
cuenta=0;
}
else
flash_led_up();
}
}
Si pudieran ayudarme se los agradecería bastante.
Hola Pocher
Pues muchas gracias por la ayuda que pudieras darme, ahorita tengo otro problema que necesito resolver lo más pronto posible. No se que estoy haciendo mal a la hora de querer generar una señal cuadrada de frecuencia constante y ciclo de trabajo del 50%. Estoy utilizando for"s pero al momento de encender el pic pues solo me manda un nivel bajo si dejo fuera de los for los output y un nivel alto si dejo los output dentro de uno de los for.
Codigo:
#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, WRT //define los fusibles que se deben poner en al parte al momento de programar
#use delay(clock=20000000) //le dice al compilador la velocidad del procesador y habilita el uso de las funciones delay_ms() and delay_us().
void main()
{
int i,j;
int periodo=1;
int ciclo=10;
set_tris_a(0x00);
set_tris_b(0xFF);
while(TRUE)
{
for(i=1;i=periodo;i++)
{
for(j=1;j=ciclo;j++)
{
//output_high(PIN_A0);
delay_ms(1);
}
}
output_high(PIN_A0);
for(i=1;i=periodo;i++)
{
for(j=ciclo;j<20;j++)
{
//output_low(PIN_A0);
delay_ms(1);
}
}
output_low(PIN_A0);
}
}
Ahora si que no se ni por donde. De antemano gracias por la ayuda
Aquí lo tienes:
Codigo:
#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT //define los fusibles que se deben poner en al parte al momento de programar
#use delay(clock=20000000) //le dice al compilador la velocidad del procesador y habilita el uso de las funciones delay_ms() and delay_us().
void main()
{
int i,j;
int periodo=1;
int ciclo=10;
set_tris_a(0x00);
set_tris_b(0xFF);
while(TRUE)
{
//for(i=1;i=periodo;i++)
for(i=1;i<=periodo;i++)
{
for(j=1;j<=ciclo;j++)
{
//output_high(PIN_A0);
delay_ms(1);
}
}
output_high(PIN_A0);
for(i=1;i<=periodo;i++)
{
for(j=ciclo;j<20;j++)
{
//output_low(PIN_A0);
delay_ms(1);
}
}
output_low(PIN_A0);
}
}
El error estaba en que te faltaba el signo < y en los FUSES es NOWRT
¿Porqué no lo haces con PWM? Es más elegante y rápido.
Un saludo
PD. Cuando quieras seguimos con el otro.
Pues muchas gracias Pocher, ahora se que estaba haciendo mal. Sabes, el chiste del programa que quiero hacer es que necesito generar una señal cuadrada con un rango de frecuencias entre 20 y 3000 pulsaciones por minuto, lo que equivaldria a 0.3333 y 50 Hz. El programa que hice para hacerlo es el siguiente:
Codigo:
#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#include<lcd.c>
int i,j;
int periodo=1;
int ciclo=10;
int duty;
int freq;
void flash_led_up()
{
for(i=1;i<=periodo;i++)
{
for(j=1;j<=ciclo;j++)
{
output_high(PIN_A0);
delay_ms(1);
}
}
for(i=1;i<=periodo;i++)
{
for(j=ciclo;j<20;j++)
{
output_low(PIN_A0);
delay_ms(1);
}
}
lcd_putc("f");
lcd_gotoxy(1,1);
freq=50/periodo;
printf (lcd_putc, "Freq=%2d Hz", freq);
lcd_gotoxy(9,2);
lcd_putc(37);
lcd_gotoxy(1,2);
duty=5*ciclo;
printf (lcd_putc, "Duty=%2d", duty);
}
void main()
{
set_tris_a(0x00);
set_tris_b(0xFF);
port_b_pullups(TRUE);
lcd_init();
while (TRUE)
{
while (input(PIN_B4)&&input(PIN_B5)&&input(PIN_B6)&&input(PIN_B7))
{
flash_led_up();
}
if (!input(PIN_B4))
{
delay_ms(30);
if (periodo==1)
periodo=50;
else
periodo=periodo-1;
while(!input(PIN_B4))
{
//Espera a que se libere el botón
}
delay_ms(30);
}
else if (!input(PIN_B5))
{
delay_ms(30);
if(periodo==50)
periodo=1;
else
periodo=periodo+1;
while(!input(PIN_B5))
{
//Espera a que se libere el botón
}
delay_ms(30);
}
else if (!input(PIN_B6))
{
delay_ms(30);
if(ciclo==19)
ciclo=1;
else
ciclo=ciclo+1;
while(!input(PIN_B6))
{
//Espera a que se libere el botón
}
delay_ms(30);
}
else if (!input(PIN_B7))
{
delay_ms(30);
if(ciclo==1)
ciclo=19;
else
ciclo=ciclo-1;
while(!input(PIN_B7))
{
//Espera a que se libere el botón
}
delay_ms(30);
}
else
flash_led_up();
}
}
En general hace lo que le pido, solo que tengo ciertos problemillas. Uno es que para periodos grandes por ejemplo mayores a 1s, los botones como que no responden. Y ahora el más reciente problema es que al usar el lcd, las instrucciones me generan un retardo extra y cuanto debería de tener un ciclo de trabajo del 50% pues ya no lo tengo.
Bueno, como me habías dicho, empezaré a trabajar con las interrupciones para los botones y te diré como voy. De antemano gracias por la ayuda.
PD: perdón por postear 2 veces el mismo problema.
Hola de nuevo Pocher
Pues empecé a hacer mi programa pero solo con interrupcion para los botones y pues como que no me gustó, porque se tarda en ejecutarse la función, y sin las interrupciones lo hace más rápido.
En fin, el programa con la interrupción por cambio de estado es este:
Codigo:
#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#BIT RBIF=0xB.0
#byte PORTB=0x06
#include <lcd.c>
int i,j;
int periodo=1;
int ciclo=10;
int duty;
int freq;
int tecla=0; //Bandera de tecla
void flash_led_up()
{
for(i=1;i<=periodo;i++)
{
for(j=1;j<=ciclo;j++)
{
output_high(PIN_A0);
delay_ms(1);
}
}
for(i=1;i<=periodo;i++)
{
for(j=ciclo;j<20;j++)
{
output_low(PIN_A0);
delay_ms(1);
}
}
}
void despliegue_lcd()
{
freq=50/periodo;
duty=5*ciclo;
lcd_gotoxy(1,1);
printf (lcd_putc, "Freq=%2d Hz", freq);
lcd_gotoxy(1,2);
printf (lcd_putc, "Duty=%2d", duty);
}
void signal()
{
if (tecla==1)
{
if (periodo==1)
periodo=50;
else
periodo=periodo-1;
}
else if (tecla==2)
{
if(periodo==50)
periodo=1;
else
periodo=periodo+1;
}
else if (tecla==3)
{
if(ciclo==19)
ciclo=1;
else
ciclo=ciclo+1;
}
else if (tecla==4)
{
if(ciclo==1)
ciclo=19;
else
ciclo=ciclo-1;
}
else
flash_led_up();
}
#int_RB
void interrupcion()
{
int current;
static int last=0xF0;
//Cuando la deteccion es de alto a bajo, last debe iniciar en 0xFF
//para que detecte por primera vez de forma correcta que se presiona el
//boton. En la libreria si se trabaja en el modo bajo a alto, debe de
//estar seguro que los botones se encuantran normalmente en cero.
current=PORTB; //Valor actual del puerto B
if (!(bit_test(current,4))&&(bit_test(last,4))) {tecla=1;} //Si el PIN_B4 pasa de 1 a 0 activa la tecla #1
if (!(bit_test(current,5))&&(bit_test(last,5))) {tecla=2;} //Si el PIN_B5 pasa de 1 a 0 activa la tecla #2
if (!(bit_test(current,6))&&(bit_test(last,6))) {tecla=3;} //Si el PIN_B6 pasa de 1 a 0 activa la tecla #3
if (!(bit_test(current,7))&&(bit_test(last,7))) {tecla=4;} //Si el PIN_B7 pasa de 1 a 0 activa la tecla #4
delay_ms(50);
last=current; //El valor actual se almace en last para el siguiente ciclo
} //Al parecer se rectifica que efectivamente se oprime la tecla y que permanece oprimida por lo memos 50ms
void iniciar()
{
set_tris_b(0xFF);
set_tris_a(0x00);
port_b_pullups(TRUE);
lcd_init();
lcd_putc("f");
lcd_gotoxy(9,2);
lcd_putc(37);
RBIF=0;
enable_interrupts(int_RB);
enable_interrupts(global);
}
main()
{
iniciar();
while(TRUE)
{
despliegue_lcd();
flash_led_up();
signal();
tecla=0;
}
}
Ahora bien, cómo le podría hacer para establecer una base de tiempo con interrupciones en lugar de delay"s. Se como hacer la interrupción pero lo que no se es como habilitarla cuando yo quiera y tomarla como si fuera un delay, no se si me explique.
Muchas gracias por toda la ayuda.
Hola Pocher
Pues ya quedó como yo quería y gracias a los consejos que me diste, en verdad te agradezco. Este es el código final:
Codigo:
#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#BIT RBIF=0xB.0
#byte PORTB=0x06
#include <lcd.c>
int i,j;
long periodo=150;
int ciclo=10;
int duty;
long per;
int tecla=0; //Bandera de tecla
void despliegue_lcd()
{
per=20*periodo;
duty=5*ciclo;
lcd_gotoxy(1,1);
printf (lcd_putc, "Peri=%4ld", per);
lcd_gotoxy(1,2);
printf (lcd_putc, "Duty=%2d", duty);
}
void flash_led_up()
{
output_high(PIN_A0);
for(i=1;i<=periodo;i++)
{
for(j=1;j<=ciclo;j++)
{
delay_ms(1);
}
}
output_low(PIN_A0);
for(i=1;i<=periodo;i++)
{
for(j=ciclo;j<20;j++)
{
delay_ms(1);
}
}
}
void signal()
{
if (tecla==1)
{
tecla=0;
if (periodo==1)
periodo=150;
else
periodo=periodo-1;
}
else if (tecla==2)
{
tecla=0;
if(periodo==150)
periodo=1;
else
periodo=periodo+1;
}
else if (tecla==3)
{
tecla=0;
if(ciclo==19)
ciclo=1;
else
ciclo=ciclo+1;
}
else if (tecla==4)
{
tecla=0;
if(ciclo==1)
ciclo=19;
else
ciclo=ciclo-1;
}
}
#int_RB
void interrupcion()
{
int current;
static int last=0xF0;
//Cuando la deteccion es de alto a bajo, last debe iniciar en 0xFF
//para que detecte por primera vez de forma correcta que se presiona el
//boton. En la libreria si se trabaja en el modo bajo a alto, debe de
//estar seguro que los botones se encuantran normalmente en cero.
delay_ms(50);
current=PORTB; //Valor actual del puerto B
if (!(bit_test(current,4))&&(bit_test(last,4))) {tecla=1;} //Si el PIN_B4 pasa de 1 a 0 activa la tecla #1
if (!(bit_test(current,5))&&(bit_test(last,5))) {tecla=2;} //Si el PIN_B5 pasa de 1 a 0 activa la tecla #2
if (!(bit_test(current,6))&&(bit_test(last,6))) {tecla=3;} //Si el PIN_B6 pasa de 1 a 0 activa la tecla #3
if (!(bit_test(current,7))&&(bit_test(last,7))) {tecla=4;} //Si el PIN_B7 pasa de 1 a 0 activa la tecla #4
last=current; //El valor actual se almace en last para el siguiente ciclo
//Al parecer se rectifica que efectivamente se oprime la tecla y que permanece oprimida por lo memos 50ms
signal();
despliegue_lcd();
}
void iniciar()
{
set_tris_b(0xFF);
set_tris_a(0x00);
port_b_pullups(TRUE);
lcd_init();
lcd_putc("f");
lcd_gotoxy(11,1);
printf (lcd_putc,"mseg"
;
lcd_gotoxy(9,2);
lcd_putc(37);
RBIF=0;
enable_interrupts(int_RB);
enable_interrupts(global);
}
main()
{
iniciar();
despliegue_lcd();
while(TRUE)
{
flash_led_up();
}
}
Por aquí voy a andar porque todavía tengo que hacer un programa para controlar un motor, entonces necesitaré de tu ayuda. Gracias.