USART

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi how can I use only the transmit function of the USART on Atmega16? i have tried Dean's tutorial on USART and it works fine. However I want to try and write data to the AVR EEPROM memory (from my C program) and then transmit that data through hyperterminal to my PC using the USART transmit only function. The data can be any constant like for e.g. one single character.I have a STK500 board.appreciate any help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just don't turn the receive on.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok here goes.. i tried the following:

#include "eeprom.h" //definitions for USART setup
 
uint8_t EEMEM byte_read= 0x45;

int main(void)
  {
    uint8_t SRAMbyte_collect;

     SRAMbyte_collect = eeprom_read_byte(&byte_read);

     USART_init();
     USART_transmit(SRAMbyte_collect);
   }

void USART_init() //setup USART in transmit mode
   {
       UCSRB |= (1 << TXEN);   // Turn on the transmission circuitry
       UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
       UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
       UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

   }

void USART_transmit(unsigned char SRAMbyte_collect)
   {

       while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
       UDR = SRAMbyte_collect; // Echo back the received byte back to the computer

    }

when i ran it, i checked my EEPROM and saw 45 in my EEPROM memory so that's working right. now i want to send this 45 to the hyperterminal through the AVR USART.

However, when i try to open up hyperterminal with 9600 baud rate nothing gets printed on the screen. when i ran a test program with just the USART, it ran fine at 9600 baud and i was able to echo all the characters i typed back in the hyperterminal window.
i am using 7.3728MHz. what am i missing?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can't see you defining BAUD_PRESCALE to anything. With 7.3728Mhz clock and 9600baud you should have BAUD_PRESCALE to 47.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
       UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes 

This is not strictly necessary since you are using the default values, but it doesn't hurt.

I would try just:

void main()
{
    USART_init();
    while(1)
    {
        USART_transmit('U');
    }
}

and see what you get. That will narrow it down to whether it is the USART or the eeprom stuff.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rg, I set the baud rate in my header file:

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((7372800/ (USART_BAUDRATE * 16UL))) - 1)

Steve, I am going to try just the basic loop. Will let you know what I get. Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok i tried just the transmit.

void main() 
{ 
    USART_init(); 
    while(1) 
    { 
        USART_transmit('D'); 
    } 
} 

and when I opened my hyperterminal, I got an "unable to open port" error. Then I hit the Call option and the hyperterminal screen was filled with D's. Is this because it is in a while loop? I tried it without the while loop to see if I got only one D character but that didnt work and all I got was a blank hyperterminal screen.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Call option and the hyperterminal screen was filled with D's. Is this because it is in a while loop?

Of course.
Quote:
I tried it without the while loop to see if I got only one D character but that didnt work and all I got was a blank hyperterminal screen.

Which means that the problem is probably hyperterminal missing the first character. I would drop hyperterminal, it sucks. Try Bray's terminal.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks that helped. However, I still need that while loop. I tried to change the baud rate and that did not work. What may be wrong? I tried reading out of the EEPROM now and its working but only in a while loop.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I tried to change the baud rate and that did not work

Your baud rate is fine. If it wasn't, it wouldn't work whether you had the while loop or not. Your focusing on what is wrong with the program, but there is obviously nothing wrong there. Your code is working, move on to something that uses it in a useful manner.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void USART_transmit(unsigned char SRAMbyte_collect) 
   { 

       while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
       UDR = SRAMbyte_collect; // Echo back the received byte back to the computer 

    } 

will return after one byte has been written to UDR.

int main(void) 
  { 
    uint8_t SRAMbyte_collect; 

     SRAMbyte_collect = eeprom_read_byte(&byte_read); 

     USART_init(); 
     USART_transmit(SRAMbyte_collect); 
   } 

So main() will return. This is strictly forbidden in embedded systems!
All compilers I know would jump to the reset-vector.

/Martin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
will return after one byte has been written to UDR.

Which is exactly what the OP intended.
Quote:
All compilers I know would jump to the reset-vector.

Which ones are those? I know that avr-gcc will do an implied while loop (though this has not always been true). I believe at least some of the other compilers for the AVR behave the same way. Though it is certainly safer to put one in. And in this case it is certainly not the problem. If it were doing that, then the OP would be getting repeated values.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

npat_avr wrote:
thanks that helped. However, I still need that while loop. I tried to change the baud rate and that did not work. What may be wrong? I tried reading out of the EEPROM now and its working but only in a while loop.

Have you allowed enough time for the power supply to the RS232 level converter to stablise?

There also needs to be a delay of at least one byte after enabling the USART or otherwise setting the TX pin to high, to ensure that the receiver is in sync.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I put a delay of 10s and still nothing on the TX.I will keep trying that.
I have a separate question: I am trying to send two bytes and I when I try to read it, I get only one byte. The spec. says the USART can transmit continuously. Do I need a delay between two bytes? This is still in the while loop.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok i got it to work but with one small problem. Here is my code:

#include "eeprom_header.h"
uint8_t EEMEM block_read [4] = {0x45,0x67,0x53,0x98};
uint8_t byte[4];

int main(void)
  {
    int i=0;
    uint8_t SRAMblock_collect[4];
    eeprom_read_block((void*)&SRAMblock_collect,(const void*)&block_read,4);

         USART_init();
        
           while(1)
            {
              for(i=0;i<5;i++)
               {
                 USART_transmit(SRAMblock_collect[i]);
 		
        
               }

 

              }

 

    }

void USART_init() //setup USART in transmit mode
   {
  
      UCSRB |= (1 << TXEN);   // Turn on the transmission and reception circuitry

      UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

      UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register

      UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

      }

void USART_transmit(uint8_t SRAMbyte_collect)
  {

	  _delay_ms(1000);

         while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it

	  _delay_ms(1000);

           UDR = SRAMbyte_collect; // Echo back the received byte back to the computer
 
  }

When I look at the hyperterminal, I am getting 0x45,0x67,0x53,0x98 and then a 0x5F for every frame. What is the 0x5F? Is that the string terminator?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your array has 4 elements, but you are sending 5 (elements 0 to 4). The for loop should be:

for(i=0;i<4;i++)
     _delay_ms(1000); 

You should not need either of these delays. If it doesn't work without them then there is something wrong outside of the AVR since there is absolutely nothing wrong with the code. At worst you would need a single delay before sending any byte in order to let the cpu frequency stabilize, but I doubt that that is your problem.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

damn I should have seen that loop counter..Thanks a lot for catching that. Its working like magic!!