2
\$\begingroup\$

So as the title states, instead of sending a byte of information at a time, I would like to be able to send a whole string. What I tried to do was that I tried to put the user input in an array and get each element of that array to be transmitted. However I was only able to get the first few letters to transmit not the whole array, here is my code:

//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]; 
        }
    }
}

What would the problem be with this?

\$\endgroup\$
7
\$\begingroup\$

Not quite sure, just a fast guess. Maybe you should put the while(UDRE0 == 0){} inbetween sending characters. I believe it's to wait until one character has been sent.

for (i = 0; i < strlen(ar); i++){ 
   while (( UCSR0A & (1<<UDRE0))  == 0){};
   UDR0 = ar[i]; 
}
\$\endgroup\$
  • 1
    \$\begingroup\$ You are right. Everytime you update 'UDR0' register MCU will start a new transmission. And its up to the programmer to ensure that the register will not get updated untill the 'UDR0' register is empty (character has been sent), otherwise there will be a "data collision error" and the MCU wont send either of them. \$\endgroup\$ – Golaž May 3 '15 at 12:13
  • \$\begingroup\$ ok so you mean within my for loop i should include another wait loop to wait for the register befor incrementing, that makes sense thank you, i will test to see if that works as soon as possible \$\endgroup\$ – Redrachet2 May 3 '15 at 19:24
  • \$\begingroup\$ So I tried your code and it works!! However when I did, as expected it kept printing out hello continuously however I made it return zero to make it print hello out once here is the code \$\endgroup\$ – Redrachet2 May 3 '15 at 21:09
  • \$\begingroup\$ You should see my other "answer" which will fix the issue with the continious "hello" printing. It also gives you some better handlers/functions for sending chars and setting up the uart. \$\endgroup\$ – Paul May 6 '15 at 15:05
  • \$\begingroup\$ I'd like to note that the while(( is blocking, and can waste quite some "CPU time", usually more on lower baudrates. Using transmit interrupts will allow you to perform the writing "in the background". \$\endgroup\$ – Paul Jun 7 '16 at 11:47
1
\$\begingroup\$

So I tried your code and it works!! However when I did, as expected it kept printing out hello continuously however I made it return zero to make it print hello out once here is the code:

            //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;
                            }
                        } 
                }

            }   

I would like to note the there are some random variables and things defined that I don't even use, just ignore them

\$\endgroup\$
  • \$\begingroup\$ BTW another question, how would I stop the chip from transmitting continuously, without using the return 0; in my code? Because I want to try to send multiple strings, at a time, or put the array logic in a function which then I can run after the user does something, like if the user types something, when ever they type something, the chip will transmit the array hello, any ideas? Would I have to use the tx interrupts? \$\endgroup\$ – Redrachet2 May 3 '15 at 21:18
  • \$\begingroup\$ Here is another thing I want to do. I want to be able to prevent the chip from transmitting hello with out the return 0; code. I am thinking about using the TXCIEn interrupt. But I am a bit confused about then this interrupt fires, does it fire when the register is empty or when it is full? \$\endgroup\$ – Redrachet2 May 3 '15 at 21:33
  • \$\begingroup\$ I'm not sure, but (on arduino I guess) if you exit from main, it starts random behaviour. \$\endgroup\$ – Paul May 4 '15 at 6:55
  • \$\begingroup\$ FYI - With my WinAVR installation (GNU C toolchain) I had to add #include <string.h> because of a warning occurring when building that stated: warning: implicit declaration of function 'strlen' warning: incompatible implicit declaration of built-in function 'strlen' \$\endgroup\$ – raddevus Jul 26 '16 at 20:02
0
\$\begingroup\$

You should make a new question for every other question you have... But well. The code below (Might be a bit arduino styled, but it might help the questioner).

The Setup code runs only once, at the start of your progam. Great to initialize any peripherals and/or send a hello message / startup routine. The Loop code runs continiously, usually this contains a program like blinking leds... or the security system of a nuclear powerplant. However, it's not designed to be returned from, it's designed to run forever. Though my code will catch you in a while(forever); if you were to return from it.

I haven't tested the code, but I recon it would be this:

#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.           
}  
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.