Autor Tema: Ejemplitos en C: Mis Funciones favoritas en CCS C  (Leído 37842 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
Ejemplitos en C: Mis Funciones favoritas en CCS C
« en: 23 de Febrero de 2006, 13:36:00 »
Iniciamos aquí otra serie de posteos, que espero sea larga y fructífera,
con la sana intención de facilitarle el camino a nuestros amables visitantes
Picmaníacos.

La titúlo Mis Funciones favoritas en CCS C ya que pretendo ir subiendo
aquellas funciones que me van haciendo falta en mi otra serie de
Ejemplitos 16F876A: Indice de contenidos y tambien aquellas funciones que detecte que son muy
buscadas y necesitadas por los amigos principiantes.

Empezamos pues con una de la mas famosas ...

Titulo: ASCII Hex to Int
=================

Descripción:

Convierte un carácter ASCII Hex (0..9 A..F) al valor
entero (0..15) correspondiente (4 bits)

Declaración:

#include <stdlib.h>

int  aschex2int(char d);

Función y ejemplo de uso:

<span class="texto_mini">Codigo:</span>[hr /
]
int aschex2int(char d){          // Convierte un caracter ascii hex a int

   int r=0;                       // Declaro e inicializo a cero el resultado
   if(isxdigit(d)){               // Si es un digito hexadecimal ...
      if(isdigit(d)){             // si es un digito decimal ...
         r=d-'0';                 // devuelvo su diferencia con el valor ascii del caracter "0"
      }
      if(isalpha(d)){             // si es alfanumerico ...
         d=toupper(d);            // lo paso a mayusculas y ...
         r=10+(d-'A');            // devuelvo 10 mas su diferencia con el valor ascii de la letra "A"
      }
   }
   return(r);
}

   // Ejemplo de uso con 1 caracter

   int x;
   x = aschex2int('F');          // x toma el valor 15


   // Ejemplo de uso con dos caracteres

   char *ptr;
   strcopy(ptr,"ff" );

   int x;
   x =(16*aschex2int(ptr[0]));             // Convierto el dígito mas significativo
   x+=(aschex2int(ptr[1]));                // Convierto el dígito menos significativo
                                           // y lo sumo a lo anterior, x toma el valor 255




Y ahora vamos con una función muy util a la hora de manejar los Displays
de 7 segmentos; sobre todo para su uso con los Drivers estilo <a href="http://picmania.garcia-cuervo.com/recursos/74LS48.pdf" target="_blank">74LS48[/url]
Esta función es facilmente adaptable a su uso con solo dos dígitos ...

Titulo: Int to BCD
==============

Descripción:

Convierte un entero a su representación BCD (Binary Code Decimal)

Declaración:

int h_digit, m_digit, l_digit;

void int2bcd(int valor);

Función y ejemplo de uso:

<span class="texto_mini">Codigo:</span>[hr /
]
void int2bcd(int valor){         // Funcion que convierte de Entero a 3 x BCD

   h_digit = (int) valor / 100;  // 1er Dígito o Centenas
   valor -= h_digit * 100;       // y se lo resto al valor
   m_digit = (int) valor / 10;   // 2do Dígito o Decenas
   valor -= m_digit * 10;        // y también se lo resto
   l_digit = valor;              // y por último solo me quedan las unidades
}

   int x=255;

   int2bcd(x);
  
   printf("
Test %u %u %u
",h_digit,m_digit,l_digit);





Titulo : Funciones Date y Time
=====================

Y ahora en otro orden de cosas vamos a tratar una serie de funciones
bajo el denominador común de Date y Time.

Estas funciones no son mías, son una traducción de lo originalmente publicado
en el <a href="http://www.ccsinfo.com/forum/viewtopic.php?t=25611" target="_blank">Foro CCS Library[/url] y su autor es <a href="mailto:nicksubzero@yahoo.com ">Aurelian Nichita[/url]
Yo me he limitado a traducirlas al español y probar que funcionan.

Incluye las funciones:

esAgnoBisiesto(int y)
diasDesdeAgno1(int y, int m, int d)
segundosDesdeHora0(int h, int m, int s)
segundosDesdeAgno1(int yr, mo, dy, hr, mi, se)
segundosEntre(int yr1, mo1, dy1, hr1, mi1, se1, yr2, mo2, dy2, hr2, mi2, se2)
ISODiaDeLaSemana(int YY, int MM, int DD)
ISONumeroDeLaSemana(int YY, int MM, int DD, int& weekOfYear, int& actualYear)

<span class="texto_mini">Codigo:</span>[hr /
]

// Definiciones y Funciones de Date Time ////////////////////////////////////////////////

// Números ISO de los dias de la semana
 
#define LUNES     1
#define MARTES    2
#define MIERCOLES 3
#define JUEVES    4
#define VIERNES   5
#define SABADO    6
#define DOMINGO   7

const int Dias_de_cada_Mes[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                                      {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };

const int Orden_Dias_Semana[7] = {6, 7, 1, 2, 3, 4, 5};

#define SEGUNDOS_EN_UN_DIA 86400

#define SEGUNDOS_EN_UNA_HORA 3600
#define SEGUNDOS_EN_UN_MINUTO 60
#define MINUTOS_EN_UN_DIA 1440
#define MINUTOS_EN_UNA_HORA 60
#define HORAS_EN_UN_DIA 24


// Algunas funciones que seran usadas mas adelante

#inline
short esAgnoBisiesto(int y) {
  return (y % 4 == 0);
}

#separate
int32 diasDesdeAgno1(int y, int m, int d) {
  int32 dias = 0;
  int i;
  short es_bisiesto;

  es_bisiesto = esAgnoBisiesto(y);
  for (i=1; i<y; i++) {
    if (esAgnoBisiesto(i))
      dias += 366;
    else
      dias += 365;
  }
  for (i=1; i<m; i++)
    dias += Dias_de_cada_Mes[es_bisiesto][ i ];
  dias += d;

  return dias;
}

#separate
int32 segundosDesdeHora0(int h, int m, int s) {
  int32 segundos;
  segundos = (int32)h * SEGUNDOS_EN_UNA_HORA;
  segundos += (int32)m * SEGUNDOS_EN_UN_MINUTO;
  segundos += s;
  return segundos;
}

#separate
int32 segundosDesdeAgno1(int yr, mo, dy, hr, mi, se) {
  int32 segundos;
  segundos = diasDesdeAgno1(yr, mo, dy) * SEGUNDOS_EN_UN_DIA;
  segundos += segundosDesdeHora0(hr, mi, se);
  return segundos;
}

// Calcula el numero de segundos entre dos fechas y horas

// Adaptado para años entre 2001 y 2135 (limitado por el tamaño de los int32)


#separate
int32 segundosEntre(int yr1, mo1, dy1, hr1, mi1, se1, yr2, mo2, dy2, hr2, mi2, se2) {
  int32 inicio;
  int32 final;
  inicio = segundosDesdeAgno1(yr1, mo1, dy1, hr1, mi1, se1);
  final  = segundosDesdeAgno1(yr2, mo2, dy2, hr2, mi2, se2);
  if (inicio > final)
    return inicio-final;
  else
    return final-inicio;
}

// Calculo del dia de la semana. Adaptado SOLO para años del 2000 al 2099

#separate
int ISODiaDeLaSemana(int YY, int MM, int DD) {
  signed long diaDeLaSemana;
  int cent = 20;  // YYYY / 100

  // Algoritmo de congruencia de Zeller

  if (MM < 3) {
    MM = MM + 12;
    if (YY > 0)
      YY--;
    else {
      YY = 99;
      cent--;
    }
  }

  diaDeLaSemana = DD;
  diaDeLaSemana += (((signed long)MM + 1) * 26) / 10;
  diaDeLaSemana += YY;
  diaDeLaSemana += YY / 4;
  diaDeLaSemana += cent / 4;
  diaDeLaSemana -= cent * 2;

  while (diaDeLaSemana < 0)
    diaDeLaSemana += 7;

  diaDeLaSemana %= 7;

  return Orden_Dias_Semana[(int)diaDeLaSemana]; // Ahora tenemos el número ISO del dia de la semana
}

// Calculo de número ISO de la semana. Adaptado SOLO para años del 2001 al 2098

#separate
void ISONumeroDeLaSemana(int YY, int MM, int DD, int& weekOfYear, int& actualYear)
{
  signed long diaDelAgno;
  int DiaDeLaSemanaInicial;
  int DiaDeLaSemanaFinal;
  short bisiesto;
  signed int i;

  do {
    bisiesto = esAgnoBisiesto(YY);
    diaDelAgno = 0;

    for (i=1; i<=MM; i++) {
      if (i < MM)
        diaDelAgno += Dias_de_cada_Mes[bisiesto][ i ];
      else
        diaDelAgno += DD;
    }
    actualYear = YY;
    DiaDeLaSemanaInicial = ISODiaDeLaSemana(actualYear, 1, 1);

    if (DiaDeLaSemanaInicial > JUEVES)
      diaDelAgno -= 8 - DiaDeLaSemanaInicial;
    else
      diaDelAgno += DiaDeLaSemanaInicial - 1;

    if (diaDelAgno <= 0)
      weekOfYear = 0xFF;
    else {
      weekOfYear = diaDelAgno / 7;
      if (diaDelAgno % 7 != 0)
        weekOfYear++;
      if (weekOfYear > 52) {
        DiaDeLaSemanaFinal = DiaDeLaSemanaInicial;
        if (bisiesto) {
          if (DiaDeLaSemanaFinal == DOMINGO)
            DiaDeLaSemanaFinal = LUNES;
          else
            DiaDeLaSemanaFinal++;
        }
        if (DiaDeLaSemanaFinal < JUEVES) {
          actualYear++;
          weekOfYear = 1;
        }
      }
    }

    if (weekOfYear == 0xFF) {
      if ((--DD)==0) {
        if ((--MM)==0) {
          YY--;
          MM = 12;
        }
        DD = Dias_de_cada_Mes[esAgnoBisiesto(YY)][MM];
      }
    }

  } while (weekOfYear == 0xFF);
}





« Última modificación: 12 de Julio de 2006, 21:30:01 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado antoniof

  • Moderadores
  • PIC24F
  • *****
  • Mensajes: 729
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #1 en: 24 de Febrero de 2006, 02:15:00 »
Hola RedPIC.

A ver si tienes a mano la de pasar enteros a ASCII con mas de una cifra claro Sonrisa Gigante

Es que la que tenia echa se me ha perdido Enfurruñado

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #2 en: 24 de Febrero de 2006, 13:17:00 »
Mi pacense amigo antoniof:

La función contraria es trivial ya que CCS nos la proporciona y se llama sprintf.
Te pongo un ejemplo de su uso:

Codigo:

   int y=128;             // Variable entera a convertir
   char sy[4];            // String de destino de la conversión (tres dígitos + de fin de string)

   sprintf(sy,"%u",y);   // sx vale ahora "128"



Sin embargo imaginemos que los amables señores de CCS no nos hubiesen proporcionado
tal función y tuviesemos que realizarla nosotros.

Entonces deberíamos proceder "descuartizando" nuestro número entero aplicandole
el principio de numeración indo-arábigo (decimal) en que se basa:

Codigo:

   int x=128;             // Variable entera a convertir
   char sx[4];            // String de destino de la conversión (tres dígitos + de fin    

   int c,d,u;             // Variables intermedias para centenas, decenas y unidades
   
   c = (int) x / 100;     // Calculamos cuantas centenas tiene nuestro número ...
   x = x - (c * 100);     // y se lo restamos
   d = (int) x / 10;      // Calculamos cuantas decenas tiene nuestro número ...
   x = x - (d *  10);     // y se lo restamos
   u = (int) x / 1;       // Y por último calculamos cuantas unidades tiene nuestro número.
                          // De esta forma nuestro string se compone de ...  
   sx[0]="0"+c;           // La Centena que será el ASCII del "0" mas nuestras centenas
   sx[1]="0"+d;           // La Decena que será el ASCII del "0" mas nuestras decenas y
   sx[2]="0"+u;           // La Unidad que será el ASCII del "0" mas nuestras unidades
   sx[3]="";            // Y finalizamos el string con su correspondiente caracter
                          // sx vale ahora "128"


Fácil y sencillo como juego de chiquillo Vacilando

hummm ... y esto me dá ideas ... si, me dá ideas ...


Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #3 en: 24 de Febrero de 2006, 16:18:00 »
Esta respuesta que he dado al tema que planteó el amigo antoniof me ha
sugerido una solución más elegante que la que anteriormente tenía para la
conversión de Entero a BCD, ya que esta conversión no deja de ser una
simplificación del tema de "descuartizar" un numero en sus potencias de 10.

El asunto estriba en que el código BCD consiste simplemente en representar
los números como lo hacemos habitualmente pero solo con cuatro dígitos binarios
convirtiendo por tanto cualquier entero en sus correspondientes componentes,
uno a uno, a su representación binaria:

57dec = 0101 0111bcd

O sea que el numero anterior debemos trocearlo en centenas, decenas y
unidades y obtener así cada dígito por separado, que es lo que realmente
.

Para ello he escrito la función int2bcd que podeis ver en el post original de
este hilo.



Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado garlic_74

  • PIC10
  • *
  • Mensajes: 33
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #4 en: 27 de Febrero de 2006, 08:37:00 »
aver si alguien se curra ejemplos de la libreria string.h que ha mi siempre me dan problemas Muchas risas
strcpy()
stcmp()
strcat()

Un saludo!!! Muchas risas

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #5 en: 27 de Febrero de 2006, 15:35:00 »
Bueno amigo Garlic, voy a ver si me busco una aplicación bonita donde haga uso del tratamiento "completo" de las funciones de string.h ...

De hecho acabo de concluir algo que hace uso de varias funciones de este "include" ... strcpy, strcmp, strncpy, strncmp ... y algo más. Voy a ver si le doy forma y lo publico ... aunque sea en la sección de Ejemplitos 16F678A

¡Te acepto el reto! Muchas risas

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 17482
    • MicroPIC
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #6 en: 27 de Febrero de 2006, 15:41:00 »
Si es que te ponen un capote y entras a saco. Asi da gusto.
Un saludo desde Sevilla, España.
Visita MicroPIC                                                                                        ɔ!doɹɔ!ɯ ɐʇ!s!ʌ

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #7 en: 27 de Febrero de 2006, 16:03:00 »
Jua, jua, jua Muchas risasMuchas risasMuchas risas  ... manolo, me llamas Toro, y yo tan ancho y tan pancho ... jua, jua, jua Muchas risasMuchas risasMuchas risas ...

Pero la verdad es que tienes razón ... a mi se me puede aplicar lo de los ingenieros:

Para hacer que un ingeniero se lance de cabeza a la resolución de un problema no hay mas que insinuarle que no es posible solucionarlo, entonces se lanza a él como un chihuahua a una rodaja de mortadela, y ni come ni duerme, ni se lava, y ni casi respira hasta encontrar la solución mas elegante, rápida y barata que en cabeza cabe.

Pero eso es otra historia ....



Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado pachopic

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 199
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #8 en: 27 de Febrero de 2006, 20:52:00 »
HOLA:

aqui  otra manera de convertir un numero cualquiera a bcd mediante el operador modulo (%) , y arreglos: Sonrisa GiganteSonrisa GiganteSonrisa GiganteSonrisa GiganteSonrisa Gigante

Codigo:

////////// FUNCION QUE CONVIERTE A 5 DIGITOS DE BINARIO long int A BCD //

void bin16_bcd5(long int n)// el numero a convertir es un entero largo
{
int i;          // indice del arreglo unidades=bcd_dato
  • ,d=[1],...m=[5]
    for(i=0;i<5;i++)// llena el arreglo con los valores uni,dec,cen,mil,diezm
    {                      // (cambio i dependiendo que tantos digitos sea el # a convertir)
    bcd_dato[ i ]=n%10;// mediante la operacion modulo se obtiene el, i digito decimal
    n=n/10;            // n dividido 10 para cada i y tomamos su valor entero:
    }                  // por ejemplo  para i=0,  4358 mod 10 =8, luego 4358/10 =435
    }                  // para i=2, 435 mod 10=5, 435/10=43 luego 43 mod 10=3

    LUEGO:

    bcd_dato[0]=8
    bcd_dato[1]=5
    bcd_dato[2]=3
    bcd_dato[3]=4
          .               .
          .               .
          .               .






salu2

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #9 en: 28 de Febrero de 2006, 05:35:00 »
Muy elegante tu función Pachopic. Te felicito.

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #10 en: 28 de Febrero de 2006, 05:52:00 »
El Reto Garlic-Strings se compone, en principio y según las páginas
138 y 139 del C Compiler Reference Manual Build-In Functions, de:

Codigo:

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>



Va a ser dificil montar un ejemplo donde se usen todas estas funciones,
asi que intentaré usar el mayor número posible de ellas, y de las que
resten pondré algunos ejemplos que aclaren su uso y/o aplicación.

Vamos a ver qué resulta de todo esto.  Giño

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #11 en: 28 de Febrero de 2006, 12:43:00 »



Con mi insufrible manía de hacer la cosas lo mas dificil 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 mayoria 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í.

Mas abajo os posteo el código  completo del <a href="http://picmania.garcia-cuervo.com/recursos/_strings_demo.c" target="_blank">Strings_Demo.c[/url]

<span class="texto_mini">Codigo:</span>[hr /
]

/////////////////////////////////////////////////////////////////////////////////////////
//
// 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;                         // Maxima longitud del buffer de recepción RS232
int const MAXLENCOMMAND=10;                      // Maxima longitud de un comando (sin argumentos)
int const MAXLENARG=8;                           // Maxima longitud de cada uno de los argumentos s1 y s2

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

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

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 caracter 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 Recepcion
   }
}

// Control del Buffer de recepcion ---------------------------------------

void Ini_buff_rec(void){                         // Inicia a "�" el Buffer de Recepcion

   int i;
   for(i=0;i<MAXLENBUFF;i++){                    // Bucle que pone a 0 todos los
      buffrec[ i ]=0x00;                           // caracteres en el Buffer de Recepcion
   }
   xbuffrec=0x00;                                // Inicializo el indice de siguiente caracter recibido
}

void Add_buffrec(char c){                         // Añade caracter al Buffer de Recepcion

      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 caracter 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 caracter recibido al Buffer
            putc(c);                             // y lo monitorizo
      }
}

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

void On_reset(void){                             // Inicializacion del Micro tras RESET

   disable_interrupts(GLOBAL);                   // todas las interrupciones desactivadas

   delay_ms(100);

   Ini_buff_rec();                               // Inicializo Buffer de recepcion
   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);                   // interrupcion 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("
Strings Demo v1.0" );
   Send_opts();
}

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

   printf("

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

}

void Send_prompt(void){                          // Presenta el cursor

   printf("
>" );
}

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

   printf("
>%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 ]="�";                                // caracteres en s1 y s2 antes de extraer
      s2[ i ]="�";
   }

   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("
Error: numero erróneo de argumentos" );
      }
      else{
         strcpy(sr,s1);
         strcat(sr,s2);
         printf("

%s + %s = %s
",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("
Error: numero erróneo de argumentos" );
      }
      else{
         strcpy(sr,s1);
         strlwr(sr);
         printf("

%s -> %s
",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("
Error: numero erróneo de argumentos" );
      }
      else{
         strcpy(sr,s1);
         ptrx=strstr(sr,s2);
         if(ptrx==0){
            printf("

%s no está en %s
",s2,s1);
         }
         else{
            printf("

%s empieza en el caracter %uº de %s
",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("
?%s",buffrec);
   }
}









« Última modificación: 19 de Enero de 2016, 05:10:38 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #12 en: 28 de Febrero de 2006, 12:54:00 »
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 caracter 0x0D (Enter) disparo el
procesado de lo recibido hasta entonces en buffrec[]

Así el comando strcat asdfg qwerty[0x0D] hace  

buffrec[] = "strcat asdfg qwerty "

por lo que entonces debo:

detectar que se trata del comando strcat cosa que hago con :

   strcpy(xcommand,"strcat" );
   if(!strncmp(buffrec,xcommand,strlen(xcommand))){

dentro de procesa_comando()

extraer sobre s1[] y/o s2[] los argumentos asdfg y qwerty que
es lo que realiza :

   error=extrae_argumentos(2);

y ...
realizar la función real strcat para presentar el resultado en :

   strcpy(sr,s1);
   strcat(sr,s2);
   printf("%s + %s = %s",s1,s2,sr);

Lo demás solo sirve para que todo esto funcione.

Si llegais a comprender su funcionamiento todo lo demas es obvio y sencillo.

¡Que tengais suerte! y no dudad en consultar aspectos oscuros o dudas que
tengáis.



« Última modificación: 03 de Mayo de 2006, 08:43:52 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado antoniof

  • Moderadores
  • PIC24F
  • *****
  • Mensajes: 729
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #13 en: 01 de Marzo de 2006, 02:29:00 »
Diox RedPIC me tienes locolocolocoloco

Sin duda cuando te propones algo lo consigues.

Vamos a tener que llamar a la universidad de Sevilla o recoger unas cuantas firmas para que te den el titulo de Ingeniero YA!!!


Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5388
    • Picmania by Redraven
RE: Ejemplitos en C: Mis Funciones favoritas en CCS C
« Respuesta #14 en: 01 de Marzo de 2006, 02:44:00 »
Ja, ja, ja ... a lo mejor ese es el único metodo posible para que me den el titulo.

Cuando estuve a finales de los 70 estudiando pa ingeniero me echaron a la calle ...
era demasiado aficionado al vidrio y las faldas Muchas risas Muchas risas Muchas risas
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania


 

anything