Leer variable int por el puerto USB uitilizando windows forms (c++)

Respondida Leer variable int por el puerto USB uitilizando windows forms (c++)

  • martes, 24 de julio de 2012 16:52
     
     

    Hola,

    Mi problema es que necesito enviar y recibir datos de un microcontrlador, y para leer caracteres utilizo el codigo siguiente (que encontre por el foro):

                     cli::array<unsigned char> ^letraleida = gcnew cli::array<unsigned char>(1);

                     this->serialPort1->Read(letraleida,0,1);

                     letradefinitiva1=letraleida[0]; //Siendo letradefinitiva1 una variable tipo char que contiene el numero correspondiente a una letra en codigo ASCII

    Y para enviar:

                     cli::array<unsigned char> ^letradefinitiva = gcnew cli::array<unsigned char>(1);
                     letraenviada='S';  // Variable tipo char
                     letradefinitiva[0]=letraenviada;
                     this->serialPort1->Write(letradefinitiva,0,1);

    Per no se como realizar lo mismo para una variable int, ya que he probado cosas semejantes al codigo de arriba pero con int sin existo. Agradeceria cualquier ayuda, mersi.

Todas las respuestas

  • martes, 24 de julio de 2012 19:53
     
     Respondida Tiene código

    Antes de nada hago constar que nunca he trabajado con puertos serie.

    Suponiendo que el código que has puesto sea correcto y que el int que quieres enviar/recibir está en binario, y no como una ristra de dígitos, yo lo haría así:

    • Primero sendas funciones para enviar/recibir un byte
    • Segundo sendas funciones que cojan un int, lo lean/escriban como un array de bytes que con un bucle envio/recibo repetidamente.
    • Las funciones del punto anterior, las haria con un template por si quiero enviar/recibir cualquier otro tipo de variable.

    El código podría ser este:

    unsigned char RecibirByte(void) { cli::array<unsigned char> ^ByteRecibido = gcnew cli::array<unsigned char>(1); this->serialPort1->Read(ByteRecibido,0,1); return ByteRecibido[0]; } void EnviarByte(unsigned char C) { cli::array<unsigned char> ^ByteAEnviar = gcnew cli::array<unsigned char>(1); ByteAEnviar[0] = C; this->serialPort1->Write(ByteAEnviar,0,1); } template <class T> T Recibir(void) { T Recibido; for (int i=0; i<sizeof(T); ++i) reinterpret_cast<unsigned char *>(&Recibido)[i] = RecibirByte(); return Recibido; } template <class T> void Enviar(T Dato) { for (int i=0; i<sizeof(T); ++i) EnviarDato(reinterpret_cast<unsigned char *>(&Dato)[i]); } // Ejemplos de uso int main(int argc, char *argv[]) { int n = Recibir<int>(); double d = Recibir<double>(); char c = 'S'; float f = 34.76; Enviar(c); Enviar(f); UnaClaseSinPunteros CSP; Enviar(CSP); }

    El código no lo he compilado ni testeado, pero puede que te de alguna idea.

    Tampoco sé si en las funciones RecibiByte/EnviarByte tendrías que comprobar el estado del puerto serie para que no envies/recibas los bytes demasiado rápido.

    • Marcado como respuesta S2G jueves, 26 de julio de 2012 14:56
    •  
  • jueves, 26 de julio de 2012 14:56
     
     

    Hola Bartomeu,

    El codigo que me pasaste no conpilava pero lo arregle para que funcionara y con lo que me dijiste di con el problema, mersi.

    El principal error que tenia es que a pesar que del microcontrolador enviava un byte, el metodo de envio que utilizaba era para enviar caracteres y al enviar 123 recibia 495051 (el 123 pero en codigo ascii), arregle para enviarlo como byte y encontre la solucion, aunque lo que me pasate no me daria bien con los numeros negativos debido a que la variable int del microcontrolador es de 2 bytes y del programa es de 4 bytes pero con el codigo siguiente me da bien.

                cli::array<unsigned char> ^ByteRecibido=gcnew cli::array<unsigned char>(2);
                int numerodefinitivo;
                int numeromedio;

                this->serialPort1->Read(ByteRecibido,0,2);
                numeromedio=(int)ByteRecibido[0];
                numeromedio=numeromedio<<8;
                numerodefinitivo=numeromedio;
                numeromedio=(int)ByteRecibido[1];
                numerodefinitivo=numerodefinitivo+numeromedio;
                if(numerodefinitivo>32767) //El bit mas alto en 1, es decir signo negativo
               {
               ByteRecibido[0]=~ByteRecibido[0];
               numeromedio=(int)ByteRecibido[0];
               numeromedio=numeromedio<<8;
               numerodefinitivo=numeromedio;
               ByteRecibido[1]=~ByteRecibido[1];
               numeromedio=ByteRecibido[1];
              numerodefinitivo=numerodefinitivo+numeromedio+1;
              numerodefinitivo=-numerodefinitivo;
              }

              this->textBox1->Text=numerodefinitivo.ToString();

    Mersi por la ayuda.

  • viernes, 27 de julio de 2012 5:51
     
     

    Como te dije, nunca he trabajado con puertos serie. Pero estoy encantado de haberte inspirado una solución.

      Saludos.

  • viernes, 27 de julio de 2012 5:52
     
     

    Como te dije, nunca he trabajado con puertos serie. Pero estoy encantado de haberte inspirado una solución.

      Saludos.

  • domingo, 03 de febrero de 2013 7:48
     
      Tiene código

    Para reducir un poco el código, te recomiendo usar en el programa variables de tipo short, que son de 2 bytes, para asegurar la compatibilidad con el microcontrolador; y para enviarlos, yo suelo hacer lo siguiente: creo un variable de tipo char* (un puntero), hago un cast desde la variable de dos bytes con la dirección de memoria, y luego lo envío como si fuera una cadena:

    void Enviar(short Numero)
    {
       char* ptr = (char*)&Numero; //Creo el puntero al numero a enviar
       FunciónQueEnvíaDatos(ptr[0]);
       FunciónQueEnvíaDatos(ptr[1]); //Envío cada byte
    }

    Hubiese usado un bucle for para enviar los datos, pero me pareció que no era necesario dado que solamente eran 2 valores.

    Si programas en C para el microcontrolador, podes usar un código similar para recuperar el valor:

    int Recibir(void) //Se entiende que el int representa 2 bytes
    {
       int recibe = 0;
       char* ptr = (char*)&recibe;
       ptr[0] = FunciónQueRecibe();
       ptr[1] = FunciónQueRecibe();
       return recibe;
    }

    Por supuesto, se supone que ambos procesadores son Little-endian o Big-endian. Si uno es Little-endian y el otro es Big-endian, la transmisión va a fallar.