Autor Tema: #INT_RB Problema al declararle su funcion  (Leído 1406 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 187
#INT_RB Problema al declararle su funcion
« en: 18 de Octubre de 2015, 15:50:14 »
Hola e observado en ejemplos de codigo referente a esta interrupcion que la funcion siempre tiene que estar debajo de #INT_RB pero yo no puedo hacer esto Mi intencion es que se genere el evento cuando se aplique un flanco alto en b4 La cabezera del programa es la siguiente:

Código: [Seleccionar]
#if defined(__PCM__)
#include <16f877.h>
#FUSES NOWDT, XT, PUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
//#fuses
#use delay(clock=4M)
#DEFINE use_portd_lcd TRUE
#include <lcd.c>
#include <stdio.h>
#use standard_io(A)           
#BYTE PORTB=0x06
#BYTE TRISB=0X1f //0001 1111
#BYTE PORTD=0X08
#BYTE TRISD=0X88 //1000 1000
#INT_RB //CAMBIO DE ESTADO ENTRE RB4 - B7
//Error si pongo aqui void RB_isr() //función de interrupción*

int1 grp2,grp3;
int1 ladra[5];
int8 peti,cliente,salir,nume;
int1 tarje,ser,nu;
unsigned int8 lee,atra,falloMF;
signed int32  mony;
int1 target[20];
int16 contra[20];
signed int32 saldo[20];
signed int32 M32;
    union UNI {
       signed int32 dat32;
       int8 bytes[4];
    };
signed int32 total,acumula;
int32 presta;
int16 meses=10;
int8 decimal,vari;
float prestamo,teres=2;
void lectura();
void borratotal();
void ponsea();
void ponme();
void skri();
void recogmateria();
void reembolso(int8 cli);
void refresco(int1 muta,int1 gp1,int1 gp2,int1 gp3);
int1 MASTER;
void recoge();
void COMBERSION(int1 Soy);
void tiempo(int8 espe);//
void mensaje(int8 men);
void mensa(int8 me);
void sajesal(int1 acet,int1 line);
void OPER(int8 dar);
void acionSalida();
void evalua();

//Error si pongo aqui #INT_RB*
void RB_isr() //función de interrupción

unsigned int8 valor=input_B();
valor=valor&0b00010000;
lcd_gotoxy(1,1);
if (valor>0){
output_high(PIN_a0);
lcd_putc("dentro");
}
else {
lcd_putc("no es b4"); }
delay_ms(1000);
output_low(PIN_a0);
clear_interrupt(INT_RB);
}

void main(){
int8 con,nume; 
ext_int_edge(l_to_h);//alto
clear_interrupt(INT_RB);
enable_interrupts(int_RB);
enable_interrupts(global);
 set_tris_b(0b00011111);
while(true){///WIL main()
.......
.......
} }

El error es
Error 71 Out of RON,A segment orthe program is too large  mensaje
Si acorto la funcion mensaje(); (cosa que no me combiene) es
Error 71 OUT of the program is to large  MAIN
y siempre hay una maldicion de memoria reservada

Me e metido asta hace poco en interrupciones tenia un mal concepto de lo que eran y lo tendre porque nisiquiera puedo hacer la prueba Que hago empiezo a cargarle a otro micro las funciones de este? Podria aver alguna otr manera de resolver esto?

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re:#INT_RB Problema al declararle su funcion
« Respuesta #1 en: 18 de Octubre de 2015, 16:04:37 »
Te da error porque ya pusiste #INT_RB más arriba. Probá ponerlo inmediatamente arriba de la declaración de tu función. Si no el compilador no tiene idea qué función ejecutar ante la interrupción.

Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6947
Re:#INT_RB Problema al declararle su funcion
« Respuesta #2 en: 18 de Octubre de 2015, 16:13:50 »
Mensaje escrito antes que gera (el seguro tiene mas idea que yo :P ):

No tengo mucha idea de lo que es el RTOS en CCS. Pero claramente tu problema es que estas haciendo una interrupcion demasiado larga. Es decir el programa que ejecuta dentro de la interrupcion ocupa mucho tiempo.

Los RTOS usan la interrupciones en un PIC de un timer para realizar el cambio de tareas. Supongamos que estas interrupciones son a cada 1 ms. Cuando entra a otra interrupcion en tu caso #int_rb y tarda mas que 1ms (ya que al entrar a una interrupcion se desactivan todas), estas parando el cambio de tareas y la base de tiempos, lo cual terminas haciendo cualquier cosa.

Por lo cual deberias quitar todos las funciones que ocupen demasiado tiempo. Una interrupcion debe ser rapida. Si veo tu codigo:

Código: C
  1. void RB_isr() //función de interrupción
  2. {  
  3. unsigned int8 valor=input_B();
  4. valor=valor&0b00010000;
  5. lcd_gotoxy(1,1);
  6. if (valor>0){
  7. output_high(PIN_a0);
  8. lcd_putc("dentro");
  9. }
  10. else {
  11. lcd_putc("no es b4"); }
  12. delay_ms(1000);
  13. output_low(PIN_a0);
  14. clear_interrupt(INT_RB);
  15. }

Tenes unos cuantos lcd_putc() y unos lcd_gotoxy(). Esos pueden usar hasta delays de unos cuantos milisegundos segun como esten realizados. Y ni hablar del delay de un segundo que tenes puesto.( Moraleja: La interrupciones siempre lo mas rapido posible )
Quitalos. Eso te va a solucionar el tema de que es muy largo.

Para lo demas (main too large). el main es simplemente un while(1);

No deberia tener codigo casi el main solo la configuracion, la asignacion de tareas, activacion del RTOS y un while sin nada, es mas creo que si se ejecuta ese while es por que no esta realmente activo el RTOS.

Todo esto suponiendo que estes usando un RTOS mas que obvio.
« Última modificación: 18 de Octubre de 2015, 16:17:08 por KILLERJC »

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 187
Re:#INT_RB Problema al declararle su funcion
« Respuesta #3 en: 18 de Octubre de 2015, 18:30:43 »
No entiendo lo que dices gera eso ya lo hize en la linea 11
#INT_RB //CAMBIO DE ESTADO ENTRE RB4 - B7
//Error si pongo aqui void RB_isr() //función de interrupción*

Solo se que RTOS esta vinculado a las interrupciones me meti aqui por esto pero todas las preguntas en las que me meti sobre #INT_RB No ablaban de ello Ni e visto seccion particular a ello que es lo que queria
El codigo tiene la ron del micro quemada y no queria liaros con el pero la interrupcion en si es muy corta no esta esigiendo nada en si (si es malo que sea larga malo malo porque eso es lo que deberia ser) y necesito que se ejecute de manera instantanea teniendo prioridad a cualquier otra cosa que este haciendo el programa
Corregirme esto si es asi por favor
Segun yo cuando B4-7 pase a true se interrumipira cualquier cosa que este haciendo el programa para ejecutar void RB_isr() esta es una funcion como otra cualquiera solo que se ejecuta si hay señal entre b4-b7 no porque el programa en si la llame en un determinado momento ¿este concepto es "true o false"?

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2034
Re:#INT_RB Problema al declararle su funcion
« Respuesta #4 en: 18 de Octubre de 2015, 18:40:14 »
gera se refiere a hacer esto:
Código: [Seleccionar]
#int_RB
void RB_isr() //función de interrupción
{
unsigned int8 valor=input_B();
valor=valor&0b00010000;
lcd_gotoxy(1,1);
if (valor>0){
output_high(PIN_a0);
lcd_putc("dentro");
}
else {
lcd_putc("no es b4"); }
delay_ms(1000);
output_low(PIN_a0);
clear_interrupt(INT_RB);
}

Y si no estas utilizando el RTOS abria que cambiar la ubicacion de la consulta.

Saludos
« Última modificación: 18 de Octubre de 2015, 18:50:40 por RALF2 »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6947
Re:#INT_RB Problema al declararle su funcion
« Respuesta #5 en: 18 de Octubre de 2015, 22:57:30 »
Citar
Solo se que RTOS esta vinculado a las interrupciones me meti aqui por esto pero todas las preguntas en las que me meti sobre #INT_RB No ablaban de ello Ni e visto seccion particular a ello que es lo que queria

Yo tambien asumi que se trataba de un RTOS, por el lugar donde estaba, aunque no veia exactamente donde habia configurado el RTOS en su programa. El lugar deberia haber sido :
Lenguaje C para microcontroladores PIC
Pero bueno, ya algun moderador lo va a mover.

Citar
El codigo tiene la ron del micro quemada y no queria liaros con el pero la interrupcion en si es muy corta no esta esigiendo nada en si (si es malo que sea larga malo malo porque eso es lo que deberia ser) y necesito que se ejecute de manera instantanea teniendo prioridad a cualquier otra cosa que este haciendo el programa

La interrupcion es justamente para eso, para que se ejecute al instante de que ocurrio. Pero tenes que tener en cuenta otros temas. Como dije cuando entra a una interrupcion se desactivan todas, hasta que salga que se activan nuevamente, si vos tenes 2 o mas interrupciones tu programa deberia ser Super rapido. Asi cuando ocurre la otra interrupcion es atendida por igual.
Si tenes una sola interrupcion, pero aun asi usas una base de tiempo, o capturas datos, o preguntas por una variable, etc en tu programa principal (main) vos queres que esto no se vea afectado por la interrupcion. Entonces nuevamente tu interrupcion debe durar poco.

No estoy hablando de largo en cantidad de instrucciones, sino largo en tiempo. La interrupcion se va a ejecutar de manera instantanea. Supongamos que en tu interrupcion actualizas valor y pones una variable a 1. Y en tu programa principal dentro del while preguntas si se puso a uno esa variable. Si es asi entonces mostras en el LCD. Estarias haciedno exactamente lo mismo que con tu interrupcion, nomas que la interrupcion duraria mucho menos. Y para vos como las instrucciones se ejecutan cada 1us seria lo mismo que se hiciera simultaneamente ( si es que esta bien programado )

Citar
Segun yo cuando B4-7 pase a true se interrumipira cualquier cosa que este haciendo el programa para ejecutar void RB_isr() esta es una funcion como otra cualquiera solo que se ejecuta si hay señal entre b4-b7 no porque el programa en si la llame en un determinado momento ¿este concepto es "true o false"?

En parte si. Es correcto que solo va a ejecutarse esa funcion cuando se produzca la interrupcion, es decir NO deberias llamarla desde ninguna otra funcion.
Lo que no es correcto es el funcionamiento de la interrupcion. Esa interrupcion actua ante el cambio. Es decir, si pasa de 1 a 0 , o de 0 a 1 cualquier entrada de las RB4 a RB7. Asi que tenes que tener en cuenta que cuando la entrada pasa de 1 a 0, tambien entraria en la interrupcion y no solamente cuando pasan a 1.

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 187
Re:#INT_RB Problema al declararle su funcion
« Respuesta #6 en: 19 de Octubre de 2015, 16:41:17 »
Voy a tener que quitar alguna aplicacion porque sigo necesitando acortar funcion mensaje(); para compilar (ron 94%)
pero inicialmente esto a hecho bingo solo e modificado el principio pero responde

void recoge();//tengo que ponerla antes que void RB_isr() para que el compilador la reconozca
#INT_RB
void RB_isr() //función de interrupción

unsigned int8 valor=input_B();
valor=valor&0b00010000;
if (valor>0) { recoge(); }//solo me interesa cuando haya señal en b4
}

No veo porque una funcion tenga que llamar a otra sin mas cambios cuando quite todos los recoge() la pondre dentro de RB_isr()
la interrupcion es para que pic1_slave lea lo que le pide pic2_master pasara lo mismo en la combersion cuando pic2_slave

Código: [Seleccionar]
//////////////////RECOGE //lee lo que le pida micro2 master
void recoge(){
output_low(PIN_C6);///S.envio  0 = pic2_B7_MASTER/E.envio
output_high(PIN_C1);//RS TRUE
int8 co;
int1 muta=0;
//while (Input(PIN_C0)==0) { }
//while(!spi_data_is_in()){ }
//AMBOS While son de los que me queria librar cuando micro es slave pierde todo el tiempo encerrado aqui y tiende a dar error
//sin hacer nada ahora ya es tarde no se me ocurre que puede hacer micro mientras sea slave*
output_high(PIN_C1);//RS TRUE
grp2=spi_read();
protSlave(); 
grp3=spi_read();
protSlave();
if (grp2==1) {////**per 2 (estado-salidas pic1)
for (co=0;5>co;co++){
ladra[co]=spi_read();   
protSlave();
}
}////**per 2
if (grp3==1) {////**per 3
peti=spi_read();// int8 peti
protSlave();
salir=spi_read();// salir
protSlave();
cliente=spi_read();// cliente
protSlave();
target[cliente]=spi_read();// int1 targe[ ] 
protSlave();
tarje=spi_read();// int1 tarje   
protSlave();
union UNI M32;//int32 mony
   for(co=0;co<4;co++){
      M32.bytes[co] = spi_read();   
      protSlave(); }
mony=M32.dat32;
}////**per 3
muta=spi_read();// *cliente
output_high(PIN_C6);//S.envio=true -----> pic2_b7_MASTER/E.envio
if (grp2==1) {
if (ladra[0]) { output_high(PIN_a0); } else { output_low(PIN_a0); } delay_ms(1); //delay_ms(2);
if (ladra[1]) { output_high(PIN_a1); } else { output_low(PIN_a1); } delay_ms(1);
if (ladra[2]) { output_high(PIN_a2); } else { output_low(PIN_a2); } delay_ms(1);
if (ladra[3]) { output_high(PIN_a3); } else { output_low(PIN_a3); } delay_ms(1);
if (ladra[4]) { output_low(PIN_a4);  } else { output_high(PIN_a4);  } delay_ms(1);//neg
} else {
delay_ms(5); }
delay_ms(2);
output_low(PIN_C6);
output_low(PIN_C1);//RS FIN
if (muta) { COMBERSION(1);  delay_ms(16); }
}
///////////////REFRESCO///////////////REFRESCO///////////////REFRESCO///////////////REFRESCO///////////////REFRESCO
void refresco(int1 muta,int1 gp1,int1 gp2,int1 gp3){//,int1 gp4){//,int1 gp5){
int8 co;
falloMF=0;
output_low(PIN_c6);//S.envio incial 0
output_high(PIN_C2);//RW TRUE
spi_write(gp1);/////ESTO es una perdida de tiempo si se kieren comunicar todos los datos........
///////output_high(PIN_c6);
//delay_ms(2);//TIEMPO
protMaster();
spi_write(gp2);
protMaster();
spi_write(gp3);///gp3 acava realmente escrita en gp[2] de savle
protMaster();
if (gp1==1) {//**per PERO si gp1==false se ahorra tiempo master y sable sabran que no es necesario comunicarse los datos del "grupo 1"
for (co=0;5>co;co++){
spi_write(ladra[co]);//int1 
protMaster();
}
}//**per 3
if (gp2==1) {//**per 3
spi_write(salir); /// int8 salir
protMaster();
spi_write(tarje); /// int1 tarje
protMaster();
union UNI M32;//int32 mony                         
M32.dat32 =mony;
     for(co=0;co<4;co++) {
      spi_write(M32.bytes[co]);
      protMaster();  }
}//**per 3
if (gp3==1) {//**per 3
spi_write(nume);//int8
protMaster();
spi_write(target[nume]);//int1 
protMaster();
}//**per 3
spi_write(peti); /// int8 peti
protMaster();
spi_write(muta);//
protMaster();
output_low(PIN_c2);//RW FIN
if (muta) { COMBERSION(0); } else { delay_ms(20);  }
}

 

*Los programas estan hechos de tal forma que cuando un micro era slave se pasava todo el tiempo encerrado en recoge() sin hacer nada ahora ya es tarde no se me ocurre que puede hacer micro mientras sea slave*

Es bueno ver que mediante interrupcion el slave pueda hacer cualquier cosa asta que se le interrumpa pero veo una pega
digamos que pic1_slave esta dentro de una operacion esta es demasiado importante como para avandonarla sin mas es necesario que trabaje todas las operaciones antes de entrar en  RB_isr() ¿Como solucionais vosotros esto? a mi solo se me ocurre interrumpir a pic2_master de nuevo sin que haga nada

Citar
Lo que no es correcto es el funcionamiento de la interrupcion. Esa interrupcion actua ante el cambio. Es decir, si pasa de 1 a 0 , o de 0 a 1 cualquier entrada de las RB4 a RB7. Asi que tenes que tener en cuenta que cuando la entrada pasa de 1 a 0, tambien entraria en la interrupcion y no solamente cuando pasan a 1.

Lo que e probado siempre coincide a 1 por eso puse esto
ext_int_edge(l_to_h);//alto

clear_interrupt(INT_RB);
enable_interrupts(int_RB);
enable_interrupts(global);
 set_tris_b(0b00011111);
while(true){///WIL main()
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);//Esto es lo primero nada mas empezar
} }

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6947
Re:#INT_RB Problema al declararle su funcion
« Respuesta #7 en: 19 de Octubre de 2015, 18:48:06 »
Si la ROM esta al 94% o se busca otro micro o se mejora el programa, no queda otra.

Acerca de la interrupcion, me autocito:

Citar
nuevamente tu interrupcion debe durar poco.

y el spi_read() es bloqueante.

Si queres ahorrar un poco mas de memoria, podrias usar el FAST_IO, lo que si vas a tener que definir los tris. Probaria con eso, ya que son 4/5 lineas de programa y seguro que te va a quitar bastante segun lo que tengas que hacer.
« Última modificación: 19 de Octubre de 2015, 19:32:48 por KILLERJC »

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re:#INT_RB Problema al declararle su funcion
« Respuesta #8 en: 19 de Octubre de 2015, 19:22:49 »
Si estás corto de memoria, una buena opción es el PIC18F452. Tiene 32 KB de ROM y 1536 B de RAM, contra 14 KB y 368 B del 877.
Dependiendo del PIC, podes tener interrupciones simultáneas. Hay algunos que permiten definir prioridades de interrupciones, de modo que una interrupción de mayor prioridad podrá interrumpir a una de menor, pero no al revés. Por ejemplo, el pic18f452 soporta 2 niveles de prioridad para cada interrupción (alta, y baja)

Saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 187
Re:#INT_RB Problema al declararle su funcion
« Respuesta #9 en: 20 de Octubre de 2015, 17:31:24 »
Citar
una buena opción es el PIC18F452.
Si es por la memoria Tiene buena pinta me coinciden todos los pin pero quizas tenga que mirar de que va FAST_IO Todo el proyecto esta creado para tratar con pic16 por lo demas me estoy biendo bien con una sola interrupcion por esto la e cambiado por #INT_EXT esto apenas me a esigido modificar nada Lo que me a creado cierta confusion al adentrarme en el programa esta tarde es que lo que era antes la funcion recoge() Esta no esta de una manera visible en el codigo y se cumple de manera fantasmal si no tienes cuidado

Saludos


 

anything