Hola Amigos, tengo una pequeña duda y quisiera consultarlo con uds ya que siempre me saco las dudas con esta pagina sin escribir absolutamente y ahora me encuentro en el problema no encuentro este tema profundizado en ninguna lado. Aqui va: estoy haciendo un proyecto usando el PIC18F14K50 elegido principalmente por su precio sin tener en cuenta la memoria que tenia y luego avanzando mas en el proyecto me di cuenta de que si era un problema la memoria, porque necesitaba tener Buffer de los datos(de 127 caracteres c/u) provenientes de dos fuentes(USB y RS232) y cuando grabo ya me dice que tengo el 98% de la memoria ocupada y todavia me faltan muchas variables por usar. Entonces opte por no reservar la memoria directamente sino que a medida que la necesita la creaba, esto lo hacia con las estructuras dinamicas, pero aca mi problema fue que al usar 50 datos me quede sin memoria y ahi si que no entedi que paso, di mil vueltas tratando de resolver esto y nada... les paso el codigo y le comento cual es el proyecto. En este proyecto tengo que pasar de USB a RS232 y antes de convertir de nivel, tengo que ademas hacer una traducción de las instrucciones ya que las instrucciones provenientes del RS232 no las entiende la PC y viceversa (USB se conecta a PC y RS232 a un Hardware X). En este codigo que le paso solo es un rs232 a usb y viceversa, lo que quisiera que me expliquen es porque con tan pocos datos se me acaba la memoria... Bueno si saben algo al respecto me ayudan por favor Gracias.
Codigo:
#INCLUDE <EDD.h>
TYPEDEF STRUCT NODO
{
INT8 DATO;
STRUCT NODO *ENLACE;
}LISTA;
VOID MandoDatos(VOID); //Funcion que se encarga de mandar los datos ya se por USB o por RS232
VOID TratoUsb(VOID);
VOID TratoUART(VOID);
VOID LIBEROMEM(LISTA *P);
BOOLEAN MandoDato=FALSE;
INT8 BufferPC;
INT8 BufferImp;
INT8 TIMER=0; //Contador de tiempo, cuando llega a 4 quiere decir que pasó un segundo.
BOOLEAN DatoUSB=false; //Bandera que indica que hay datos del USB.
BOOLEAN DatoUART=false; //Bandera que indica que hay datos del USB
LISTA *BASE;
LISTA *BASE1;
BOOLEAN MEM=TRUE;
INT8 BUFFERAUX;
//***************************Rutina Principal***********************************************
VOID MAIN() {
//********* CONFIGURAR EL TIMER 0 E INICIALIZO EL PUERTO USB************//
SETUP_TIMER_0 ( RTCC_INTERNAL | RTCC_DIV_64 ) ; //
SET_TIMER0 ( 18662 + GET_TIMER0 ( ) ) ;//Timer 0 cada 250ms
ENABLE_INTERRUPTS(INT_RTCC);
OUTPUT_LOW(LV); // enciendo el led rojo y q aun no detecta el host
OUTPUT_HIGH(LR);
USB_CDC_INIT();
USB_INIT(); // Inicializamos el USB.
USB_TASK(); //Habilita periferico usb e interrupciones
USB_WAIT_FOR_ENUMERATION(); //Esperamos hasta que el PicUSB sea configurado por el host
OUTPUT_TOGGLE(LR); //Indicamos que el PIC fue enumerado.
OUTPUT_HIGH(LV);
// ************************** INICIO DEL PROGRAMA *************************************
WHILE(!USB_CDC_CONNECTED()){} // Espera a detectar una transmisión de la PC (Set_Line_Coding).{}
WHILE (TRUE)
{
USB_TASK();
IF(USB_ENUMERATED())
{
IF (USB_CDC_KBHIT()){ //Pregunto si hay un dato proveniente del USB
LISTA *P,*Q;
BASE=NULL;
P=NULL;
Q=NULL;
P=(STRUCT NODO *)MALLOC(SIZEOF(*P));
BASE=P;
BufferPC=USB_CDC_GETC();
(*P).DATO=BufferPC;
(*P).ENLACE=NULL;
WHILE(USB_CDC_KBHIT() && MEM){
BufferPC=USB_CDC_GETC();
Q=(STRUCT NODO *)MALLOC(SIZEOF(*P)); //RESERVO UN LUGAR DE MEMORIA PARA ESTE ULTIMO DATO
IF(Q==NULL){
printf(usb_cdc_putc, "NO HAY MAS MEMORIA");
BUFFERAUX=BUFFERPC;
MEM=FALSE;
}
ELSE{(*P).ENLACE=Q; //HAGO EXACTAMENTE LOS MISMO QUE EN EL ANTERIOR SOLO QUE ACA EN EL PENULTIMO
P=Q; //DATO(P1) APUNTO HACIA ESTE
(*P).DATO=BufferPC;
}
}
(*P).ENLACE=NULL;
DATOUSB=TRUE;
}
IF(DatoUSB){
TratoUsb();
}
IF(KBHIT()){ OUTPUT_TOGGLE(LR);
LISTA *P,*Q;
BASE1=NULL;
P=NULL;
Q=NULL;
P=(STRUCT NODO *)MALLOC(SIZEOF(*P));
BASE1=P;
BUFFERIMP=GETC();
(*P).DATO=BUFFERIMP;
(*P).ENLACE=NULL;
WHILE(KBHIT()){
BUFFERIMP=GETC();
Q=(STRUCT NODO *)MALLOC(SIZEOF(*P)); //RESERVO UN LUGAR DE MEMORIA PARA ESTE ULTIMO DATO
IF(Q==NULL){
printf(usb_cdc_putc, "NO HAY MAS MEMORIA");
BUFFERAUX=BUFFERIMP;
MEM=FALSE;
}
ELSE{(*P).ENLACE=Q; //HAGO EXACTAMENTE LOS MISMO QUE EN ELANTERIOR SOLO QUE ACA EN EL PENULTIMO
P=Q; //DATO(P1) APUNTO HACIA ESTE
(*P).DATO=BUFFERIMP;
}
}
(*P).ENLACE=NULL;
DatoUART=TRUE;
}
IF (DatoUART ){
TratoUART();
}
IF(MandoDato){
MandoDatos();
}
}
}
}
//************************************************Funciones*********************************************
//**********************Rutina encargada de enviar los datos vis USB o RS232****************************
VOID MandoDatos(){
WHILE(MandoDato){LISTA *P;
IF (DatoUSB){P=BASE; //Si los datos provienen del USB los envio hacia la PC, en el caso de que
DO{ //no haya tratamiento de datos se cuantan los datos que llegaron, para ser enviados
USB_CDC_PUTC ((*P).DATO); //nuevamente la misma cantidad pero por el puerto RS232. Si este no es el caso solo
PUTCHAR(*P.DATO); //mando los comando necesarios.
P=(*P).ENLACE;
DELAY_MS(1);
}WHILE(P!=NULL); //
IF (!MEM){
USB_CDC_PUTC (BUFFERAUX);
MEM=TRUE;
}
LIBEROMEM(BASE);
DatoUSB=FALSE;
MANDODATO=FALSE;
}
IF (DatoUART) //Lo mismo que el caso anterior salvo que es en el sentido opuesto
{P=BASE1;
DO{ //no haya tratamiento de datos se cuantan los datos que llegaron, para ser enviados
USB_CDC_PUTC ((*P).DATO); //nuevamente la misma cantidad pero por el puerto RS232. Si este no es el caso solo
//PUTCHAR(*P.DATO); //mando los comando necesarios.
P=(*P).ENLACE;
}WHILE(P!=NULL); //
IF (!MEM){
USB_CDC_PUTC (BUFFERAUX);
MEM=TRUE;
}
LIBEROMEM(BASE1);
DatoUART=FALSE;
MANDODATO=FALSE;
}
}
}
//**********************************Rutina de interpretacion del comando que llego de los Datos********************************************
//
VOID TratoUsb(VOID){
Switch((*BASE).DATO){ //Indentifico el comando y luego lo trato
CASE 0x1f:
MANDODATO=TRUE;
BREAK;
DEFAULT: MANDODATO=TRUE;
}
}
VOID TratoUART(VOID){
Switch((*BASE).DATO){ //Indentifico el comando y luego lo trato
CASE 0x01:
MANDODATO=TRUE;
BREAK;
DEFAULT: MANDODATO=TRUE;
}
}
VOID LIBEROMEM(LISTA *P){ //EN ESTA RUTINA INTENTO LIBERAR LA MEMORIA DE LOS DATOS Q GUARDE
LISTA *P1;
P1=P;
WHILE((*P1).ENLACE!=NULL){
P=(*P).ENLACE;
FREE(P1);
P1=P;
}
FREE(P1);
}
//******************************************Interrupciones***************************
#INT_RTCC //
void RTCC_isr(VOID) //Interrupción TMR0
{
SET_TIMER0 ( 18662 + GET_TIMER0 ( ) ) ;
TIMER++;
IF ( TIMER == 4 ) //Tiene que entrar 4 veces para que sea un segundo
{
TIMER = 0;
IF ( USB_CDC_CONNECTED()){
OUTPUT_TOGGLE(LV);}
IF (!USB_ENUMERATED()){
OUTPUT_TOGGLE(LV);}
}
}