Enviar enteros desde 8051 UART

0

Tengo un contador que cuenta el número de interrupciones en el pin 3.2 en 8051. No estoy seguro de la implementación. Hasta ahora podía contar el número de interrupciones pero no podía enviar el valor entero en UART. Me está dando los valores ASCII en realidad. Sé que SBUF = 'A'; enviará un valor ASCII de 'A'. ¿Cómo enviar los enteros? Este es mi código que he estado tratando de hacer que funcione.

#include<reg51.h>
#include<stdio.h>
#include<stdlib.h>

/* function prototypes */
void delay(unsigned int ms);
void putc1( chr);
void windspeed_read( void);
void initialize(void);
void record_wind(unsigned char counter);
void puts1(char* p);

sbit P3_2 = P3^2;
sbit P3_3 = P3^3;

// global variables declared
unsigned char c = 0;
char *ptr;
int i;

char buf[16];
char *p;

/* delay function to create a delay of 1 sec */
void delay(const unsigned int ms)
{
 unsigned int x;
 unsigned int y;
 for (x = 0; x < ms; x++)
 {
 for (y = 0; y <= 113; y++)
 ;
 }
}

/* to print the character in UART and serial window*/
void putc1( c)
{
   SBUF = c;
   while(TI==0);            /*Wait until the character is completely sent */
   TI=0;                   /*Reset the flag */
}

/* main function */
void main()
{
IE = 0x81;
EX0 = 1;
EA = 1; 
while (1)
{
}
}
void initialize()
{
 SCON  = 0x50;   /*SCON: mode 1, 8-bit UART, enable receive      */ 
 TMOD |= 0x20;   /*TMOD: timer 1, mode 2, 8-bit                  */
 TH1   = 0xFD;   /*TH1:  for 9600 baud                           */
 TR1   = 1;      /*TR1:  timer 1 run                             */ 
}

void windspeed_read( void ) interrupt 0
{
c++;

sprintf(buf, "%d", c);
p = buf;
while(*p)
{
    P2 = *p;
   putc1(*p++);
}
}
    
pregunta d-coder

1 respuesta

2

La llamada existente a sprintf parece ser la forma correcta de hacer el formateo del número, ya que parece que stdio.h está disponible. El búfer buf debe contener "0", "1", "2", etc. Pero no está claro si eso está sucediendo o no ...

Un buen primer diagnóstico es agregar un mensaje de banner, para probar si el enlace serial 8051 está funcionando. Tal vez el puerto serie no estaba siendo inicializado? Tal vez el software del terminal está configurado a la velocidad de transmisión incorrecta? ¿O tal vez el cable serial es defectuoso?

Como segundo diagnóstico, intente imprimir un valor numérico constante y conocido. Código sugerido edita abajo:

char[] szBannerMessage = "\r\n""Hello from 8051""\r\n"; // [MarkU] test message
/* main function */
void main()
{
    initialize(); // [MarkU] -- looks like initialize() wan't being called?
    // [MarkU] -- test serial port by sending a string message
    p = szBannerMessage; puts_p();
    // [MarkU] -- test sprintf decimal number formatting
    sprintf(buf, "%d\n", 231);
    p = buf; puts_p();
    IE = 0x81;
    EX0 = 1;
    EA = 1; 
    while (1)
    {
    }
}

// [MarkU] -- put string.  @pre global char* p points to null-terminated C string.
// encapsulated d-coder's existing code
void puts_p(void)
{
    while(*p)
    {
        P2 = *p; // diagnostic: also send character to port P2.7..P2.0
        putc1(*p++);
    }
}

Con estas ediciones, cada vez que se reinicie el 8051, su firmware debería enviar:

Hello from 8051
231

Si no ves aparecer ninguna de estas dos líneas en la ventana de tu terminal, hay un problema con el enlace serial.

  • reinicia el 8051 pero manténlo encendido. Tal vez el reloj no sea estable cuando se enciende por primera vez?
  • ¿el software del terminal está configurado a la velocidad de transmisión incorrecta?
  • ¿El cable serie está defectuoso?

Si solo ve la primera línea pero no el 231 , entonces el puerto serie está funcionando, pero por alguna razón, el sprintf(buf, "%d", c) no está formateando el número.

  • verifique el listado, ¿se ha declarado buf [] en el espacio de dirección de memoria correcto?

Otros diagnósticos: vea si su compilador de C genera una lista de ensamblaje de las instrucciones reales de 8051, y un archivo de mapa que muestra dónde están todas las funciones y variables. El 8051 tiene varios espacios de direcciones, por lo que los compiladores de C que tienen como destino 8051 tienen extensiones para indicar a qué espacio de direcciones pertenece cada variable. Además, verifique si el enlazador está apuntando a la variante de 8051 correcta. Esta arquitectura de microcontrolador ha existido durante décadas, y hay muchas variaciones. Si el compilador está creando código para un chip de 65K y está colocando datos en una memoria externa (xram), pero el chip de destino es un chip de 2k más pequeño sin xram, eso no va a funcionar.

Sobre el controlador de interrupciones. A largo plazo, sería una mejor práctica evitar el envío de cadenas de puerto serie dentro del controlador de interrupción, ya que las rutinas de servicio de interrupción generalmente tienen la intención de responder rápidamente a una condición de hardware y regresar a la tarea de primer plano lo más rápido posible. Enviar un personaje a través del puerto serie es relativamente lento, por lo que el 8051 pasará mucho tiempo en la interrupción. Es bastante común que una rutina de interrupción simplemente capture los registros de hardware y establezca una marca global, para que el bucle while principal se ocupe de ello más adelante. Además, las rutinas de puerto serie a veces se implementan utilizando interrupciones, por lo que en ese tipo de sistema es importante evitar usar el puerto serie desde otro controlador de interrupciones, ya que el procesador ya está manejando una interrupción y no puede administrar otra hasta la primera. Vuelve y el 8051 sale del modo de interrupción. Pero como la tarea principal es un bucle vacío y la rutina en serie no usa interrupciones, no debería haber conflicto en este caso.

    
respondido por el MarkU

Lea otras preguntas en las etiquetas