2009-08-01 14 views
6

Estoy haciendo que un microcontrolador 8051 se comunique de forma inalámbrica con una computadora. El microcontrolador enviará una cadena a su puerto serie (DB9) y la computadora recibirá esta cadena y la manipulará.¿Cómo puedo enviar una cadena en serie desde un 8051 solo UNA VEZ?

Mi problema es que no sé cómo hacer que el 8051 transmita la cadena solo una vez. Como necesito manipular la cadena en el extremo de la PC, debe ser recibida solo una vez. Actualmente, aunque en el código C estoy enviando la cadena una vez, en mi computadora estoy recibiendo la misma cadena continuamente. Supongo que esto se debe a que todo lo que está en el SBUF se transmite continuamente. ¿Hay alguna manera de que pueda enviar mi cadena solo una vez? ¿Hay alguna manera de vaciar el SBUF?

Intenté usar el pin RTS (Request to Send) (7º pin) en el DB9 porque leí en alguna parte que si negaba el voltaje en ese pin, detendría el flujo de datos al puerto serie. Entonces, lo que hice fue programar mi microcontrolador para enviar la cadena y luego enviar el nivel lógico 0 a un pin de salida que estaba conectado a mi pin DB9 RTS. Sin embargo, eso no funcionó.

¿Alguien tiene alguna sugerencia? Realmente los apreciaría.

EDITAR

El software que estoy usando en el PC es X-CTU para los módulos Xbee. Este es el código en mi microcontrolador:

include reg51.h 
void SerTx(unsigned char); 
void main(void) 
{ 
    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    SerTx('O'); 
    SerTx('N'); 
    SerTx('L'); 
    SerTx('Y'); 

} 

void SerTx(unsigned char x) 
{ 
    SBUF = x; 
    while(TI==0); 
    TI = 0; 
} 

Podría alguien por favor compruebe que es en realidad sólo una vez que el envío de la cadena?

EDITAR

Parece que Steve, brookesmoses y Neil dio en el clavo en la cabeza cuando me dijeron que era lo que ocurría después de mi función principal que estaba causando el problema. Acabo de probar el código sugerido por Steve (más específicamente el for (;;) y la definición de serTX fuera de main) y funcionó perfectamente. Es probable que el controlador se haya reiniciado y, por lo tanto, el mismo código sigue repitiéndose.

¡Muchas gracias por la ayuda! :)

+0

El software que estoy usando en la PC es X-CTU para módulos Xbee. Este es el código en mi microcontrolador: #include void SerTx (unsigned char); void main (void) { \t TMOD = 0x20; \t TH1 = 0xFD; \t SCON = 0x50; \t TR1 = 1; \t \t \t SerTx ('O'); \t SerTx ('N'); \t SerTx ('L'); \t SerTx ('Y'); \t void SerTx (unsigned char x) { \t SBUF = x; \t while (TI == 0); \t TI = 0; } } ¿Alguien podría verificar que de hecho solo está enviando la cadena una vez? – CodeConfused

+0

Edite su pregunta e inserte el código, formateado como código, para que sea más fácil de leer. –

+0

@CodeConfused: ¡Me alegra que todos hayamos encontrado una solución! Tengo dos solicitudes más para ti. (1) Para esta pregunta, y todas sus otras preguntas sobre Stack Overflow, marque una respuesta como "aceptada" haciendo clic en la marca grande por la que cree que proporciona la mejor respuesta a su pregunta. Esto es útil para otras personas que pueden tener la misma pregunta en el futuro, ya que de inmediato pueden ver la mejor respuesta. (2) En esta pregunta, formatee el código como código. Para hacerlo, edite la pregunta, seleccione el código y presione el botón de código (es el botón con 1s y 0s en él). Gracias. –

Respuesta

6

¿Puede confirmar que el 8051 realmente está enviando los datos solo una vez? Una manera de verificarlo sería usar un alcance para ver qué está sucediendo en el pin TX de UART.

¿Qué software está utilizando en la PC? Sugiero usar un software de comunicaciones simple como HyperTerminal o PuTTY. Si muestran la cadena que se envía a la PC varias veces, entonces es probable que la falla esté en el software que se ejecuta en el 8051.

EDIT: Para ser honesto, esto suena como el tipo de depuración que los ingenieros tienen que hacer frente de forma regular, por lo que es una buena oportunidad para que usted practica una buena pasada de moda metódica resolución de problemas.

Si puedo ser muy contundente, le sugiero que haga lo siguiente:

  1. depuración. Pruebe las cosas, pero no adivinar. Experimentar. Haga pequeños cambios en su código y vea qué sucede. Prueba todo lo que puedas pensar Busque en la web para obtener más información.
  2. Si eso no produce una solución, regrese aquí y bríndenos toda la información que necesitamos. Eso incluye piezas pertinentes del Código, todos los detalles del hardware que está utilizando, y la información acerca de lo que se trató en el paso 1.

EDIT: no tengo el representante de editar la pregunta, así que aquí está el código publicado por la OP en el comentario a la pregunta:

#include<reg51.h> 

void SerTx(unsigned char); 

void main(void) 
{ 
    TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1; 
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y'); 

    void SerTx(unsigned char x) 
     { SBUF = x; while(TI==0); TI = 0; } 
} 

Como Neil y Brooksmoses menciona en sus respuestas, en un sistema embebido, la función principal nunca se le permite dar por terminado. Por lo tanto, debe colocar el código en un bucle infinito (que puede ser lo que está sucediendo inadvertidamente), o agregar un bucle infinito al final, de modo que el programa se detiene de manera efectiva.

Además, la función SerTx debe definirse fuera de main. Esto puede ser sintácticamente correcto, pero mantiene las cosas simples para no declarar funciones dentro de otras funciones.

Así que trate de esto (También he añadido algunos comentarios en un intento de hacer que el código sea más fácil de entender):

#include<reg51.h> 

void SerTx(unsigned char); 

void main(void) 
{ 
    /* Initialise (need to add more explanation as to what 
     each line means, perhaps by replacing these "magic 
     numbers" with some #defines) */ 
    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    /* Transmit data */ 
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y'); 

    /* Stay here forever */ 
    for(;;) {} 

} 

void SerTx(unsigned char x) 
{ 
    /* Transmit byte */ 
    SBUF = x; 

    /* Wait for byte to be transmitted */ 
    while(TI==0) {} 

    /* Clear transmit interrupt flag */ 
    TI = 0; 
} 
+0

Estoy usando módulos Xbee, Steve, entonces el software en la PC es X-CTU. Sin embargo, traté de solucionar problemas usando Hyperterminal también. Lo mismo ocurre con eso, es decir, la cadena se recibe continuamente. – CodeConfused

+0

¡Absolutamente usted puede ser muy directo, Steve! :) ¡Cualquier cosa que ayude! Tu código hizo el truco, muchas gracias. P.S. TI = 0 no es exactamente para desactivar el transmisor. TI tiene que ser forzado a cero porque después de la transmisión de un personaje, el 8051 levanta la bandera de TI para indicar que está listo para más transmisión. – CodeConfused

2

Es difícil decir cuál es el problema sin ver a ninguno de los códigos 8051. Por ejemplo, un error lógico en ese lado podría provocar que los datos se envíen varias veces, o el software 8051 podría estar esperando un ACK que nunca se recibe, etc.

Normalmente, en un código 8051 debe enviarse explícitamente cada uno personaje, pero supongo que esto se ocupará de ti en el tiempo de ejecución de C.

El uso de RTS/CTS (Solicitud de envío/Borrar para enviar) es para control de flujo (es decir, para evitar saturaciones de búfer, los búfers suelen ser bastante pequeños en estos microcontroladores) y no para detener la transmisión por completo.

6

El código que envió tiene ningún bucle en main(), por lo que necesita determinar qué tiempo de ejecución C de su compilador hace cuando main() regresa después de enviar 'Y'. Dado su problema, me imagino que el compilador genera algún código para hacer algunas tareas de limpieza y luego reiniciar el micro (tal vez un reinicio de hardware, tal vez simplemente reiniciar el tiempo de ejecución de C). Parece que su programa funciona exactamente como lo ha escrito, pero ha ignorado lo que sucede antes y después de llamar a main().

Si desea que su cadena se envíe una vez y solo una vez, entonces necesita agregar algo como while(1) {} después de enviar el último carácter. Pero, entonces su programa no está haciendo nada, solo ejecutará un bucle vacío para siempre. Se necesita reiniciar (como ciclos de encendido) para comenzar de nuevo y enviar la cadena.

Tenga en cuenta que si su micro tiene un temporizador de vigilancia, podría intervenir y forzar un reinicio inesperado. Si esto sucede, su cadena se enviará una vez por cada reinicio del perro guardián (que podría ser algo así como una vez cada segundo, con la tasa en función de su hardware).

Además, tener serTx() definido anidado dentro de main() probablemente no sea lo que desea.

+0

Gracias Neil, tenías toda la razón. Pero, ¿hay alguna manera de que salga del bucle vacío sin involucrar hardware? – CodeConfused

+0

P.S. No creo que mi micro tenga un temporizador de vigilancia. – CodeConfused

+0

Supongo que la respuesta simple es: hacer que el ciclo haga algo. El firmware incorporado generalmente tiene un bucle principal que se ejecuta para siempre. Este bucle sondearía el hardware para ver si quedaba algo por hacer, como los datos nuevos de un puerto en serie o una entrada digital modificada, y luego llamaría a una función apropiada para manejar ese evento. – Neil

2

Haciendo eco de la respuesta de Neil (en una respuesta, ya que aún no tengo el representante para comentar): en una situación típica de microcontrolador sin sistema operativo, no está claro inmediatamente cuál es la función exit() que recibe implícitamente el end of main() debería hacer - o, más exactamente, no puede hacer lo usual "terminar el programa y regresar al sistema operativo", porque no hay sistema operativo al que regresar.

Además, en una aplicación real, casi nunca desea que el programa simplemente pare, a menos que apague el sistema. Entonces, una cosa que la implementación de exit() definitivamente no debería hacer es tomar mucho espacio de código.

En algunos sistemas en los que he trabajado, exit() en realidad no está implementado en absoluto; si no vas a usarlo, ¡no desperdicies ni un byte! El resultado es que cuando la ruta de ejecución llega al final de main(), el chip simplemente se desvía hacia un terreno de ejecución de lo que sea que esté en el siguiente bit de memoria, y típicamente termina rápidamente o atascado en un bucle o fallando con un código de operación ilegal. Y el resultado habitual de una falla con un código de operación ilegal es ... reiniciar el chip.

Parece una teoría plausible de lo que está sucediendo aquí.

+0

Gracias brooksmoses. ¡Lo explicaste muy bien!Y creo que eso es exactamente lo que estaba pasando aquí. – CodeConfused

Cuestiones relacionadas