2009-10-24 5 views
5

Estoy tratando de hacer que un microcontrolador se comunique con un programa en mi escritorio. Estoy usando conexiones de puerto serie con radios Xbee en ambos extremos.¿Cómo envío y recibo continuamente con puerto serie inalámbrico en 8051?

La comunicación funciona bien cuando envío algo desde el microcontrolador al escritorio y luego el programa en el escritorio envía algo al microcontrolador.

Sin embargo, cuando requiero que la información se envíe continuamente desde el controlador al programa de escritorio hasta que el programa de escritorio envía una respuesta en particular, no funciona.

Aquí está el código para lo que estoy hablando:

unsigned char ans = 'N'; 
    unsigned int count = 0; 

    void main(void) 
    { 


     while(1) 
     { 
      if(count == 0) 
      { 
       Configure(); 
       count = 1; 
      } 

        //there is some more code here but is irrelevant to the serial communication 

     } 

    } 


void Configure() 
{ 


    //Repeat this until the user accepts the sent string as correct 
    while(ans == 'N') 
    { 

     BuildString(); 
     Send(); 
     Receive(); 
    } 
} 

void Send() 
{ 
    unsigned int i; 

    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    for(i=0; i<4; i++) 
    { 
     SBUF = toSend[i]; 
     while(TI == 0); 
     TI = 0; 
    } 

} 

void Receive() 
{ 
    unsigned int j; 

    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 


    for(j=0; j<2; j++) 
    { 
     while(RI == 0); 
     Received[j] = SBUF; 
     RI = 0; 
    } 


    if(count == 0) 
     ans = Received[1]; 

    else 
    { 
     RunType = Received[0]; 
     Move = Received[1]; 
    } 


} 

La función BuildString() simplemente construye una cadena sobre la base de algunas entradas de sensor. Las funciones de enviar y recibir funcionan bien, pero cuando las necesito para enviar y recibir continuamente, como en la función Configurar() anterior, no funciona.

¿Alguna sugerencia? Realmente los apreciaría.

+0

Un hack rápido y sucio que hará que su código sea más confiable es limitar la cantidad de tiempo que esperará a que RI se establezca en verdadero. Establezca una variable a 65535 y decremente. Si llega a 0 antes de obtener un byte, abandone e intente enviar de nuevo. Si realmente necesitas una versión basada en interrupciones de tu código, puedo llamarte; en general, estos son mucho más confiables. –

Respuesta

4

El problema es que las funciones de enviar y recibir son sondeadas y bloqueadas. Cuando llame a la función de recepción, solo regresará después de recibir un mensaje completo. Dito para la función de envío, pero en caso de envío, la duración es mucho más corta (su programa propagadamente solo llamará a enviar cuando haya un mensaje que enviar, mientras que la recepción puede esperar días antes de que llegue el mensaje.

Si requiere comunicación asincrónica, lo mejor es usar comunicaciones basadas en interrupciones, al menos para la recepción e idealmente para enviar y recibir.

También es posible imponer esto utilizando comunicaciones sondeadas, pero luego debe escribir una función que comprueba si un carácter está disponible para recibir (o si tx está vacío), para leer/escribir el siguiente carácter desde/hacia el búfer

Las ventajas de la interrupción b la comunicación ASED son:

  • full duplex
  • se utiliza
  • menos tiempo de CPU (bucles no esperar necesario)
  • menos energía (que permite a la CPU para ir a un modo de bajo consumo/modo de espera, con el despertar de interrupción ; el sondeo siempre requiere plena potencia)

Como primer paso, le aconsejo que implemente (u obtenga) una recepción basada en interrupciones; incluso cuando la función de transmisión aún está bloqueada, permitirá el funcionamiento dúplex completo con un mínimo esfuerzo. Si no tiene un sistema operativo (rtos/scheduler), tendrá que pensar en un mecanismo de sincronización. La forma más sencilla es que su recepción maneje un mensaje si hay uno disponible, y que devuelva inmediatamente si no hay un mensaje (completo).

buena suerte.

Edición después de los comentarios Sobre una base de mensaje por mensaje, las cosas puede parecer que funciona si el escritorio está reaccionando en los mensajes enviados por el controlador. Si su controlador tiene una gran memoria intermedia FIFO (es decir, 64 bytes) en la recepción, esto puede funcionar. La mayoría de los controladores que conozco no tienen esto. Muchos tienen solo un buffer de caracteres. Puede detectar esto usando un bit OVERFLOW en los registros; si esto está establecido, entonces los caracteres se perdieron al recibir.

Algunas cajas de uso: * desea enviar 2 mensajes de una vez (por ejemplo: init + do_something). La pc responde al primer mensaje, pero el controlador sigue enviando y elimina la mayoría de los datos. * La PC comienza a enviar antes de que el controlador ejecute la función receive(). Los datos al comienzo del paquete pueden perderse * cualquier caída en la comunicación puede causar un interbloqueo (es decir, el controlador y el escritorio están esperando que el otro extremo envíe algo.

Para diagnosticar: verifique el bit de desbordamiento. está configurado, ha perdido datos y necesita trabajar en las funciones de interrupción. Si es posible, supervise ambos lados (al menos el estado, un parpadeo y un LED para enviar, y uno para recibir, por ejemplo).

A El monitor rs232 puede ayudarlo (necesitará algunos puertos adicionales para esto. Hay muchas aplicaciones (incluidas aplicaciones gratuitas) que pueden monitorear múltiples puertos rs232 y proporcionar marcas de tiempo. Para que pueda observar el orden de las comunicaciones. Google me encontró: link; he usado varios simil ar utilidades en los últimos años.

+0

Muchas gracias por su sugerencia Adriaan. Pero estoy confundido. Tuve la corazonada de que podría no estar funcionando debido al aspecto de bloqueo, pero pensé que la forma en que había escrito mis programas habría salido a su alrededor. Consulte Hago que el controlador envíe un mensaje mientras el programa de escritorio lo espera con un Receive() Luego el programa de escritorio verifica si el mensaje es aceptable (todo esto mientras el programa controlador está esperando Recibir) y luego envía una señal de mensaje de aceptación o rechazo del msg. El Receive() en el controlador que estaba bloqueado ahora está desbloqueado, ¿no? – CodeConfused

+0

Entonces, ¿no debería proceder con el resto del código? Eso es comprobar si el mensaje recibido es para aceptación o rechazo (durante este tiempo la computadora de escritorio está esperando con una recepción bloqueada) y luego enviar el mensaje de nuevo? Estoy seguro de que la comunicación asíncrona resolvería este problema como usted dijo, pero estoy en una fecha límite con este proyecto y nunca he intentado comunicación asincrónica. antes así que realmente apreciaría mucho si pudieras ayudar a resolver esto con sincronía! – CodeConfused

+0

ver la edición en la respuesta. – Adriaan

1

Su programa, tal como está escrito, debe enviar 4 bytes y luego leer 2 bytes. (Suponiendo que los registros que tiene son correctos, pero si lo hizo funcionar correctamente, entonces envíe 4 bytes de nuevo ... probablemente no está colgando en la parte de envío sino en el lado de recepción, ya que siempre estará esperando leer dos bytes, y si por alguna razón dos bytes no llegan al registro de entrada continuará esperando para siempre.

Es posible que cuando estresas el sistema (envío de bytes demasiado rápido) desbordes el búfer de entrada y acabas perdiendo un byte? nunca obteniendo dos bytes. y se estancará

  1. ¿Puedes depurar dónde te quedas atascado? ¿está de hecho en el bucle de recepción?
  2. ¿puede estrangular la transmisión desde la PC al micro para que pueda enviar manualmente un byte a la vez?
  3. ¿hay algún apretón de manos entre la interfaz micro y xbee? ¿puede eso ser estrangulado por el micro?
+0

Sí, Simon tiene razón, debería enviar 4 bytes, luego recibir 2 y así sucesivamente hasta que se reciba una determinada respuesta. Estoy bastante seguro de que el problema no se encuentra en la parte de recepción, simplemente porque los Xbees se iluminan al enviar o recibir. Así que puedo 'ver' que los 2 bytes del programa de escritorio han salido del escritorio y también pueden 'verlos' llegar al microcontrolador. el código simplemente no lo maneja después de eso. Intenté depurar manualmente enviando los bytes uno por uno como dijiste. Pero aun así no funcionó. – CodeConfused

+0

No estoy seguro del apretón de manos entre el micro y Xbee. Pero estoy bastante seguro de que no hay. – CodeConfused

+0

@CudeConfused, ¿Puedes determinar si/cuántas veces se está cambiando el bit de RI? De alguna forma cuando estás s terminando un byte algunas veces el bit RI no se está configurando. ¿Puede algo desencadenar el RI antes de despejarlo y perder el segundo byte? – simon

Cuestiones relacionadas