cómo convertir bytes en ASCII en lenguaje C

6

Estoy recibiendo bytes de mi UART como uint8. ¿Cómo convierto estos bytes en ASCII? Estoy usando Atmel 6.0 y mi microcontrolador es ATMega16L.

EDIT

Estoy usando un teléfono Android para enviar y recibir información a un módulo Wifi (RN-131) de las redes itinerantes. El módulo wifi se conecta al microcontrolador (atmega16L) a través de UART. Todo lo que el módulo wifi recibe del teléfono se transmite desde su UART. Del mismo modo, todo lo que se escribe en su UART se transmite a través de wifi.

Ahora, lo que estoy tratando de hacer es enviar una cadena desde el teléfono que se convierte en bytes. El código se muestra a continuación:

PrintWriter out = new PrintWriter(new BufferedWriter(new outputStreamWriter(socket.getOutputStream())), true);
out.println("Eclipse");

aquí, el ' BufferedWriter ' - construye un nuevo BufferedWriter, proporcionando un búfer de 8192 bytes. y ' PrintWriter ' Construye un nuevo PrintWriter sin su escritor objetivo. El parámetro autoFlush determina si el escritor de impresión descarga automáticamente su contenido al escritor de destino cuando se encuentra una nueva línea.

ahora para programar el microcontrolador, estoy usando AVR studio 6.0

uint8_t data;
char arr[32];
data = UDR;
length = strlen(data);
itoa(data, arr, 10);

Pero lo que recibo es "50, 53, 52" incluso cuando envío "Eclipse".

EDITAR el 20 de junio de 2012

Aquí está mi código hasta ahora. Nota: el código está escrito en AVR Studio 6.0, por lo que se ve un poco diferente a otros códigos escritos en AVR Studio 4.18.

/**************************************************
 *  Includes
 */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include "../../../../../../Program Files (x86)/Atmel/Atmel Studio 6.0/extensions/Atmel/AVRGCC/3.4.0.65/AVRToolchain/avr/include/avr/iom16.h"

/**************************************************
 *  Global Variables
 */
int trigger=0, length=0;
int i=0, n=0;
uint8_t data;
char arr[8];

/**************************************************
 *  Defines
 */
#define LED_PORT PORTA
#define RED_ON (PORTA | 0x01)
#define RED_OFF (PORTA & ~0x01)
#define YELLOW_ON (PORTA | 0x02)
#define YELLOW_OFF (PORTA & ~0x02)
#define GREEN_ON (PORTA | 0x04)
#define GREEN_OFF (PORTA & ~0x04)

/**************************************************
 *  Function Prototypes
 */
void initialize(void);                      
void time_display(void);

int main(void){
    initialize();

    while(1){
        //TODO:: Please write your application code

    }
}

void initialize(void){

    DDRA = 0x07; //PORTA pins 0,1,2 set as outputs
//  DDRD = 0x02; //PORTD pin 1 is output (TX) and pin 0 is input (RX)

    //Timer SETUP
    TCCR1A = 0x80; //OCR1A enable in CTC mode
    TCCR1B = 0x0C; //CTC mode, 256 prescale 
    TIMSK = 0x10; //CTC on OCR1A enabled, overflow disabled
    OCR1A = 2000; //OCR value set to get an interrupt every 1 second (15624)

    //USART SETUP
    UCSRA = 0x00; //no Frame Error, no parity error, no Data OverRun
    UCSRB = 0xE0; //receiver enable, transmitter enable (0x18)
    UCSRC = 0x8E; //Asynchronous USART mode, no parity, 1 stop bit, 8-bit character size, Data transmitted on rising edge and received on falling edge of the clock
    UBRRL = 51; //Baud rate of 9600bps
    UBRRH = 0;

    sei(); //Global interrupt enable
}

//timer capture interrupt
ISR(TIMER1_COMPA_vect){

}

ISR(USART_RXC_vect){
    LED_PORT = RED_ON;
    _delay_ms(100);

    for(int x=0; x<5; x++){
        arr[x] = UDR;
    }

    LED_PORT = RED_OFF;
    _delay_ms(100);

    trigger = 1;
}

ISR(USART_UDRE_vect){
    if(trigger >= 1){
        LED_PORT = GREEN_ON;
        _delay_ms(200);
        LED_PORT = GREEN_OFF;
        _delay_ms(200);

        UDR = data; //transmit the data
        trigger = 0;
    }
}
    
pregunta David Norman

2 respuestas

6

** EDITAR 19/06/2012 *************************************** ********************

Ok, así que después de agregar su código, he hecho algunos cambios para que lo intente (¡y entienda!)

En primer lugar, hemos declarado que la matriz de caracteres es volátil para que el compilador sepa que puede cambiar inesperadamente por una interrupción. Del mismo modo, hemos creado una variable para realizar un seguimiento de nuestra posición de índice en la matriz:

/**************************************************
 *  Global Variables
 */
int trigger=0, length=0;
int i=0, n=0;
uint8_t data;
volatile char arr[8];
volatile char arr_idx = 0;

A continuación, he editado el código de inicialización de UART según la hoja de datos de ATMega16L y sus comentarios:

//USART SETUP
UCSRA = 0x00; //no Frame Error, no parity error, no Data OverRun
UCSRB = 0xD8; //receiver enable, transmitter enable (0x18)
UCSRC = 0x86; //Asynchronous USART mode, no parity, 1 stop bit, 8-bit character size, Data transmitted on rising edge and received on falling edge of the clock
UBRRL = 51; //Baud rate of 9600bps (8MHz clock?)
UBRRH = 0;

Mire detenidamente la hoja de datos (página ~ 166). Creo que ahora he configurado correctamente el UART en función de sus comentarios. No voy a repasar cada bit, pero deberías. Haga preguntas si cree que cometí un error o si no recibe algo.

Finalmente, he editado tu rutina ISR:

ISR(USART_RXC_vect){
    arr[arr_idx] = UDR;
    arr_idx++;
    arr_idx %= 7; //make sure index stays within array

    trigger = 1;
}

Tenga en cuenta que, el ISR se ejecuta cada vez que se recibe un solo byte (o carácter). Esto significa que queremos procesar el carácter único (agregarlo a nuestra matriz), incrementar nuestra ubicación de índice y salir de él rápidamente para que estemos listos para el próximo carácter.

Ahora debes mirar arr [] a través del método que has estado usando y ver si ahora está recibiendo tus caracteres correctamente.

** FIN DE EDICIÓN ****************************************

Una opción es usar una de las bibliotecas disponibles incluidas en AVR Studio:

#include <stdlib.h>

y luego en algún lugar de tu código ...

char num2[5]; //create a buffer for the ascii string
itoa(num1,num2,10); //convert the integer (num1) to an ascii string (num2) in base 10

Si luego muestra esto en una pantalla LCD de caracteres, puede enviar la matriz num2 a la función de impresión lcd que está usando.

Si le preocupa el espacio de código, puede escribir fácilmente su propia función simple itoa (entero a ascii). Deberá tomar cada posición de "decenas" de su entero usando los operadores "/" y "%" y convertirla a ascii:

enlace

En la tabla anterior, puedes ver que una vez que agarras el valor de cada dígito (0-9), solo agrega 48 para convertirlo en la representación de caracteres ascii.

EDIT

Bien, así que después de agregar su información y asumir:

  • Ha inicializado correctamente la velocidad en baudios de UART, etc. en su ATMEGA
  • El código de Android está enviando con éxito los bytes ASCII a través de WiFi y fuera de su UART

Entonces el microcontrolador ya debería recibir estos caracteres como Ascii, y la función ITOA no es lo que se necesita aquí y, de hecho, desordenaría los datos de cadena que ingresan.

Aunque podría ser un montón de cosas diferentes ... ¿Cómo estás viendo los datos de uart que recibe tu microcontrolador?

    
respondido por el justing
4

Un carácter ASCII es simplemente un número de 8 bits que se muestra como un carácter cuando se llaman funciones como "printf" que están destinadas a mostrar caracteres.

En C, una cadena es una matriz de estos caracteres (o números de 8 bits) que termina con el valor 0 o "terminado en nulo".

Entonces, cuando envías una cadena como "Eclipse", ya estás enviando números. De hecho, esto es lo que parece cuando lo envías:

[69, 99, 108, 105, 112, 115, 101, 0]

Al pasar esto a printf , por ejemplo, se imprimirá "Eclipse". Note el terminador nulo. También tenga en cuenta que no necesita ninguna función para convertir esto.

itoa es una función utilizada para convertir números a su representación de cadena. Por ejemplo:

 char str[32];
 itoa(223, str, 10);
 printf("%s", str);

Esto imprimiría "223". Los valores numéricos reales que residen en str[] que sabemos con seguridad: [50, 50, 51, 0] . Desde su descripción, estoy bastante seguro de que esto no es lo que quiere.

No siempre asuma la codificación ASCII . Esta es una codificación de caracteres muy utilizada en el nivel de aplicación y desarrollo web: UTF-8 : estos caracteres no siempre son de 8 bits, algunos de ellos son de 16 bits para representar caracteres en otros idiomas, por ejemplo.

EDIT:

Hay algo que necesita saber sobre un periférico UART típico en un AVR (no pretende ser una declaración general para todos los UART en todas las unidades de juego, solo la familia que está usando). Funcionan de la siguiente manera: cuando entra un byte, se coloca en una ubicación de memoria de un solo byte: UDR : cuando realice una lectura de este registro, se borrará. ¿Se están recibiendo nuevos datos en el UART y todavía no ha leído este registro? Se va a sobrescribir con el nuevo valor. Aquí no se colocarán cuerdas enteras. Solo personajes solos. Todo esto se describe en la hoja de datos de su uC, le recomiendo que se familiarice con él.

Con suerte, eso te dará suficiente información para comprender por qué strlen(data) no funcionará. Si aún no está seguro de por qué, lea la hoja de datos, lea qué sucede cuando realiza esta asignación en C data = UDR; y también lea qué son los parámetros de strlen , y tenga en cuenta que uno de ellos es un < em> puntero a una cadena. Si no tiene un buen dominio de los punteros, le sugiero esto: enlace

Si todo esto te parece demasiado trabajo, entonces sugiero que escojas un Arduino. No me malinterpretes, sería increíble si pudieras captar todo esto y usar C simple en tu AVR, pero si hay demasiados vacíos en tu conocimiento en este momento, puede que sea un poco abrumador. / p>

Ahora, a lo que quieres lograr. Mencionó en su comentario que quería hacer un bucle hasta que obtenga una cadena completa de UART, almacenándola en un búfer, donde luego la procesará como un comando. De acuerdo. Totalmente factible, de hecho, una técnica algo común.

Aquí hay un código psuedo para ti:

i = 0;
char str[32];

while(forever) {
   if (data_byte_is_available) {
        if (i == 31)
             i = 0;
        str[i] = UDR;
        i++;
   }
   print(str);
}

Intente averiguar qué necesita hacer para una función data_byte_is_available . La ficha técnica es tu amiga. Además, ¿cómo estás mostrando lo que viene en la UART de la unidad de usuario? Sea lo que sea, sustituye el print que tengo con eso. Espero que no haya problemas con lo que estés usando allí ...

    
respondido por el Jon L

Lea otras preguntas en las etiquetas