Cómo enviar cadena en comunicación serie en AVR-C

Entonces, como dice el título, en lugar de enviar un byte de información a la vez, me gustaría poder enviar una cadena completa. Lo que traté de hacer fue que traté de poner la entrada del usuario en una matriz y hacer que se transmita cada elemento de esa matriz. Sin embargo, solo pude obtener las primeras letras para transmitir, no toda la matriz, aquí está mi código:

//tx serial
#include <avr/io.h> 

#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  


int main(void){  

    char ar[]= "hello";

    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //////////////// 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
    ////////////////////////////////////////////////////////////////
    int i = 0;

    while (1){  

    while (( UCSR0A & (1<<UDRE0))  == 0){};
        for (i = 0; i < strlen(ar); i++){ 
            UDR0 = ar[i]; 
        }
    }
}

¿Cuál sería el problema con esto?

Respuestas (3)

No estoy muy seguro, solo una suposición rápida. Tal vez deberías poner el while(UDRE0 == 0){}intermedio entre los caracteres de envío. Creo que es esperar hasta que se haya enviado un carácter.

for (i = 0; i < strlen(ar); i++){ 
   while (( UCSR0A & (1<<UDRE0))  == 0){};
   UDR0 = ar[i]; 
}
Tienes razón. Cada vez que actualice el registro 'UDR0', la MCU iniciará una nueva transmisión. Y depende del programador asegurarse de que el registro no se actualice hasta que el registro 'UDR0' esté vacío (el carácter se ha enviado); de lo contrario, habrá un "error de colisión de datos" y la MCU no enviará ninguno de ellos.
ok, quiere decir que dentro de mi ciclo for debería incluir otro ciclo de espera para esperar el registro antes de incrementar, eso tiene sentido gracias, probaré para ver si funciona lo antes posible
¡Así que probé tu código y funciona! Sin embargo, cuando lo hice, como era de esperar, siguió imprimiendo hola continuamente, sin embargo, hice que devolviera cero para que imprimiera hola una vez aquí está el código
Debería ver mi otra "respuesta" que solucionará el problema con la impresión continua de "hola". También le brinda mejores controladores/funciones para enviar caracteres y configurar el uart.
Me gustaría señalar que se while((está bloqueando y puede desperdiciar bastante "tiempo de CPU", generalmente más en velocidades de transmisión más bajas. El uso de interrupciones de transmisión le permitirá realizar la escritura "en segundo plano".

¡Así que probé tu código y funciona! Sin embargo, cuando lo hice, como era de esperar, siguió imprimiendo hola continuamente, sin embargo, hice que devolviera cero para que imprimiera hola una vez aquí está el código:

            //data_buffer 

            //tx serial

            #include <avr/io.h> 

            #define F_CPU 16000000 
            #define BUAD 9600 
            #define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  
            #define buffer_size 128
            #define boolen 0
            int main(void){  
                char br;
                char ar[]= "hello";
                char buffer[10]; 
                //High and low bits
                UBRR0H = (BUAD_RATE_CALC >> 8); 
                UBRR0L = BUAD_RATE_CALC; 
                //////////////// 
                //transimit and recieve enable
                UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
                UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
                ////////////////////////////////////////////////////////////////
                int i = 0;

                while (1){  
                /*while( (UCSR0A & (1<<RXC0))  == 0 ){}; 
                    br = UDR0;
                */

                while (( UCSR0A & (1<<UDRE0))  == 0){};

                        for (i = 0; i < strlen(ar); i++){ 
                            while (( UCSR0A & (1<<UDRE0))  == 0){};
                            UDR0 = ar[i]; 
                            if (i == (strlen(ar) - 1)){ 
                                return 0;
                            }
                        } 
                }

            }   

Me gustaría señalar que hay algunas variables aleatorias y cosas definidas que ni siquiera uso, simplemente ignórelas

Por cierto, otra pregunta, ¿cómo evitaría que el chip transmita continuamente, sin usar el retorno 0; en mi código? Porque quiero intentar enviar varias cadenas, a la vez, o poner la lógica de matriz en una función que luego puedo ejecutar después de que el usuario haga algo, como si el usuario escribe algo, cada vez que escribe algo, el chip transmitirá la matriz hola, alguna idea? ¿Tendría que usar las interrupciones tx?
Aquí hay otra cosa que quiero hacer. Quiero poder evitar que el chip transmita saludo sin el retorno 0; código. Estoy pensando en usar la interrupción TXCIEn. Pero estoy un poco confundido acerca de si esta interrupción se dispara, ¿se dispara cuando el registro está vacío o cuando está lleno?
No estoy seguro, pero (en arduino, supongo) si sales de main, comienza un comportamiento aleatorio.
FYI: con mi instalación de WinAVR (cadena de herramientas GNU C), tuve que agregar #include <string.h> debido a una advertencia que se produjo al construir que decía: advertencia: declaración implícita de la función 'strlen' advertencia: declaración implícita incompatible de incorporado función 'strlen'

Deberías hacer una nueva pregunta por cada otra pregunta que tengas... Pero bueno. El siguiente código (podría tener un poco de estilo arduino, pero podría ayudar al interrogador).

El Setupcódigo se ejecuta solo una vez, al comienzo de su programa. Genial para inicializar cualquier periférico y/o enviar un mensaje de saludo/rutina de inicio. El Loopcódigo se ejecuta continuamente, por lo general este contiene un programa como leds parpadeantes... o el sistema de seguridad de una central nuclear. Sin embargo, no está diseñado para ser devuelto, está diseñado para ejecutarse para siempre. Aunque mi código te atrapará en un rato (para siempre); si volvieras de ella.

No he probado el código, pero reconozco que sería este:

#include <avr/io.h> 
#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  

//Function definitions
void Setup(void);
void Loop(void);
void serialSetup(void);
void serialSend(char* sendString);

//Global variables.
char ar[]= "hello";

void Setup(){
//Code to be run once (At start).
    serialSetup();
    serialSend(ar);
}

void Loop(){
    //Code to be run continiously.
}

void serialSetup(){
    //Register settings
    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
}

void serialSend(char* sendString){
     for (int i = 0; i < strlen(sendString); i++){ 
         while (( UCSR0A & (1<<UDRE0))  == 0){};
         UDR0 = sendString[i]; 
     } 
}

int main(void){  
    Setup();
    while(1){
       Loop();
    }
while(1){}//If you ever return from Loop(); This while will catch you, so it won't continue doing randomness.           
}