int j=0;
int i=0;
while(j==0) //mientras ningun interruptor sea pulsado
{
for (i=0;i<9;i++) //chequeo de todos los inerruptores
{
if(!(input(Interruptor[i]))) //interruptor contiene todos los interruptores y es de tamaño 9
{
qué hacer....;
j=1; //salgo del while
}
}
}
pero no me parece que sea una solucion optima.. es un poco chapucerolo que haces en tu codigo es un bucle infinito....Código: [Seleccionar]int j=0;
int i=0;
while(j==0) //mientras ningun interruptor sea pulsado
{
for (i=0;i<9;i++) //chequeo de todos los inerruptores
{
if(!(input(Interruptor[i]))) //interruptor contiene todos los interruptores y es de tamaño 9
{
qué hacer....;
j=1; //salgo del while
}
}
}
a ver... una interrupcion es lo que la palabra indica... interrupcion...
imagina que esta en una funcion... por ejemplo esta...
___________________________________esto es la funcion de interrupcion por el puerto b4,7____________________________________________________
#int_rb
void cuenta_isr(){
if(comparacion==0x00)valor_puerto[0]=portb;else valor_puerto[1]=portb;
for(cuenta=4;cuenta<=7;++cuenta){
if((bit_test(valor_puerto[0],cuenta))!=(bit_test(valor_puerto[1],cuenta)))++resultado[cuenta-4];
}
comparacion=~comparacion;
if(flag_cambio==0xFF){printf(lcd_putc "\f1 %lu 2 %lu \n3 %lu 4 %lu " resultado[0],resultado[1],resultado[2],resultado[3]);
flag_cambio=0x00;
for(borrado=0;borrado<=3;++borrado){
resultado[borrado]=0;
}
}
}
______________________________________funcion interrumpida________________________________________________________
void ejemplo(){
for(;;){
delay_ms(10);
porta= efecto_luces;
efecto_luces=efecto_luces+1;
}
}
si hay una interrupcion... deja lo que estaba haciendo el pic en ese momento y atiende la funcion de la interrupcion, osea imagina que hay una interrupcion justo despues de la linea porta= efecto_luces; entonces dejaria de momento lo que esta haciendo y ejecutaria la funcion void cuenta_isr(), una vez acabada esta retomaria lo que estaba haciendo...
#int_default
void interruptor0
{la funcion.....}
y una interrupcion para cada interruptor?
1- porqué es una interrupcion por el puerto b4,7 como dices? qué la hace especifica a ese puerto?
2- en tu ejemplo, si la interrupcion es justo despues de porta= efecto_luces; qué es lo que activaria la interrupcion? para mi se necesita un if que testee para ver si la interrupcion ha sucedido ...
3- he mirao en CCs la ayuda sobre las interrupciones..
a mi entender yo necesitaria algo tipo: #int_default
1- porqué es una interrupcion por el puerto b4,7 como dices? qué la hace especifica a ese puerto?
2- en tu ejemplo, si la interrupcion es justo despues de porta= efecto_luces; qué es lo que activaria la interrupcion? para mi se necesita un if que testee para ver si la interrupcion ha sucedido ...
3- he mirao en CCs la ayuda sobre las interrupciones..
a mi entender yo necesitaria algo tipo: #int_default
a ver...
1 el puerto B del 16f628A se puede habilitar la interrupcion por el cambio de flanco en los pines RB4....al RB7 que es justo el ejemplo que yo te he puesto....
2 la interrupcion puede pasar en cualquier instante,antes del delay_ms(), mientras esta en el delay_ms() despues del delay_ms().... imagina que mientras se ejecuta una funcion se detecta un envio por el puerto serie de un dato... el pic debe de ser capaz, de parar lo que esta haciendo, acabar de recibir el valor que se le ha enviado, procesar el dato, actuar ante lo recibido y retomar lo que estaba haciendo...
3 mejor centrate en el tipo de interrupcion que necesitas asi no utilizaras toda la rom del pic..
imagina lo qu puedes hacer con todo esto y mucho mas.... eto son las interrupciones posibles en un 16f886...
[...]
#INT_RB
void leer_interruptor()
{
for (i=0;i<8;i++)
{
if (bit_test(port_b,i)==1) //la habia definido port_b como la direcction de puerto b en otro ligar del codigo
{
el interruptor conectado al pin i del puerto b ha sido pulsado (o no, dependiendo de si estoy en pull-up o pull-down);
}
}
}#include <18F4550.h>
#use delay(clock=2000000)
#byte port_a=0xF80 //esto es correcto, seguro ;)
#byte port_b=0xF81
#byte port_c=0xF82
#byte port_d=0xF83
#byte port_e=0xF84
#INT_RB
void leer_interruptor()
{
int valor_puerto;
valor_puerto=port_b;
if (bit_test(valor_puerto,5)==0) //he probao poniendo ==1 por si acaso
{
output_high(PIN_A0); //nunca he conseguido encenderla
}
}
int main()
{
port_a=0x00;
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;
set_tris_a(0b0000000);
set_tris_b(0b11111111);
set_tris_c(0b00000000);
set_tris_d(0b00000000);
set_tris_e(0b1000);
enable_interrupts(INT_RB); //he probao a poner esto o quitarlo, sin efecto alguno
while(1)
{
output_high(PIN_D0); //esto lo hace bien
delay_ms(1000);
output_low(PIN_D0);
delay_ms(1000);
}
}osea que el codigo funciona bien, y ni casoentonces, supongamos que yo tnego 8 interruptores (no es el caso, pero bueno, pa entender...) conectados al puerto B (de 0 a 7) en un pic18f4550
(en en .h de CCS he visto que existe #INT_RB supongo pues que las interrupciones funcionan para todo el puerto B)
entonces, supongamos que yo tnego 8 interruptores (no es el caso, pero bueno, pa entender...) conectados al puerto B (de 0 a 7) en un pic18f4550
(en en .h de CCS he visto que existe #INT_RB supongo pues que las interrupciones funcionan para todo el puerto B)
Hola excalibur1491, #INT_RB solo es para los pines RB4 a RB7. Para aprender más sobre el uso de esta interrupción te recomendaría estudiar el ejemplo del CCS: EX_PBUTT.C
Saludos!
En el código también te falta: enable_interrupts(GLOBAL);
Leete también esto, te puede ayudar: http://www.todopic.com.ar/foros/index.php?topic=21226.0 (http://www.todopic.com.ar/foros/index.php?topic=21226.0)
Te conviene buscar en el foro sobre teclados matriciales, hay mucha información al respecto.
Tené en cuenta que un teclado de 16 teclas matricial lo podés manejar utilizando 8 pines, lo cual es mucho mas conveniente que utilizar un pin por tecla. Con 7 pines del PIC podrías manejar un teclado de hasta 12 teclas
#include <18F4550.h>
#use delay(clock=2000000)
#include <math.h>
#byte port_a=0xF80 //puertos de 18f4550
#byte port_b=0xF81
#byte port_c=0xF82
#byte port_d=0xF83
#byte port_e=0xF84
void main()
{
port_a=0x00; //inicializo puertos
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;
set_tris_a(0b0111110);
set_tris_b(0b00000000);
set_tris_c(0b0000000);
set_tris_d(0b00000000);
set_tris_e(0b1111);
float p=6;
double q=6;
setup_adc_ports(AN0); //leo la tension por an0 que es A0
setup_adc(ADC_CLOCK_INTERNAL); //no sé pa que sirve, pero en un ejemplo lo ponian asi
while (1)
{
set_adc_channel(0); //leo por el canal 0, osea An0
delay_us(20); //espero
output_high(PIN_B7); //enciendo un led que me dice que es el momento de pulsar el interruptor
delay_ms(1000); //mientras este segundo, pulso el interruptor
q=read_adc(); //leo la tension
//q=floor(q);
output_low(PIN_B7); //apago el led
p=5.0*q /1024.0 ; //calculo la tension
if (p==0) //si la tension era nula, osea que el interruptor no estaba apretao
{output_high(PIN_B3);} //enciendo el led B3
if (ceil(p)==5) //si aprieto el boton con una resistencia de 10k la tension se pone a 5V y apago el led B3
{output_low(PIN_B3);} //PERO NO LO APAGA NUNCA
if (floor(p)==2) //resistencia de 0.07Ohm
{output_high(PIN_B4);} //NUNCA LO ENCIENDE
delay_ms(1000);
}
}
Te conviene buscar en el foro sobre teclados matriciales, hay mucha información al respecto.
Tené en cuenta que un teclado de 16 teclas matricial lo podés manejar utilizando 8 pines, lo cual es mucho mas conveniente que utilizar un pin por tecla. Con 7 pines del PIC podrías manejar un teclado de hasta 12 teclas
ya he visto el post sobre el tecaldo 4x4... no entiendo na! y ademas no dispongo de teclado, solo de interruptores sueltos
estoy haceindo un 3 en raya , asi que 9 interruptores sueltos conectados al PIC -> 9 pines....
el problema es el siguiente: apra disminuir el consumo, voy a encender un solo led a la vez, muy rapido para que parezca que estan todos encendidos...
pero si hago esto necesito que mi funcion de scaneo de los interruptores para ver donde quiere jugar la persona sea una interrupcion (porque no puedo ejecutar a la vez la funcion que ilumina los leds y la que chequea los botones).
por eso quiero usar una interrupcion.
No importa que no dispongas de un teclado matricial, se puede armar tranquilamente con teclas sueltas.
Por otro lado se puede usar la interrupción de alguno de los timers para que sea tu base de tiempo para el refresco de los leds.
Te muestro un ejemplo de como armar un teclado matricial con simples switch. Los pines Col x irían a salidas del pic y los pines Fila x irían a entradas que generen interrupción (RB4..RB7), entonces cuando se presiones alguna tecla se une el puerto de salida con el de entrada y genera interrupción.
Incluso para tu caso que necesitas 9 pulsadores te alcanza con sólo 6 pines.
void print(char* T)
{
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
output_high(PIN_B0);
output_high(PIN_B1);
output_high(PIN_B2);
output_high(PIN_A0);
while(j==0)
{
//Enciendo unas leds segun una secuencia: funciona bien
}
disable_interrupts(GLOBAL);
disable_interrupts(INT_RB);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_A0);
j=0;
}#INT_RB //teclado
void teclado(char* T, int* movmntsO, int* M)
{
int i=4;
int linea=0;
int columna=0;
int mov=0;
for (i=4;i<7;i++) //Chequeo que linea ha sido pulsada (rb4, rb5 o rb6)
{
if (bit_test(port_b,i)==1)
{linea=i-3;} //las lineas se llaman 1 2 o 3... asi que corrijo i
}
i=0;
for(i=0;i<3;i++)
{
output_low(31752+i); // pone a 0 la columna i (el PIN_B0 esta definido en el header como 31752, asi q uso directamente el numero)
if (bit_test(port_b,linea+3)==0) //la linea ya no recibe corriente (corrijo.. si linea=1 quiero mirar el rb4, asi que linea+3
{columna=i;} //
}
if (linea==1)
{mov=columna;} //mi cuadro T es asi: {0 ,1 ,2
if (linae==2) 3, 4, 5,
{mov=columna+3;} 6, 7, 8}
if (linea==2)
{mov=columna+6;}
movmntsO[*M]=mov; // esto funciona bien ;)
T[mov]='O';
*M=*M + 1;
j=1; //para para la funcion print
clear_interrupt(INT_RB);
}
port_b=0x00;
set_tris_b(0b01110000);
y lo que sucede este me hace bien la secuencia de leds cuando entra por primera vez en print(T) pero en cuandot pulso un interruptor, se paga todo y buenas noches..... No sé que fallo hay,excalibur1491:
Podés subir el código completo y el dsn así chequeo el funcionamiento.
Saludos.
Jukinch
excalibur1491:
Subí sólo la parte del header en donde definís los pines.
En los comentarios hacés referencia a que el PIN_B0 esta definido en el header como 31752 y si no me equivoco me parece que luego lo utilizas como si hicieras referencia a todo el puerto b completo?
Por las dudas te aclaro que las funciones output_high(PIN); o output_low(PIN); sólo controlan un pin del microcontrolador,
Si quieres controlar todo el puertob entero, usá la función output_b(DATO);
Jukinch
excalibur1491:
Con relación al tema del array vi el código esta mañana y veo que lo has resuelto solo y era por el ámbito del array T[] el cual estaba declarado dentro de main y no como global como las otras variables que usabas.
Con respecto a la optimización te sugiero que dentro de la interrupción hagas lo menos posible. Tan sólo cambiar de estado banderas para luego consultarlas en el programa principal para que no se haga un cuello de botella en el código e implementes un antirebote con un algoritmo que no espere un tiempo X. (como es el delay_ms(100))
Para ello verifica 10 veces seguidas si una variable de tipo bool como ser botonPulsado sea verdadera las 10 veces seguidas en que la consultaste. Con eso detectarás que el botón se haya pulsado de verdad y no que sea ruido.-
Si no llega a ser verdadera en una de las 10 veces en que consultaste, que descarte la pulsación y vuelva a ingresar al bucle en donde comprobás si se pulsó el botón. Con esto eliminarás el ruido de la pulsación de los botones y serán menores las esperas.
Y tambíen usaría un cristal que me de el mayor clock para la velocidad de trabajo del micro.
Saludos.
Jukinch.
mm, no, no se entiende, xD
TEMA ANTIRREBOTE:
normalmente se usa una espera de x milisegundos para evitar que una pulsación mecánica se interprete digitalmente como varias pulsaciones por los motivos que ya conoces.
Pero eso no es lo óptimo. ¿Por que esperar X tiempo?
Se puede comprobar en menos tiempo que X.
Para ello debes crear un algoritmo que verifica si el botón se pulsó, y además se mantuvo pulsado durante x iteraciones.
Un ejemplo a continuación:
do {
if (input(PIN_B0) ) // controla si el botón se pulsó
arranca=arranca+1;
ELSE
IF (ARRANCA>1)
arranca=arranca-1;
}while(arranca<=100); // el valor de 100 lo podés variar en más o en menos para afinarlo a tu necesidad.
Es poco probable que tengas un ruido que dure 100 iteraciones seguidas con el estado alto de RB0.
Y así el tiempo de este algoritmo es mucho menor que esperar 1 milisegundo. Se entiende?
excalibur1491:
Por ahora olvidate del algoritmo del antirebote y probá sólo con bajar el delay de 100ms a 20 ms para ver que resultado tenés.
Dependiendo de la calidad del botón podés llegar hasta los 5ms. Pero es cuestión de que pruebes.
Saludos.
Jukinch
do {
if (input(PIN_B0) ) // controla si el botón se pulsó
arranca=arranca+1;
ELSE
IF (ARRANCA>1)
arranca=arranca-1;
}while(arranca<=100); do {
if (!input(PIN_B0) ) // controla si el botón se pulsó
arranca=arranca+1;
ELSE
IF (ARRANCA>1)
arranca=arranca-1;
}while(arranca<=100);
#INT_RB
interrupcion_RB4_RB7()
{
arranca=0;
do {
if (input(PIN_B4) ) // controla si el botón se pulsó
arranca=arranca+1;
else
if(arranca>1)
arranca=arranca-1;
}while(arranca<=100);
.
.
.
#INT_RB
interrupcion_RB4_RB7()
{
arranca = 0;
do
{
if (input(PIN_B4) ) // controla si el botón se pulsó
arranca = arranca+1;
else //Se ha quitado el if(arranca>1)
arranca = arranca-1;
}
while (arranca < 100) && (arranca > 0); //La variable arranca debe se definida como signed
#INT_EXT
interrupcion_RB0()
{
arranca = 0;
do {
if (input(PIN_B0) ) // controla si el botón se pulsó
arranca=arranca+1;
ELSE
IF (ARRANCA>1)
arranca=arranca-1;
}while(arranca<=100); #INT_EXT
interrupcion_RB0()
{
arranca = 0;
do {
if (!input(PIN_B0) ) // esta es la unica modificacion
arranca=arranca+1;
ELSE
IF (ARRANCA>1)
arranca=arranca-1;
}while(arranca<=100); Los pulsadores siempre generan rebotes cuando los soltamos.
Supongo que cuando te refieres a "por cambio de flanco" te estas refiriendo a por cambio de estado en pines RB4..RB7 ¿es así? , conviene aclararlo porque si no, nos liaremos.
Si la interrupción es por cambio de estado en RB4..RB7, efectivamente al soltar la tecla de nuevo se entraria en la interrupción y como RB4=0, no se saldria del while.
................
La solución es como dices:Código: [Seleccionar]#INT_RB
interrupcion_RB4_RB7()
{
arranca = 0;
do
{
if (input(PIN_B4) ) // controla si el botón se pulsó
arranca = arranca+1;
else //Se ha quitado el if(arranca>1)
arranca = arranca-1;
}
while (arranca < 100) && (arranca > 0); //La variable arranca debe se definida como signed
#INT_RB
interrupcion_RB4_RB7()
{
arranca = 125;
do
{
if (input(PIN_B4) ) // controla si el botón se pulsó
arranca = arranca+1;
else
arranca = arranca-1;
}
while (arranca < 250) && (arranca > 0);
.
.
.#INT_EXT
interrupcion_RB0()
{
arranca = 125;
do
{
if (input(PIN_B0) ) // controla si el botón se pulsó
arranca = arranca+1;
else
arranca = arranca-1;
}
while (arranca < 250) && (arranca > 0);
.
.
.
#INT_RB
interrupcion_RB4_RB7()
{
arranca = 0;
do
{
if (input(PIN_B4) ) // controla si el botón se pulsó
arranca = arranca+1;
else
arranca = arranca-1;
}
while (arranca<= 100) ;