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.
- Cambiado Leandro TuttiniMVP martes, 24 de julio de 2012 17:15 (De:Windows Forms)
Todas las respuestas
-
martes, 24 de julio de 2012 19:53
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
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.

