PicManía by RedRaven
 

Búsqueda personalizada

El Rincón del CCS C - Parte

 

  El lenguaje C es el que uso por defecto para el 90% de mis programas. Aquí os muestro algunos ejemplos de cómo hacer cosas con este idioma. Todos ejemplos que se muestran en esta sección se han realizado usando el PCW PICC de CCS (Veriones 3.242 a 4.096 según depende)

Más CCS C : 1 2 3 4
Índice Parcial:
 

 


Controlando un SERVO con el PIC desde nuestro PC
(O todo lo que siempre quiso saber sobre los Servomotores y nunca se atrevió a preguntar)


   Pero como decía Jack El Destripador: ¡Vayamos por partes!

   Y para empezar un poco de teoría, que a ninguno de nosotros nos va a venir mal. Un Servomotor es un cacharro, entre otros muchos, que puede manejarse inyectándole un señal PWM.

   Y si me preguntáis qué es esto os respondo que es método de control que consiste en enviar un tren de pulsos, cada uno de ellos con un periodo de tiempo en alto, a 5V, y otro en bajo, a 0V; separados cada uno del siguiente un tiempo constante y que podemos variarle la respectivas duraciones que permanece en alto y bajo, o como su propio nombre indica: Pulse Width Modulation, que dicho para entendernos significa Modulación de Ancho de Pulso.

   Un Servo es un motor controlado por una electrónica que lee el PWM y que se encarga de mover al motor dependiendo de lo que ha leído.

   El Servo, o mejor dicho la electrónica del Servo coloca al motor en cada posición dependiendo del tiempo en que el pulso que le inyectamos permanece en alto. Si el tiempo que dura pulso en estado alto dura exactamente 1.5 milisegundos entonces el Servo se coloca en el centro de su recorrido, si el pulso dura exactamente 0.5 milisegundos el servo retrocede desde el punto medio unos 90º y se coloca en su extremo izquierdo y si, por último, el pulso dura exactamente 2.5 milisegundos el servo avanza desde el punto medio unos 90º y se coloca en su extremo derecho. Al tiempo en que permanece en alto un pulso le llamamos Duty Cicle.

   Con duraciones intermedias del tiempo en que permanece el pulso en alto, o sea: con distintos Duty Cicle, el Servo se posiciona en puntos intermedios de su recorrido. Para que el servo responda correctamente deben llegarle al servo los pulsos con una periodicidad, o frecuencia, constante, uno tras otro, separados 20 milisegundos cada uno uno del siguiente, cada flanco de subida debe estar separado del siguiente flanco de subida los mismos 20 milisegundos; por lo tanto cada ciclo alto-bajo dura siempre exactamente 20 milisegundos y lo que variamos es la relación entre el tiempo que está en alto y en bajo.

   Decir que los pulsos están separados unos de otros 20 milisegundos es exactamente lo mismo que decir que se envían con una frecuencia de 50 Hertzios, ya que 50 hz son 50 pulsos por segundo y por lo tanto 1000 milisegundos (que tiene un segundo) dividido entre 50 son exactamente eso: 20 milisegundos. f (frecuencia en Hertzios) = 1 / t (Periodo en Segundos).

   En el fondo todo este asunto no es distinto de encender y apagar nuestro famoso led, que es algo por lo que empezamos todos cuando comenzamos a trastear con los PIC's, pero controlando muy exactamente los tiempos durante los que que está encendido y apagado.

   Esto podemos verlo mas fácil y claro en la imagen esquema siguiente:
 

 

   Ahora lo que tenemos que hacer es saber cómo podemos controlar estos tiempos en nuestro PIC para poner en alto (disparar el pulso) y en bajo (apagarlo) siguiendo la tabla de tiempos descrita mas arriba.

   Para ello voy a echar mano del socorrido TIMER0 del PIC que nos va a servir de reloj para saber cuándo y durante cuánto tiempo tengo que tener mi pulso en alto. Como soy el mas listo de la clase he elegido un divisor, o Preescaler, del TIMER0 de 1:16 (mas adelante os contaré el por qué de este divisor). El TIMER0 funcionando a 1:16 hace saltar la Interrupción por Desbordamiento de Timer, también conocida como RTCC, cada 4.096 milisegundos.

   Esto es lo mismo que decir que TIMER0 tarda 4.096 milisegundos en contar desde 0 a 255 y que al llegar a 255 pasar de nuevo a 0 hace saltar la RTCC.

   Esto significa que cada paso de contador del TIMER0, a lo que vamos a llamar un tick de reloj, tarda 4.096 / 256 = 0.016 milisegundos. Esto me da una pauta bastante fácil de calcular que consiste en que cada 5 RTCC completas tengo 5 * 4.096 = 20.48 milisegundos que es un poco más de lo que necesito, que son 20 milisegundos exactos.

   Esto lo podemos conseguir contando 4 RTC's completas, a 4.096 milisegundos cada una, y otra más un poco mas corta. No podemos hacer que la RTCC se acabe antes de la cuenta, pero si que podemos, y es lo que vamos a hacer, que no empiece a contar desde 0 sino desde 30: esto se explica porque 30 * 0.016 = 0.48 milisegundos menos que va contar esta última RTCC al haber empezado desde un valor de 30 en lugar de 0, luego 4.096 - 0.48 = 3.616 milisegundos para la última RTCC.

   Concluyendo: tengo 4 RTCC's completas a 4.096 milisegundos y una capada a 3.616 luego 4 * 4.096 + 3.616 = 20 milisegundos. Lo que realmente voy a hacer es contar 1 RTC completa, 2 RTCC completas, 3 RTCC completas, 4 RTCC completas y pongo el contador de TIMER0 a 30, 5 RTCC completas luego ya han pasado 20 milisegundos exactamente.

   A estas 5 RTCC's les llamo flagRTCC que solo voy a activar cuando se completen las 5 RTCC's (4 completas y otra mas incompleta).

   Además sabiendo que cada tick de reloj ocupa 0.016 milisegundos podemos traducir los tiempos de anchos de pulsos descritos anteriormente en ticks de reloj: así 0.5 milisegundos son lo mismo que esperar 31 ticks de reloj, 1.5 milisegundos equivalen a 93 ticks de reloj y 2.5 milisegundos son 155 ticks de reloj. (Recuerda que un tick de reloj es el tiempo que tarda TIMER0 en contar exactamente 1, o sea 0.016 milisegundos)

   La imagen anterior podemos ahora convertirla en esta siguiente en las que hemos cambiado los tiempos por RTCC's y Ticks:
 


 

   Como vemos en el cronograma superior: cada vez que se produce un super RTCC, de 4 RTC's y pico a la que llamamos flagRTCC, ponemos en alto el PIN de la señal del Servo, debemos recordar que esto siempre va a ocurrir en el tránsito del contador TIMER0 entre los valores de 255 y 0, por lo que flagRTCC siempre va a coincidir con TIMER0=0.

   Ahora entonces solo debemos esperar el número suficiente de ticks para volver a poner nuestro PIN a bajo. Si deseamos que el Servo se posicione en su centro debemos mantener el PIN en alto durante 93 ticks de TIMER0 o, lo que es lo mismo, esperar 1.5 milisegundos para bajar el pulso.

   La secuencia queda entonces de la siguiente manera:
 

  • RTCC corre alocadamente, una tras otra, dedicándose exclusivamente a contar cuantas de ellas han pasado, si es la cuarta pone Timer0 a 30 para que la quinta sea mas corta, si es la quinta pone en alto flagRTCC para lo que sea necesario y comienza de nuevo.
     
  • En el programa principal detectamos que flagRTCC se ha activado así que lo desactivamos y ponemos en alto el PIN y marcamos, con flagSERVO1, que acabamos de activarlo.
     
  • A continuación, y siempre que flagSERVO1 esté activado, comprobamos el valor de TIMER0 que si es mayor que el que deseamos, en nuestro caso 93, y cuando lo alcancemos ponemos a bajo el PIN y lo marcamos desactivando flagSERVO1. Hemos acabado.
Cada 20 milisegundos activamos el pulso, y transcurridos 1.5 milisegundos lo desactivamos, que es exactamente lo que queríamos hacer.

El valor de TIMER0 con el comparamos para controlar la duración de cada pulso la tenemos guardada en tSERVO1, que inicialmente cargamos con el número de ticks necesarios para colocar el Servo en su punto medio, ticks_PULSO_MEDIO, y que podemos cambiar dinámicamente mediante la recepción de comandos a través de la RS232.

De esta forma con los comandos "1", "2" y "3" podemos cambiar el valor de tSERVO1 a ticks_PULSO_MINIMO, ticks_PULSO_MEDIO y ticks_PULSO_MAXIMO respectivamente; y con los comandos "+" y "-" vamos incrementando o decrementando su valor. Con "r" le pedimos al PIC que nos envíe su valor actual.

Ahora solo nos quedaría implementar todo esto en un programa en C que queda de la siguiente forma:
  Titulo  
  // servo_pwm_232

// Ejemplo con un servo FUTABA S3003
// Alimentación y pulsos a 5V
// Cuadro de Tiempos :
// Periodo 20 ms (Frecuencia 50 Hz)
// Ancho Pulso minimo 0.5 ms
// Ancho pulso medio 1.5 ms
// Ancho pulso maximo 2.5 ms
// TMR0 a 1:16 -> 1 RTCC cada 4.096 ms
// -> 1 Tick cada 0.096 / 256 = 0.016 ms
// -> 20 ms = (4 x RTCC completas) + (1 * RTCC - 30 ticks)
// Ancho Pulso minimo 0.5 ms -> 31 ticks de TMR0
// Ancho pulso medio 1.5 ms -> 93 ticks de TMR0
// Ancho pulso maximo 2.5 ms -> 155 ticks de TMR0

#include <16f876a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define PIN_SERVO1 PIN_B0

const int AJUSTE_FINO_DE_RTCC = 30;
const int ticks_PULSO_MINIMO = 31;
const int ticks_PULSO_MEDIO = 93;
const int ticks_PULSO_MAXIMO = 155;

int1 flagRTCC = 0;
int contRTCC = 0;
int1 flagSERVO1 = 0;
int tSERVO1 = ticks_PULSO_MEDIO;
char Keypress =0x00;

void eco_servos(void);
void ajusta_servo(void);

#int_rda
void rda_isr() {
  Keypress=0x00;
  if(kbhit()){
    Keypress=getc();
  }
}

#int_RTCC
RTCC_isr(){
  ++contRTCC;
  if(contRTCC==4){
    set_TIMER0(AJUSTE_FINO_DE_RTCC);
  }
  if(contRTCC==5){
    flagRTCC=1;
    contRTCC=0x00;
  }
}

void main() {

int ValTIMER0;

  setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
  enable_interrupts(int_rda);
  enable_interrupts(global);
  printf("\r\n\SERVO Commander\r\n\r\n" );
  eco_servos();
  set_TIMER0(0);
  enable_interrupts(INT_RTCC);
  do {
    // DISPARO DEL PULSO PWM
    if(flagRTCC==1){
      flagRTCC=0;
      output_high(PIN_SERVO1);
      flagSERVO1=1;
    }
    // CONTROL DE ANCHO DEL PULSO PWM
    if(flagSERVO1==1){
      valTIMER0 = get_TIMER0();
      if(valTIMER0>tSERVO1){
        flagSERVO1=0;
        output_low(PIN_SERVO1);
      }
    }
    // CONTROL DESDE LA RS-232
    if(Keypress!=0x00){
      ajusta_servo();
      Keypress=0x00;
    }
  } while (TRUE);
}

void ajusta_servo(void){

  switch(Keypress){
    // Periodos Prefijados
    case '1': tSERVO1=ticks_PULSO_MINIMO;
              break;
    case '2': tSERVO1=ticks_PULSO_MEDIO;
              break;
    case '3': tSERVO1=ticks_PULSO_MAXIMO;
              break;
    // Inc Dec Periodo
    case '+': if(++tSERVO1>ticks_PULSO_MAXIMO){
                tSERVO1=ticks_PULSO_MAXIMO;
              }
              break;
    case '-': if(--tSERVO1<ticks_PULSO_MINIMO){
                tSERVO1=ticks_PULSO_MINIMO;
              }
              break;
    // Dame Periodo actual
    case 'r': eco_servos();
              break;
  }
}

void eco_servos(void){
  printf("S=%u\r\n",tSERVO1);
}
 
 
 

Descargar servo_pwm_232.c

 


Como podéis ver en el comentario inicial del código, todo esto está montado para la familia de servos compatibles  FUTABA S3003, HiTec HS-300 CW, HOBBICO COMMAND CS-51,   que son de los mas usados por los aficionados al Radio control.

Para ajustar este código a otros servos solo hay que calcular el Preescaler y los ticks necesarios para ajustarse a las características de éste. Hay servos que funcionan a 400hz en lugar de 50hz y con anchos de pulso ligeramente distintos a los utilizados aquí. Es normal anchos de pulso en los extremos de 1.00 y 2.00 milisegundos respectivamente. El punto medio en 1.5 milisegundos es muy común.

Otro corolario de este ejemplito estriba en la posibilidad de manejar varios Servos. Utilizando la misma estructura de PIN_SERVO1 y tSERVO1 podemos habilitar el control indistinto de tantos servos como deseemos, teniendo así PIN_SERVO2 y tSERVO2, PIN_SERVO3 y tSERVO3 ... etc. controlando cada uno de ellos de forma absolutamente similar.
 

Haz Click sobre la imagen para verla a tamaño grande
 

 


Strings Demo o como se pueden manejar las cadenas en nuestro PIC
 
   Con mi insufrible manía de hacer la cosas lo mas difícil posible he montado una demo de este asunto de los strings mediante un "monitor rs232".

   Quiero decir que he hecho un programa que se comunica con el PC mediante la RS232 y que acepta comandos y argumentos de estos comandos para los ejemplos de algunas funciones ...

   Pero para poder hacer esto de los comandos, que en el fondo no es mas que procesar strings, he necesitado hacer uso de la mayoría de las funciones que estamos tratando de ejemplificar.

   El resultado ha sido plenamente satisfactorio ya que funciona perfectamente y a la vez ha salido, perdonen la inmodestia, muy pedagógico. Aparecen la mayoría de las funciones de tratamiento de strings y las que no lo hacen se manejan de forma absolutamente análogas a las que sí.
 

 




STANDARD STRING FUNCTIONS

STRCAT()

STRCHR()

STRRCHR()

STRCMP()

STRNCMP()

STRSPN()

STRICMP()

STRNCPY()

STRCSPN()

STRLEN()

STRLWR()

STRPBRK()

STRSTR()




Syntax: ptr=strcat (s1, s2) Concatenate s2 onto s1

ptr=strchr (s1, c) Find c in s1 and return &s1[ i ]

ptr=strrchr (s1, c) Same but search in reverse

cresult=strcmp (s1, s2) Compare s1 to s2

iresult=strncmp (s1, s2, n) Compare s1 to s2 (n bytes)

iresult=stricmp (s1, s2) Compare and ignore case

ptr=strncpy (s1, s2, n) Copy up to n characters s2->s1

iresult=strcspn (s1, s2) Count of initial chars in s1 not in s2

iresult=strspn (s1, s2) Count of initial chars in s1 also in s2

iresult=strlen (s1) Number of characters in s1

ptr=strlwr (s1) Convert string to lower case

ptr=strpbrk (s1, s2) Search s1 for first char also in s2

ptr=strstr (s1, s2) Search for s2 in s1



Parameters: s1 and s2 are pointers to an array of characters (or the name of an array).

Note that s1 and s2 MAY NOT BE A CONSTANT (like "hi" ).

n is a count of the maximum number of character to operate on.

c is a 8 bit character



Returns: ptr is a copy of the s1 pointer

iresult is an 8 bit int

result is -1 (less than), 0 (equal) or 1 (greater than)



Function: Functions are identified above.



Availability: All devices



Requires: #include <string.h>

 

 
   Recomiendo encarecidamente, para los interesados en el manejo de strings, el estudio detallado de la funcion int extrae_argumentos(int cuantos) ya que implementa las esencias fundamentales de su tratamiento.

   Tened en cuenta al recibir vía RS232 el carácter 0x0D (Enter) disparo el procesado de lo recibido hasta entonces en buffrec[]

Así el comando strcat asdfg qwerty[0x0D] hace
   buffrec[] = "strcat asdfg qwerty \0"
por lo que entonces debo:

1º detectar que se trata del comando strcat cosa que hago con :
   strcpy(xcommand,"strcat" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){
dentro de procesa_comando()

2º extraer sobre s1[] y/o s2[] los argumentos asdfg y qwerty que
es lo que realiza :
   error=extrae_argumentos(2);
y ...

3º realizar la función real strcat para presentar el resultado en :
   strcpy(sr,s1);
   strcat(sr,s2);
   printf("\r\n\n%s + %s = %s\r\n",s1,s2,sr);

Lo demás solo sirve para que todo esto funcione.
Si llegáis a comprender su funcionamiento todo lo demás es obvio y sencillo.
 
 
  strings_demo.c
 
 
  /////////////////////////////////////////////////////////////////////////////////////////
//
// Strings_Demo v.1.0
//
// © 28.02.2006 By RedRaven (RedPic)
//
// Para Foro Todo Pic
//
// Idioma: CCS PICC v.3.242
//
/////////////////////////////////////////////////////////////////////////////////////////

#include <16f876a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <stdlib.h>

// Constantes y definiciones ////////////////////////////////////////////////////////////

int const MAXLENBUFF=42; // Máxima longitud del buffer de recepción RS232
int const MAXLENCOMMAND=10; // Máxima longitud de un comando (sin argumentos)
int const MAXLENARG=8; // Máxima longitud de cada uno de los argumentos s1 y s2

// Variables Globales ///////////////////////////////////////////////////////////////////

char buffrec[MAXLENBUFF]; // Buffer de Recepción
int xbuffrec=0x00; // índice del Buffer de Recepción

int1 new_command=0; // Flag para indicar comando disponible
int1 pdte_send_prompt=0; // Flags para enviar echos fuera de la int_rda
int1 pdte_send_tmp_prompt=0;

char s1[MAXLENARG]; // Argumento 1
char s2[MAXLENARG]; // Argumento 2
char sr[MAXLENBUFF]; // Resultado de nuestras manipulaciones de Strings

// Declaracion de Funciones /////////////////////////////////////////////////////////////

void On_reset(void); // Tras RESET del Micro
void Send_listen(void); // Monitoriza RS232 : Comienzo
void Send_opts(void); // Monitoriza RS232 : Presenta opciones
void Send_prompt(void); // Monitoriza RS232 : Presenta el Cursor
void Send_tmp_prompt(void); // Monitoriza RS232 : Presenta el Cursor y el comando actual
void Ini_buffrec(void); // Borra el buffer de recepción
void Add_buffrec(char c); // Añade un carácter al buffer de recepción
void Procesa_comando(void); // Procesado de comandos


// INTERRUPCIONES ///////////////////////////////////////////////////////////////////////

// INTERRUPCION RDA - Recepción USART -

#int_rda
void serial_isr() {
  if(kbhit()){ // Si hay algo pendiente de recibir ...
    Add_buffrec(getc()); // lo recibo y lo añado al Buffer de Recepción
  }
}

// Control del Buffer de recepción ---------------------------------------

void Ini_buff_rec(void){ // Inicia a "\0" el Buffer de Recepción

  int i;
  for(i=0;i<MAXLENBUFF;i++){ // Bucle que pone a 0 todos los
    buffrec[i]=0x00; // caracteres en el Buffer de Recepción
  }
  xbuffrec=0x00; // Inicializo el índice de siguiente carácter recibido
}

void Add_buffrec(char c){ // Añade carácter al Buffer de Recepción

  switch(c){
    case 0x0D: // [Enter] -> Habilita Flag para procesar comando en Main
      buffrec[xbuffrec++]=' '; // Añade un espacio en blanco al final y ...
      new_command=1; // Habilita Flag para procesar comando en Main
      break;
    case 0x08: // [Del] -> Borra último carácter del Buffer
      if(xbuffrec>0){ // Si hay algo en el buffer
        buffrec[--xbuffrec]=0x00; // decremento el índice, escribo un cero y ...
        pdte_send_tmp_prompt=1; // habilito flag para refrescar el prompt
      }
      break;
    case 0x01B: // [Esc] -> Borra el Buffer completamente y ...
      Ini_buff_rec(); // habilito flag para refrescar el prompt
      pdte_send_prompt=1;
      break;
    case 0x009: // [Tab] -> Refresca el prompt y el comando tal como esté
      pdte_send_tmp_prompt=1;
      break;
    default:
      buffrec[xbuffrec++]=c; // Añade carácter recibido al Buffer
      putc(c); // y lo monitorizo
  }
}

// Rutinas y Funciones de RROS ///////////////////////////////////////////

void On_reset(void){ // Inicialización del Micro tras RESET

  disable_interrupts(GLOBAL); // todas las interrupciones desactivadas

  delay_ms(100);

  Ini_buff_rec(); // Inicializo Buffer de recepción
  new_command=0; // Desactivo flag de comando pendiente.
  pdte_send_prompt=0; // Desactivo Flags para enviar echo fuera de la int_rda
  pdte_send_tmp_prompt=0;

  enable_interrupts(int_rda); // interrupción RDA habilitada
  enable_interrupts(global); // todas las interrupciones activadas

  Send_listen(); // Presenta Comienzo
  Send_prompt(); // Presenta el Cursor

}

void Send_listen(void){ // Presenta Comienzo

  printf("\r\nStrings Demo v1.0");
  Send_opts();
}

void Send_opts(void){ // Relación de comandos válidos

  printf("\r\n\n");
  printf("[?] ver comandos válidos\r\n");
  printf("[strcat ABC abc] añade s2=abc a s1=ABC\r\n");
  printf("[strlwr ABC] convierte ABC a minúsculas\r\n");
  printf("[strstr ABC abc] busca s2=abc dentro de s1=ABC\r\n");

}

void Send_prompt(void){ // Presenta el cursor

  printf("\r\n>");
}

void Send_tmp_prompt(void){ // Presenta el cursor con el comando actual

  printf("\r>%s",buffrec);
}

// MAIN Programa Principal ///////////////////////////////////////////////

void main(void)
{
  On_reset();

  do {

    // Deteccion de la necesidad de procesar comandos pendientes ///////
    if(new_command==1){ // Si hay un nuevo comando ...
      new_command=0; // deshabilito el aviso y ...
      Procesa_comando(); // Procesado de comandos
      Ini_buff_rec(); // inicializo todo para nuevo comando y ...
      pdte_send_prompt=1; // mando prompt.
    }

    // Deteccion de la necesidad de enviar echos ///////////////////////
    if(pdte_send_prompt==1){ // Si esta pendiente de enviar prompt ...
      pdte_send_prompt=0; // marco que ya no lo está y ...
      Send_prompt(); // lo envío.
    }
    if(pdte_send_tmp_prompt==1){ // Si esta pendiente de enviar prompt temporal ...
      pdte_send_tmp_prompt=0; // marco que ya no lo está y ...
      Send_tmp_prompt(); // lo envío.
    }

  } while(TRUE);
}

// Funciones necesarias ... //////////////////////////////////////////////

int extrae_argumentos(int cuantos){

  int i,c;
  int error=0; // Para devolver código de error si se da el caso
  char *ptri;
  char *ptrf;

  for(i=0;i<MAXLENARG;i++){ // Bucle que pone a 0 todos los
    s1[i]='\0'; // caracteres en s1 y s2 antes de extraer
    s2[i]='\0';
  }

  c=1;
  for(i=0;i<MAXLENBUFF;i++){ // Bucle que marca los separadores " " (espacios)
    if(buffrec[i]==' '){ // en el buffer de recepción
      buffrec[i]=c++; // escribiendo 0x01 en el primero, 0x02 en el segundo ... etc.
    } // con lo que s1 estará entre 0x01 y 0x02 y ...
  } // s2 estará entre 0x02 y 0x03.

  if(cuantos==1){ // Si necesito dos argumentos y ...
    if(c!=3){ // Error: tengo menos o mas de un argumento
      error=1; // ya que hemos puesto un numero distinto a 2 de marcas
      goto retorno; // observa que para 2 marcas c vale 3
    }
  }
  if(cuantos==2){ // Si necesito dos argumentos y ...
    if(c!=4){ // Error: tengo menos o mas de dos argumentos
      error=1; // ya que hemos puesto un numero distinto a 3 de marcas
      goto retorno; // observa que para 3 marcas c vale 4
    }
  }

  ptri=strchr(buffrec,0x01); // obtengo el puntero donde aparece 0x01
  ptrf=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02
  if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02
    ptri+=1; // avanzo 1 ptri para saltarme 0x01
    strncpy(s1,ptri,ptrf-ptri); // Luego s1 lo extraigo entre ptri y ptrf
  }

  if(cuantos==1){ // Si solo necesito un argumento he terminado
    goto retorno;
  }

  ptri=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02
  ptrf=strchr(buffrec,0x03); // obtengo el puntero donde aparece 0x03
  if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02
    ptri+=1; // avanzo 1 ptri para saltarme 0x02
    strncpy(s2,ptri,ptrf-ptri); // Luego s2 lo extraigo entre ptri y ptrf
  }

retorno:

  return(error);
}

// Procesa_comando: Hace cosas o manda hacerlas ... //////////////////////

void Procesa_comando(void){

  int1 procesado_ok=0; // Flag para comprobar si he procesado algo válido
  char xcommand[MAXLENCOMMAND]; // Comprobador de comando recibido
  int error;
  char *ptrx;

  // COMANDO = "" intro en blanco ---------------------------------------
  strcpy(xcommand,"");
  if(!strcmp(buffrec,xcommand)){
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "?" ------------------------------------------------------
  strcpy(xcommand,"?");
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    Send_opts();
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "strcat" -------------------------------------------------
  strcpy(xcommand,"strcat");
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    error=extrae_argumentos(2);
    if(error!=0){
      printf("\r\nError: numero erróneo de argumentos");
    }
    else{
      strcpy(sr,s1);
      strcat(sr,s2);
      printf("\r\n\n%s + %s = %s\r\n",s1,s2,sr);
    }
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "strlwr" -------------------------------------------------
  strcpy(xcommand,"strlwr");
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    error=extrae_argumentos(1);
    if(error!=0){
      printf("\r\nError: numero erróneo de argumentos");
    }
    else{
      strcpy(sr,s1);
      strlwr(sr);
      printf("\r\n\n%s -> %s\r\n",s1,sr);
    }
    procesado_ok=1;
    goto fin_procesa;
  }
  // COMANDO = "strstr" -------------------------------------------------
  strcpy(xcommand,"strstr");
  if(!strncmp(buffrec,xcommand,strlen(xcommand))){
    error=extrae_argumentos(2);
    if(error!=0){
      printf("\r\nError: numero erróneo de argumentos");
    }
    else{
      strcpy(sr,s1);
      ptrx=strstr(sr,s2);
      if(ptrx==0){
        printf("\r\n\n%s no está en %s\r\n",s2,s1);
      }
      else{
        printf("\r\n\n%s empieza en el caracter %uº de %s\r\n",s2,(ptrx-&sr[0])+1,s1);
      }
    }
    procesado_ok=1;
    goto fin_procesa;
  }

fin_procesa:

  // COMANDO ERRÓNEO - ¿ezo qué é lo que é ?-----------------------------
  if(procesado_ok==0){
    printf("\r\n?%s",buffrec);
  }
}
   
 
 

Descargar strings_demo.c

 

 



Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias.
 
Visitas
Totales : 68537 Hoy: 2 Activas: 1 Vistas: 68537

Esta página fue modificada el 07-08-2010 15:42:21

           
 DmSoft WAMP Escribir Unreal