USART in Atmega48

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

hi guys,

i am trying to get my USART to work in my lil' atmega48.

did the following already .

Quote:
void USART_init(unsigned int ubrr)
{
/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/*Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);

//Enable double speed
UCSR0A |= (1<<U2X0);

/* Set frame format: 8data (UCSZ00), 1stop bit(USBS) , Parity : none (UPM) */
UCSR0C &= ~(1<<UMSEL01) & ~(1<<UMSEL00) & ~(1<<UPM01) & ~(1<<UPM00) & ~(1<<USBS0) | (3<<UCSZ00);

}
//UART Transmission
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}

//UART Receiption
unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) )
;
/* Get and return received data from buffer */
return UDR0;
}

I would be running at a baud rate of 9600 using a 8N1 frame.

Now the problem is, i want to receive data/info from the hyperterminal (thru the serial port) to trigger some things on the atmega48. Data that would be sent from the hyperterminals are single characters.

How can i read these characters once i received them ?
can i use functions like getchar() ? how can i do that ?

thank you !
cheers

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

DOS had a kbhit() function that told you when there was a char waiting... all the old programmers that used Turbo Pascal and Turbo C write a kbhit() function.... it is just like getchar().... except it doesnt get the char... it just returns true if the status bit is set in the uart.
I guess unix was already invented at the point Gary Kildall wrote CPM and invented kbhit() so msdos could inherit it, but I'll be darned if I know how to do a kbhit() on unix, vms, or win32 (actually, it took me years to figure out how to do it in win32... I used to just read and write right to the ports in dos and win98... you have to use creatfile, readfile and writefile.... makes perfect sense in the inverse reality of microsoft I guess)

Imagecraft compiler user

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

ok i've done some reading around.
i've came up with this code but im not sure whether it will work cuz i am not sure about the arguments to use.

i just wanna read the character that was just received from the hyperterminal that is saved in the register UDR0.

Quote:
int main(void)
{
char returned;
returned = fdevopen(fgetc, UDR0);
}

is the above code correct ?
cuz from the manual it says

Quote:
If the get function pointer is provided, the stream is opened with read intent. The function passed as get shall take a pointer to FILE as its single argument, and return one character from the device, passed as an int type. If an error occurs when trying to read from the device, it shall return _FDEV_ERR. If an end-of-file condition was reached while reading from the device, _FDEV_EOF shall be returned.

in the fdevopen i used above , is the second argument correct ?

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

If you Google "fdevopen site:avrfreaks.net" (because the search here is broken) you hit loads of likely looking threads. This one contains a lof of the detail:

https://www.avrfreaks.net/index.p...

Bottom line is that you need to wire up printf/scanf to your get_char() and put_char() routines. Then you'll be able to read/write strings/numbers/whatever to your heart's content.

Cliff

PS and yes, Bob, this one does look like it's destined for GCC land :wink:

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

Is your problem knowing when the character is received, or actually reading it?

Knowing when it's received can be done by polling the appropriate register or setting up an interrupt to trigger when there's a character available.

As for actually reading it, you've already got the UART receive function. What else are you looking for?

Passing the register to the fdevopen function won't get you anywhere. If anything, you'll have to set up a FILE stream and pass that in. Something like:

FILE uart_read = FDEV_SETUP_STREAM( UART_receive, ... );

Not sure on exactly the parameters that go after ..., but that's the basic call. Then make sure UART_receive is a function that returns what the fdevopen is expecting. Then pass uart_read as the file handle when doing something like fscanf to read. For your case, it's probably much easier just to call UART_receive directly. Unless you want to process it with formatting that scanf provides, which is unlikely.

The file handle method is more useful for printing stuff out the uart, or to an LCD, as you can then make use of all the string formatting that printf provides.

In your case, I would either set up a polling loop in your main program to check the UART receive ready bit or set up an interrupt for UART receive, and then just call UART_receive directly when you detect a character there.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

i might have confused myself with using fdevopen when using the uart_putchar function in the manual.

my intent was just to read the character which is already there. So does it mean i can just read off whatever is stored in UDR0 ?

like

Quote:
char received = USART_receive();
if (received == 'c')
{ //code here
}

then what does like
fdevopen(uart_putchar,NULL,0) actually do ?
does this mean that stdio would use the put and get function i supply it with ?

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

I think the fdevopen is probably a red herring in this case (I was just reponding to your previous mention of it). As you may know a standard C library has some standard IO function calls (perhaps not surprisingly the ones given in stdio.h!). Functions such as printf() to output formatted output and scanf() to read formatted input. Now on a PC it's fairly clear what the source and destination of these should be by default (output to the console and input from the console keyboard). But in an embedded system where do you send the output (a UART, the LCD display, if UART, which one, etc.)? The fdevopen() mechanism in avr-libc gives you an opportunity to provide the ultimate output-a-character and input-a-character routines to be used by the standard library calls such as printf(), scanf() etc. It's then your choice as to whether you use the output-a-character routine you are providing to write to UART0, UART1, LCD, SPI, or whatever.

But I think you'll just complicate things and confuse yourself for this particular application - so for now pretend you never heard of "fdevopen" !

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
//------------------------
unsigned char kbhit(void){ 
//return true if char waiting
unsigned char b;
 
  b= UCSR0A & (1<<RXC0);  
  return b; 
} 

Imagecraft compiler user