Autor Tema: Error en strtok ccs 5, pic 16f876a  (Leído 3575 veces)

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

Desconectado claudiovega

  • PIC10
  • *
  • Mensajes: 31
Error en strtok ccs 5, pic 16f876a
« en: 02 de Julio de 2015, 13:49:05 »
Hola, tengo un programa que al momento de probarlo con isis proteus arroja un error en la función strtok. Conozco muy poco de debug como para averiguar que produce el error.
Estoy trabajando con el pic 16f876a, el programa lee por el puerto serial un comando como este: ITG0001|OPEN|00S00S00S00S00S00S00S00S01S00S01S00S00S00S# que luego es separado en 3 partes (tokens) usando como separador la barra |.
Pongo aqui el codigo y la simulacion en isis. Además un pantallazo del error.

Código: [Seleccionar]
#include <16F876A.h>
#include <stdlib.h>

#FUSES NOWDT, XT, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT, HS   

#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, STREAM=COM_A, parity=N, bits=8)

char p, term[2], command[66] = "", action[10] = "", values[45] = "", picid[10] = "";
char picsaved[8] = "", permited[9] = "";
short newcommand = 0;
int k = 0;
int32 seconds[14], times[14], epoch;
int contador1 = 0;
int1 newsecond=0;

// subrutina de interrupción del timer1
#int_TIMER1                               
void TIMER1_isr(){             
disable_interrupts(INT_TIMER1);
contador1++;
if(contador1 == 1500){
newsecond = 1;
contador1 = 0;
}          
set_timer1(63936);
enable_interrupts(INT_TIMER1);
}

#INT_RDA
void usart_modem(void)

disable_interrupts(INT_RDA);
newcommand = 0;
if (kbhit(COM_A))
{
p = fgetc(COM_A);
if(p == '#') {
command[k] = '\0';
newcommand = 1;
k = 0;
}else{
command[k] = p;
k++;
}
}
enable_interrupts(INT_RDA);
}

int is_equal(char *p1, char *p2)
{
int *p3;
p3 = strstr(p1,p2);
return (p3);
}

void open(void)
{
int i, j=0;
char numbers[3] = "", letter;
unsigned char number;

for(i = 0; i < strlen(values); i += 3){
numbers[0] = values[i];
numbers[1] = values[i+1];
numbers[2] = '\0';
letter     = values[i+2];
number     = atoi(numbers);
if(letter == 77) number *= 60;
seconds[j] = number;
times[j]   = epoch;
j++;
}
if(seconds[0]  > 0) output_bit(PIN_C0, 1);
if(seconds[1]  > 0) output_bit(PIN_C1, 1);
if(seconds[2]  > 0) output_bit(PIN_C2, 1);
if(seconds[3]  > 0) output_bit(PIN_C3, 1);
if(seconds[4]  > 0) output_bit(PIN_B7, 1);
if(seconds[5]  > 0) output_bit(PIN_B6, 1);
if(seconds[6]  > 0) output_bit(PIN_B5, 1);
if(seconds[7]  > 0) output_bit(PIN_B4, 1);
if(seconds[8]  > 0) output_bit(PIN_B3, 1);
if(seconds[9]  > 0) output_bit(PIN_B2, 1);
if(seconds[10] > 0) output_bit(PIN_B1, 1);
if(seconds[11] > 0) output_bit(PIN_B0, 1);
if(seconds[12] > 0) output_bit(PIN_C5, 1);
if(seconds[13] > 0) output_bit(PIN_C4, 1);
}

void close(void)
{
if(values[0]  > 0) output_bit(PIN_C0, 0);
if(values[1]  > 0) output_bit(PIN_C1, 0);
if(values[2]  > 0) output_bit(PIN_C2, 0);
if(values[3]  > 0) output_bit(PIN_C3, 0);
if(values[4]  > 0) output_bit(PIN_B7, 0);
if(values[5]  > 0) output_bit(PIN_B6, 0);
if(values[6]  > 0) output_bit(PIN_B5, 0);
if(values[7]  > 0) output_bit(PIN_B4, 0);
if(values[8]  > 0) output_bit(PIN_B3, 0);
if(values[9]  > 0) output_bit(PIN_B2, 0);
if(values[10] > 0) output_bit(PIN_B1, 0);
if(values[11] > 0) output_bit(PIN_B0, 0);
if(values[12] > 0) output_bit(PIN_C5, 0);
if(values[13] > 0) output_bit(PIN_C4, 0);
}

void auto_off(void)
{
if(seconds[0]  > 0 && (epoch - times[0])  > seconds[0])  output_bit(PIN_C0, 0);
if(seconds[1]  > 0 && (epoch - times[1])  > seconds[1])  output_bit(PIN_C1, 0);
if(seconds[2]  > 0 && (epoch - times[2])  > seconds[2])  output_bit(PIN_C2, 0);
if(seconds[3]  > 0 && (epoch - times[3])  > seconds[3])  output_bit(PIN_C3, 0);
if(seconds[4]  > 0 && (epoch - times[4])  > seconds[4])  output_bit(PIN_B7, 0);
if(seconds[5]  > 0 && (epoch - times[5])  > seconds[5])  output_bit(PIN_B6, 0);
if(seconds[6]  > 0 && (epoch - times[6])  > seconds[6])  output_bit(PIN_B5, 0);
if(seconds[7]  > 0 && (epoch - times[7])  > seconds[7])  output_bit(PIN_B4, 0);
if(seconds[8]  > 0 && (epoch - times[8])  > seconds[8])  output_bit(PIN_B3, 0);
if(seconds[9]  > 0 && (epoch - times[9])  > seconds[9])  output_bit(PIN_B2, 0);
if(seconds[10] > 0 && (epoch - times[10]) > seconds[10]) output_bit(PIN_B1, 0);
if(seconds[11] > 0 && (epoch - times[11]) > seconds[11]) output_bit(PIN_B0, 0);
if(seconds[12] > 0 && (epoch - times[12]) > seconds[12]) output_bit(PIN_C5, 0);
if(seconds[13] > 0 && (epoch - times[13]) > seconds[13]) output_bit(PIN_C4, 0);
}

/* Programa principal */
void main(void)
{
// Activo todos los pines B como salidas
set_tris_b(0b00000000);
// Activo PIN_C4 y PIN_C7 como entradas
set_tris_c(0b10010000);

// Todos los pines B y C apagados, excepto los que son entradas
output_B(0b00000000);
output_bit(PIN_C0, 0);
output_bit(PIN_C1, 0);
output_bit(PIN_C2, 0);
output_bit(PIN_C3, 0);
output_bit(PIN_C4, 0);
output_bit(PIN_C5, 0);

setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
set_timer1(63936);                   

// Activo interrupciones
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER1);

epoch = 0;
strcpy(picsaved, "ITG0001");

while(TRUE)
{
if(newsecond)
{
epoch++;
auto_off();
newsecond = 0;
}

if(newcommand)
{
newcommand = 0;

strcpy(term, "|");
strcpy(picid, strtok(command, term));
strcpy(action, strtok(0, term));
strcpy(values, strtok(0, term));

if(is_equal(picid, picsaved))
{
strcpy(permited, "OPEN");
if(is_equal(permited, action))
{
open();
printf("%s opened\r\n", picid);
}
strcpy(permited, "CLOSE");
if(is_equal(permited, action))
{
close();
printf("%s closed\r\n", picid);
}
}
}
}
}

Desconectado RodrigoAndres

  • PIC16
  • ***
  • Mensajes: 171
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #1 en: 06 de Julio de 2015, 15:59:27 »
es un error muy raro, te recomiendo ke busques esa funcion strtok por internet y la reemplases, talves la ke trae el ccs esta dañada

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #2 en: 06 de Julio de 2015, 16:38:24 »
Con respecto al problema, probaste cambiarle aca:

Código: C
  1. strcpy(term, "|");
  2.                         strcpy(picid, strtok(command, term));
  3.                         strcpy(action, strtok(0, term));
  4.                         strcpy(values, strtok(0, term));

ese term , por un '|' , observa que puse comillas simples y estoy diciendo que no uses un strcpy, ya que "|" es lo mismo que {'|','\0'}, y tal ves buscando eso no pueda,no se se me ocurre eso nomas , quedandote:

Código: C
  1. strcpy(picid, strtok(command, '|'));
  2.                         strcpy(action, strtok(0, '|'));
  3.                         strcpy(values, strtok(0, '|'));


Sino podes crear tu propia funcion, Creo que un uos while + copiar las cosas haria masomenos simple la operacion.

Jugando para ver como lo podia hacer, sin optimizarlo ni nada:

Código: C
  1. void separar_valores(char *arrayfinal, char *arrayinicial, char delimitador)
  2. {
  3.         char dest = arrayinicial;                                       // Guardo el valor inicial del array
  4.         while(*arrayinicial!=delimitador || *arrayinicial!='\0')        // Copio la parte hasta que encuentro mi token ( delimitador )
  5.         {
  6.                 *arrayfinal=*arrayincial;
  7.                 arrayfinal++;
  8.                 arrayinicial++;
  9.         }
  10.         *arrayfinal='\0';                                               // Termino mi string con un caracter nulo
  11.         if(*(arrayinicial-1)==delimitador)                              // Se termino el string ?, si sigue ( hay un delimitador) muevo todos los caracteres asi comienza
  12.         {                                                               // Sin el delimitador y sigue por lo demas
  13.                 while(*arrayinicial!='\0')
  14.                 {
  15.                         *dest = *arrayinicial;
  16.                         arrayinicial++;
  17.                         dest++;
  18.                 }
  19.         }
  20.         *dest='\0';                                                     // Sea como sea, si habia un delimitador o un caracter nulo, cierro el string
  21. }

Y de utilizarlo se haria:

Código: C
  1. separar_valores(picid,command,'|');
  2. separar_valores(action,command,'|');
  3. separar_valores(values,command,'|');

Desconectado RodrigoAndres

  • PIC16
  • ***
  • Mensajes: 171
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #3 en: 06 de Julio de 2015, 17:11:19 »
si, el tiene razon rambien se pude aser asi

Desconectado claudiovega

  • PIC10
  • *
  • Mensajes: 31
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #4 en: 30 de Julio de 2015, 16:03:16 »
Hola, gracias por la respuestas.
Me di cuenta que el error se producía en la última llamada a strtok(), dado que no había un símbolo | al final. Es decir, al enviar un comando así: ITG0001|OPEN|00S00S00S00S00S00S00S00S01S00S01S00S00S00S|# ya no se produce el error.
Creía que ese error hacía que el PIC se bloqueara (hay que resetearlo para volver a funcionar normalmente), pero no es así, solucionado el error aun el pic se bloquea.
Al diseñar la tarjeta mis compañeros electrónicos (yo soy informático y no se nada de eso) no pusieron ninguna protección al pic (protección contra ripple), dado que en una tarjeta anterior muy parecida no usan ninguna y funciona muy bien.
En la tarjeta anterior la salida del pic pasa a un ULN y luego a un transistor que hace el switch a 12 volts para activar unas camaras de video; en la tarjeta nueva la salida va a un ULN y luego a un relay que abre el circuito de 12 volts para activar unos motores de 12 volts. La principal diferencia imagino yo, será el amperaje, que en los motores es mucho mas alto.
¿Pueden darme ideas de donde buscar la causa que provoca el bloqueo del PIC?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #5 en: 30 de Julio de 2015, 23:19:47 »
No creo que se bloquee por eso, pero si que se resetee, podrias mirar la tension de entrada si es que baja en algun momento, de tal forma que resetee el micro. Pero bloquearlo no. Podrias probar tambien poner los motores lejos de la placa para ver si son estos los que lo influyen

Desconectado claudiovega

  • PIC10
  • *
  • Mensajes: 31
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #6 en: 10 de Agosto de 2015, 13:02:23 »
Hola, creo que finalmente he encontrado el problema.
No es un error de hardware (ruido o cosas así), no es un error en el software ni en la comunicación. Se ha resuelto cambiando el PIC, de 16F876A a 18F2550.
Con el PIC anterior iba muy justo de memoria, el programa ocupaba el 92%, ahora ocupa 17% en el nuevo PIC.
Se me ocurre la siguiente explicación: al recibir los comandos el PIC se queda sin memoria y se comienza a corromper la memoria de programa hasta hacer que se bloquee.
« Última modificación: 10 de Agosto de 2015, 13:38:07 por claudiovega »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #7 en: 10 de Agosto de 2015, 13:14:18 »
Puede ser por que la memoria que "sobra" es usada por C en su stack, y no se si existe una proteccion contra un stack overflow desde C al no esta limitado el stack.

Desconectado claudiovega

  • PIC10
  • *
  • Mensajes: 31
Re: Error en strtok ccs 5, pic 16f876a
« Respuesta #8 en: 10 de Agosto de 2015, 13:40:11 »
En la simulación con isis proteus nunca se dió el problema, sometido al mismo trabajo. Quizá la simulación no toma en cuenta los límites de memoria.