Вы находитесь на странице: 1из 95

serialCOM

Components Required
Hardware: ATMEGA8 (2 pieces), power supply (5v), AVR-ISP
PROGRAMMER, 100uF capacitor (connected across power
supply), 1KΩ resistor (two pieces), LED , Button.
Software: Atmel studio 6.1, progisp or flash magic.
PROGRAM ON TRANSMITTER SIDE:
#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 1000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program

int main(void)
{
DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
PORTD |= 1 << PIND0;

int UBBRValue = 25;//AS described before setting baud rate

//Put the upper part of the baud number here (bits 8 to 11)
UBRRH = (unsigned char) (UBBRValue >> 8);

//Put the remaining part of the baud number here


UBRRL = (unsigned char) UBBRValue;
//Enable the receiver and transmitter
UCSRB = (1 << RXEN) | (1 << TXEN);

//Set 2 stop bits and data bit length is 8-bit


UCSRC = (1 << USBS) | (3 << UCSZ0);

while (1)
{
if (bit_is_clear(PINC,0))//once button is pressed
{

while (! (UCSRA & (1 << UDRE)) );


{
UDR = 0b11110000;//once transmitter
is ready sent eight bit data
}

// Get that data outa here!

_delay_ms(220);
}

PROGRAM ON RECEIVER SIDE:


#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main(void)
{
DDRD |= (1 << PIND0);//PORTD pin0 as INPUT
DDRC=0xFF;//PORTC as OUTPUT

int UBRR_Value = 25; // 2400 baud rate


UBRRH = (unsigned char) (UBRR_Value >> 8);
UBRRL = (unsigned char) UBRR_Value;
UCSRB = (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << USBS) | (3 << UCSZ0);

unsigned char receiveData;


while (1)
{
while (! (UCSRA & (1 << RXC)) );

receiveData = UDR;

if (receiveData == 0b11110000)
{
PORTC ^= (1 << PINC0);
_delay_ms(220);
}
}
}

Yang LAEN :

Yeah, I just straight copy/pasted the code and hit compile. I'm sure it's
probably something not so subtle causing the problem, but my newbie
experience just can't point it out to me.
#include

#define USART_BAUDRATE 9600

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

int main (void)

char ReceivedByte;
UCSRB |= (1 << RXEN) | (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

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the recieved byte value into the


variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is


ready for more data to be written to it

UDR = ReceivedByte; // Echo back the received byte back to the


computer

Using the USART with AVR-GCC


Freaks,
I've had this three-quarters finished and sitting on my hard drive since mid-
last year, so I decided to finish it and post here for the benefit of others. I'm
the first to admit it's not very clearly written, so I may re-write it in the
future. Comment away.
This tutorial will focus on setting up the serial USART on the AVR platform.
Although other hardware AVR interfaces (eg, USI) can be configured for
limited RS-232 serial transmission and reception such alternatives will not be
covered.
What is the USART?
The vast majority of devices in the current AVR family lineup contain a
USART hardware subsystem. The USART hardware allows the AVR to
transmit and receive data serially to and from other devices - such as a
computer or another AVR.
The USART transmission system differs to most other digital busses in that it
does not utilize a separate pin for the serial clock. An agreed clock rate is
preset into both devices, which is then used to sample the Rx/Tx lines at
regular intervals. Because of this, the USART requires only three wires for bi-
directional communication (Rx, Tx and GND).
The RS-232 Specification
The serial USART is frequently referred to as RS-232, which is a reference to
the RS-232 specification which mandates the logic levels and control signals.
While the AVR's normal logic levels are about 3-5V, RS-232 communication
uses a low of +3V to +25V for a digital '0', and -3V to -25V for a digital '1'.
If the two USART devices are running at AVR logic levels, the Tx and Rx pins
can be connected together directly. If the devices are using RS-232 spec.
voltages, a level converter is needed.
This tutorial will assume the user is attempting to interface with a computer
RS-232 port, which uses the proper RS-232 specification logic levels.
First things first - Setting up the Hardware
To connect your AVR to a computer via the USART port, you will need to add
a level converter to your existing circuit. The most common/popular serial
level converter is the Maxim MAX232 (datasheet avaliable here). This small
and relatively inexpensive IC will convert your AVR's 5V logic levels to 10V
RS-232 and vice versa.
Before you can hook up your MAX232, you need to first identify which pins of
your AVR are responsible for serial communication. Looking in your AVR's
datasheet, you should be able to identify the two serial port pins (named as
alternative pin functions TX and RX).
You should wire up your MAX232 to reflect the schematic here. This will
enable your AVR's USART hardware to interface with the computer's USART
hardware.
Deciding on your AVR's system clock frequency
As mentioned above, the USART does not use an external clock. To allow the
two interfaced devices to communicate together, you need to decide on a
baud rate for communication. Also due to the timing-critical nature of the
USART, your system's clock should be stable and of a known frequency. The
AVR's system clock frequency is very important. The USART clock is derived
from the system clock, and it is used to sample the Rx line and set the Tx
line at precise intervals in order to maintain the communication.
If the system clock cannot be precisely divided down to a "magic" frequency
for perfect communications, it will have a percentage error (where a byte
fails to be read or written inside designated time frame). System clocks for
perfect USART communications should be multiples of 1.8432MHz which
when used will give a 0.00% error.
Other frequencies for the main AVR clock can be used, but as the frequency
drifts from the "perfect" multiples of 1.8432MHz, the greater the percentage
error will be (and thus the less reliable the serial communication will be). It is
generally accepted that error percentages of less than +/- 2% are
acceptable.
Looking in your AVR's datasheet in the USART section you should see a table
of common baud rates, system clocks and error percentages. You should find
a combination which suits your project's constraints and has the lowest
possible error percentage.
I will be basing the rest of this tutorial on an example setup; a MEGA16
running at 7.3728MHz and a baud rate of 9600bps (bits per second). This
combination, because it uses a system clock which is a multiple of the magic
1.8432MHz, has an error percentage of 0.00%).
Initializing the USART
Now you should have selected a baud rate, system clock and have your AVR
set up with a RS-232 level converter - you're all set to go! All you need is the
firmware to drive it.
First off, you need to enable both the USART's transmission and reception
circuitry. For the MEGA16, these are bits named RXEN and TXEN, and they
are located in the control register UCSRB. When set, these two bits turn on
the serial buffers to allow for serial communications:
#include

int main (void)

UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission


and reception circuitry

Next, we need to tell the AVR what type of serial format we're using. The
USART can receive bytes of various sizes (from 5 to 9 bits) but for
simplicity's sake we'll use the standard 8-bits (normal byte size for the AVR).
Looking again at the MEGA16 datasheet, we can see that the bits responsible
for the serial format are named UCSZ0 to UCSZ2, and are located in the
USART control register C named UCSRC.
The datasheet very handily gives us a table showing which bits to set for
each format. The standard 8-bit format is chosen by setting the UCSZ0 and
UCSZ1 bits. Before we write to the UCSRC register however, note a curious
peculiarity in our chosen AVR, the MEGA16. To save on register addresses,
the UCSRC and UBRRH registers (the latter being explained later in this text)
share the same address. To select between the two, you must also write the
URSEL bit when writing to UCSRC:
#include

int main (void)

{
UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission
and reception circuitry

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


character sizes - URSEL bit set to select the UCRSC register

The URSEL bit does not exist in all AVR models; check your chosen AVR's
datasheet.
There, we're almost done setting up the USART! The last thing to set for
basic serial communications is the baud rate register. This register sets the
clock divider for the USART which is used as a timebase to sample the
incoming data at the correct frequency. It also gives the timebase for
sending data, so it's vital for RS-232 serial communications.
The baud rate register is 16-bit, split into two 8-bit registers as is the case
with all 16-bit registers in the AVR device family. To set our baud rate
prescaler value, we first need to determine it. Note that the baud rate
register value is NOT the same as the baud rate you wish to use - this is a
common point of failure amongst those new to the serial subsystem. Instead,
the value must be derived from the following formula:
BaudValue = (((F_CPU / (USART_BAUDRATE * 16))) - 1)
Where F_CPU is your AVR's system clock frequency (in Hz), and
USART_BAUDRATE is the desired communication baud rate.
Given my example project using a system clock of 7372800Hz and a baud
rate of 9600, our formula gives:
BaudValue = (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) BaudValue =
(7372800 / (9600 * 16) - 1)
BaudValue = (7372800 / 153600 - 1)
BaudValue = (48 - 1)
BaudValue = 47
To make our life easier, we can turn this formula into a set of handy macros.
F_CPU is automatically defined in AVR-GCC via your makefile, so all that is
needed is the baud rate:
#define USART_BAUDRATE 9600

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

This avoids "magic numbers" (unexplained constants) in our source code,


and makes changing the baud rate later on very easy - just change the
BAUD_RATE macro value. Now, we need to load this into the baud rate
registers, named UBRRH (for the high byte) and UBRRL (for the low byte).
This is simple via a simple bitshift to grab the upper eight bits of the
BAUD_PRESCALE constant:
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register

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

Now we're ready to rock and roll!


Sending and receiving data
Once initialized, we're ready to send and receive data. We do this by the
special register named UDR - short for "USART I/O Data Register". This is
special for two reasons; it behaves differently when it is read or written to,
and it is double buffered.
By assigning a byte to the UDR register, that byte is sent out via the AVR's
Tx line. This process is automatic - just assign a value and wait for the
transmission to complete. We can tell when the transmission is complete by
looking at the transmission completion flag inside the USART control
registers.
On the MEGA16, the Transmission Complete flag is located in the control
register UCSRA, and it is named TXC. Using this information we can construct
a simple wait loop which will prevent data from being written to the UDR
register until the current transmission is complete:
UDR = ByteToSend; // Send out the byte value in the variable
"ByteToSend"

while ((UCSRA & (1 << TXC)) == 0) {}; // Do nothing until transmission


complete flag set

However this is non-optimal. We spend time waiting after each byte which
could be better spent performing other tasks - better to check before a
transmission to see if the UDR register is ready for data. We can do this by
checking the USART Data Register Empty flag instead (called UDRE), also
located in the UCSRA control register of the MEGA16:
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready
for more data to be written to it

UDR = ByteToSend; // Send out the byte value in the variable


"ByteToSend"

This is much better, as now time is only wasted before a transmission if the
UDR register is full. After a transmission we can immediately continue
program execution while the UDR byte is sent, saving time.
Now we can move on to receiving data. As mentioned before, the UDR
register behaves differently between read and write operations. If data is
written to it it is sent out via the AVR's Tx pin, however when data is
received by the RX pin of the AVR, it may be read out of the UDR register.
Before reading the UDR register however, we need to check to see if we have
received a byte.
To do this, we can check the USART Receive Complete (RXC) flag to see if it
is set. Again, this is located in the UCSRA control register of the MEGA16:
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have
been received and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the received byte value into the variable
"ReceivedByte"

Putting it all together


Right! Now it's time to put everything together! Let's make a simple program
that echoes the received characters back to the computer. First, the basic
program structure:
#include

int main (void)

Next, our USART initializing sequence:


#include

#define USART_BAUDRATE 9600

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

int main (void)

UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission


and reception circuitry

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


character sizes

UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud


rate value into the high byte of the UBRR register

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate


value into the low byte of the UBRR register

Now, an infinite loop to contain our echo code:


#include

#define USART_BAUDRATE 9600

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


int main (void)

UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission


and reception circuitry

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


character sizes

UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud


rate value into the high byte of the UBRR register

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate


value into the low byte of the UBRR register

for (;;) // Loop forever

And some echo code to complete our example. We'll add in a local variable
"ReceivedByte", which will always hold the last received character from the
computer:
#include

#define USART_BAUDRATE 9600

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

int main (void)

char ReceivedByte;
UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission
and reception circuitry

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


character sizes

UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud


rate value into the high byte of the UBRR register

UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate


value into the low byte of the UBRR register

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing


until data have been received and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the received byte value


into the variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing


until UDR is ready for more data to be written to it

UDR = ReceivedByte; // Echo back the received byte back


to the computer

And voila, we have a working serial example! Connect to this project via a
serial terminal on your computer, using 8-bit, no parity 9600 baud
communication settings and it will echo back anything you send to it.
Potential Pitfalls
There are several "gotchas" when dealing with the USART. First, make sure
your AVR is running of a reliable, known clock source with a low error
percentage at your chosen baud rate. New AVRs default to their internal
oscillators until their fuses are changed. The internal RC oscillator is of
too low a tolerance for use with the USART without external
calibration.
Check your datasheet to check for the locations of the different flags.
Different AVRs have the control flags located in different control registers
(UCSRA, UCSRB and UCSRC).
Make sure your computer terminal is connected at the exact settings your
AVR application is designed for. Different settings will cause corrupt data.
Cross your Rx and Tx wires. Your PC's Rx line should be connected to your
AVR's Tx line and vice-versa. This is because the Rx/Tx lines are labeled
relative to the device they are marked on.
Some AVRs do not have the URSEL bit to differentiate between the UCSRC
and UBRRH registers - check your datasheet.
Advanced serial communication
A more advanced method of serial communication involves the use of the
USART interrupts and is not covered here. I may cover it in a later tutorial if
so desired.
For an updated version of this tutorial in PDF format, please see this
page of my website.
- Dean :twisted:

Ini lagi:

#include <avr/io.h>

int main (void)


{
char ReceivedByte;

UCSR1B = 0x18; //enable tx


UCSR1C |= (1 << UCSZ1); //use
8-bit character sizes

UBRR1L = 0x2F; //baud rate


UBRR1H = 0x00;

for (;;) //loop fore


{
while ((UCSR1A & (1 << RXC1)) == 0) {}; //do nothing until
data have been recieved and is ready to be read from UDR
ReceivedByte = UDR0;
//fetch the recieved byte value into the variable "ByteReceived"

while ((UCSR1A & (1 << UDRE1)) == 0) {}; //do nothing until


UDR is ready for more data to be written to it
UDR1 = ReceivedByte; //echo back
}
}

i'm using atmega8535 and atmega16


i want to input character from computer
then it will execute led on,example in PORTA.0
if i input another character,it will execute another program,example led will
off or whatever
i confuse for the C language code program....
anyone help me??
give me that code program....
I am a beginner but maybe this will help. I am using an Atmega16. It waits
for a single character command from the PC and then returns data to the PC.
In this example it waits for an "S" from the computer.
#define USART_BAUDRATE 9600

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

void ConfigureDevice(void)

UCSRB |= (1 << RXEN) | (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

int main (void)

ConfigureDevice();

char ReceivedByte;

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the recieved byte value into the


variable "ByteReceived"
// if received an "S"

if (ReceivedByte == 83) {

// do something here

// turn on led or whatever you want

hi Dean
about your previous reply :"The demo application just echoes back the sent
bytes, so all you need is a terminal application on your computer which can
send and receive serial data."
to confirm with you, the sent bytes is it any data to be sent from micro
controller to the computer?
after building the code that you have written, where should i add or write in
your code to send or receive data? is it after this line?
while ((UCSRA & (1 << RXC)) == 0) {};
ReceivedByte = UDR;
//add function or data to send to computer?
i not really too sure what i have asked is it clear or not, but i guess i am
confused by what i should write to send data to computer...
so can you help me with this, from your code, what else must i write or add,
for an example to send and receive data, to your code?
#include
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int main (void)
{
char ReceivedByte;
UCSRB |= (1 << RXEN) | (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
for (;;) // Loop forever
{
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been
recieved and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the recieved byte value into the variable
"ByteReceived"
//???add or write code at this line to send data???
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready
for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
//???add or write code at theis line to receive data???
}
}
i hope to hear from you and learn more about it... so do correct me...
thanks...
lewaltz
hi Dean
sorry i was having my examinations during this few weeks and now i am
focusing on the programming for my project...
i wanted to canofirm with you about the code that i have tried out but it
turns out to be nothing... chould you help me to check if there is any error in
my code?
i want transmit a char "S" from computer so that when (ReceivedByte ==
"S") it will turn off my LED (PORTC)
here is the code...
int main (void)

char ReceivedByte;

DDRC = 0xFF; // switch to output

PORTC = 0xFF; // set to high, LED lights up

// Configure Device

UCSRB |= (1 << RXEN) | (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

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been recieved and is ready to be read from
UDR
ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived"

UDR = "S";

if (ReceivedByte == "S") // if received an "S"

PORTC = 0x00;

//UDR = c; // send the character

Hi there, I need help, I tried to write a program for communication between


PC and ATMEGA8535. here is the code:
Quote:

#include
#include
/* Prototypes */
void USART0_Init( unsigned int baudrate );
unsigned char USART0_Receive( void );
void USART0_Transmit ( unsigned char data );
/* Initialize UART */
void USART0_Init(void)
{
/* Set the baud rate */
UBRRL = 0x19;
//I use 4 MHz crystal, and I want the baudrate to be
//9600, and then the UBRR should be 25, am I right?
UBRRH = 0x00;
/* Enable UART receiver and transmitter */
UCSRB = ( ( 1 << RXEN ) | ( 1 << TXEN ) );
/* Set frame format: 8 data 2stop */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
/* Read and write functions */
unsigned char USART0_Receive( void )
{
while ( !(UCSRA & (1<<RXC)) );
return UDR;
}
void USART0_Transmit ( unsigned char data )
{
while ( !(UCSRA & (1<<UDRE)) );
UDR = data;
}
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x02;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
USART0_Init();
MCUCR= 0x00;
TIMSK= 0x02; //timer interrupt sources
GICR= 0x00;
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//
void main(void)
{
init_devices();
for(;;)
{
USART0_Transmit ('a');
while(1);
}
}
from the code above, the problem is that the data received at the PC is
wrong. what could possibly the the cause of this problem? I thought the
MAX232 i used was damaged, so I've replaced it with a new one, and there
are no mistakes with hardware connection. Thanks a lot.
#include
#include
#ifndef F_CPU
#define F_CPU 8000000
#endif
#define BAUDRATE 9600
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
int main (void)
{
char ReceivedByte;
DDRD = 0b01111111; //7 0
PORTD = 0b00000000;
UCSR1B |= (1 << RXEN1) | (1 << TXEN1); // Turn on the transmission and
reception circuitry
UBRR1L=UBRRVAL; //low byte
UBRR1H=(UBRRVAL>>8); //high byte
// sei(); // Enable the Global Interrupt Enable flag so that interrupts can be
processed
for (;;) // Loop forever
{
// while ((UCSR1A & (1 << RXC1)) == 0) {}; // Do nothing until data have
been recieved and is ready to be read from UDR
// ReceivedByte = UDR1; // Fetch the recieved byte value into the variable
"ByteReceived"
ReceivedByte = 'U';
while ((UCSR1A & (1 << UDRE1)) == 0) {}; // Do nothing until UDR is
ready for more data to be written to it
UDR1 = ReceivedByte; // Echo back the received byte back to the computer
}
}
/*
ISR(USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR1; // Fetch the recieved byte value into the variable
"ByteReceived"
UDR1 = ReceivedByte; // Echo back the received byte back to the computer
}
*/
thatsthe code used atm, the reason i loop a 'U' out is simpel, clawson
sugested use a 'U' becouse that will measure 2,5volt avg on the avrs TXD.
Useing no codeline to set bits parity stopbits, im told skipping this leavs the
default 8n1
i have connected the avrs TXD to a max232 pin 10, wich is TTL input, still
measure 2.5volt
onmax 232 pin 7 i measure 0,14 volt wich is correct, its the avg of rs232
signal low and high (-9 and +9)
so it all seems to work, still when i connect it to my PCs serialport pin ground
and RXD my hyperterminal set to 8n1 do not output 'U' endlesly, nutting att
all happends
HELP!

I have used this tutorial successfully for Atmega8.Now I am trying with


Atmega128 but it is not working properly.I have set the hfuse =99 and lfuse
=E4 and I modified the code as below:

#include

#include

#define USART_BAUDRATE 9600

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

int main (void)

char ReceivedByte;

UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value


into the low byte of the UBRR register

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

UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission


and reception circuitry

UCSR0C |= (1 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00); // Use 8-bit


character sizes
for (;;) // Loop forever

while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR1; // Fetch the recieved byte value into the


variable "ByteReceived"

while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR


is ready for more data to be written to it

UDR0 = ReceivedByte; // Echo back the received byte back to the


computer

But I am getting some garbage characters.What could be the problem?

I have used this tutorial successfully for Atmega8.Now I am trying with


Atmega128 but it is not working properly.I have set the hfuse =99 and lfuse
=E4 and I modified the code as below:

#include

#include

#define USART_BAUDRATE 9600

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

int main (void)

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

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

UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission


and reception circuitry

UCSR0C |= (1 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00); // Use 8-bit


character sizes

for (;;) // Loop forever

while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR1; // Fetch the recieved byte value into the


variable "ByteReceived"

while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR


is ready for more data to be written to it

UDR0 = ReceivedByte; // Echo back the received byte back to the


computer

But I am getting some garbage characters.What could be the problem?

Could any one please tell me what could be the problem.

I am trying to figure out why me RS transmission is not working. I though it


was written so much about it, that is should be easy.
I have connected pins correctly, iam running atmega32 with 10MHz crystal
and the test code is like:

#define BAUDRATE 64 // 9600 at 10MHz

#define LED 0
#define LED2 6

#define F_CPU 10000000

//tranmission led

#define LED_ON() PORTC |= (1<<LED)

#define LED_OFF() PORTC &= ~(1<<LED)

//power led

#define LED2_ON() PORTD |= (1<<LED2)

#define LED2_OFF() PORTD &= ~(1<<LED2)

#include

#include

void rsInit(unsigned char baud) {

//UBRRH = 0;

UBRRL = baud;

UCSRC = (1<<UCSZ0) | (1<<UCSZ1); // 8N1

UCSRB = (1<<RXEN) | (1<<TXEN); // enable tx and rx

void rsSend(unsigned char data) {

while( !(UCSRA & (1<<UDRE)));

UDR = data;

unsigned char rsRecv() {


while( !(UCSRA & (1<<RXC)));

return UDR;

void portInit() {

//DDRD = (1 << LED);

// PORTC = 0xFF;

DDRC = 0xFF;

DDRD = (1 << LED2);

volatile unsigned char bytes[16];

int main(void){

unsigned int i=0;

asm("cli");

portInit();

_delay_ms(100);

rsInit(BAUDRATE);

LED2_ON();

bytes[0]=0x30;

bytes[2]=0x40;

bytes[3]=0x42;
bytes[4]=0xFF;

bytes[5]=0x48;

bytes[6]=0x40;

bytes[7]=0x60;

bytes[8]=0x70;

bytes[9]=0x80;

bytes[10]=0xF0;

bytes[11]=0xF0;

bytes[12]=0xF0;

bytes[13]=0xFA;

bytes[14]=0xFA;

bytes[15]=0xFA;

while(1){

for(i=0;i<16;i++){

rsSend(bytes[i]);

LED_ON();

_delay_ms(250);

LED_OFF();

_delay_ms(250);

_delay_ms(250);

_delay_ms(250);

return 0;

}
I am setting in Putty at the PC side 8bits,no parity,1 stop, no flow control,
checked also with Xon/Xoff. Sometimes it throws on my screen series of '
and |

Hallo All.
It is great that you spent time to make this great tutorial........thanks alot.
I want to make the mega16 responde to a command I will send from a
program made i C# from the pc over a serial rs232 line and use the modbus
protocol.
but right now I trying to send a string to the pc. I only works in JTAG mode
and is printing some strange charters like(!,,\)
in runtime mode it prints (X on pc if I enter a (0xE1). I checked the hex
value and it is A8F8
I dont understand why it do not print at least 5 charters.
can anybody help me???. and a sample code with the modbus implemented
would be perfect. see code below

#include

#include "stdlib.h"

#include "string.h"

#include "stdio.h"

#define USART_BAUDRATE 9600

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

int main ()

int ReceivedByte;

UCSRB |= (1 << RXEN) | (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

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the recieved byte value into the


variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR


is ready for more data to be written to it

if ( ReceivedByte==0xED)

{UDR = 0xEC;

if ( ReceivedByte==0xE1)

{USART_TxString("hallo");// send hallo to pc

else UDR = ReceivedByte; // Echo back the received byte


back to the computer
}

void USART_Tx(char data)

UDR = data; // Send data to the computer

while (!(UCSRA & (1<<UDRE)));{} // wait till transmit Data


register is empty

void USART_TxString(const char StringPtr[])

while (*StringPtr != 0x00)

USART_Tx(*StringPtr);

StringPtr++;

I've tried to connect my ATMega 32 to my mobile (siemens A50 with doesn't


nedd RS232) but something don't work.
My phone uses the following config:
19200 bits per second.
8 data bits.
None parity.
1 stop bit.
Using fuses I've choosen "Int. RC Osc. 8 MHz; Start-up time: 6 CK + 64 ms"
I have the following code:

#include

#define USART_BAUDRATE 19200

#define F_CPU 7372800

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

int baud = BAUD_PRESCALE;

void USART_Init( unsigned int baud )

/* Set baud rate */

UBRRH = (unsigned char)(baud>>8);

UBRRL = (unsigned char)baud;

/* Enable receiver and transmitter */

UCSRB = (1<<RXEN)|(1<<TXEN);

/* Set frame format: 8data, 2stop bit */

UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);//1 solo bit de parada

void USART_Transmit( unsigned char data )

/* Wait for empty transmit buffer */

while ( !( UCSRA & (1<<UDRE)) )

/* Put data into buffer, sends the data */

UDR = data;
}

void USART_Putstring(char * str)

while(*str)

USART_Transmit(*str++);

unsigned char USART_Receive( void )

/* Wait for data to be received */

while ( !(UCSRA & (1<<RXC)) )

/* Get and return received data from buffer */

return UDR;

int main (void)

USART_Init(baud);

int x;

DDRA=0xff;

PORTA=0xff;//Encendido
USART_Putstring("ATD 636725862");

PORTA=0x00;//Apagado

Anyone can help me???


THANKS!!!
n00b here , and this is my first post...
Anyways , i picked up ATmega 32 for interfacing motors to MATLAB , so that
I can control PWM , etc using my computer.
The problem i'm facing is that in hyperterminal , i can receive characters
from the microcontroller , but i can't send anything to it.
I set F_CPU to 1Mhz (1000000UL) , and baud as 2400.
Int. Osc 1mhz 6clk+64ms is selected in the fuse bits.
I'm using the exact same code given in the tutorial with minor modifications.

#include

#define USART_BAUDRATE 2400

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

int main (void)

char ReceivedByte;

int i=0;

UCSRB |= (1 << RXEN) | (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

for (;i<10;1++) // Loop for printing chars


{

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is


ready for more data to be written to it

UDR = 'a'+i; // print chars from a.

for (;;) // Loop forever

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data


have been recieved and is ready to be read from UDR

ReceivedByte = UDR; // Fetch the recieved byte value into the


variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is


ready for more data to be written to it

UDR = ReceivedByte; // Echo back the received byte back to the


computer

in hyperterminal , I get the output abcdefghi , but after that , any characters
that I type are ignored and are not echoed back.
I've tested loopback using a wire , and it works fine for all baud rates ,
databits,parity , etc.
I've been trying to solve this for the last 2 days , and i'm at my wits end now
.. :(
hope you could guide me in the right direction.

Hi there,
all is fine so far but how can one write texts of strings of characters and
display them on a screen.
is it?
Output the following please:
"Hello world"
or is it
printf "hello world"
etc.?
I tried this recipe:
#include
#include
#include
#include
#define F 4000000 /* oscillator-frequency
in Hz */
#define UART_BAUD_RATE 9600
#define UART_BAUD_CALC(UART_BAUD_RATE,FC)
(F/(UART_BAUD_RATE*16l)-1)
size_t strlen (const char*);
void usart_putc(unsigned char c) {
// wait until UDR ready
while(!(UCSRA & (1 << UDRE)));
UDR = c; // send character
}
void uart_puts (char *s) {
// loop until *s != NULL
while (*s) {
usart_putc(*s);
s++;
}
}
char *str1 = "Hallo World!";
char s [7];
int16_t i=0x40;
void init(void) {
// set baud rate
UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F)>>8);
UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F);
// Enable receiver and transmitter; enable RX interrupt
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
//UCSRB = (1<<
//asynchronous 8N1
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}
int main(void) {
init(); // init USART
//sei(); // enable interrupts
// send initial character
while (!(UCSRA & (1 << UDRE)));
itoa(i,s,10);
uart_puts(s);
return 0;
}
But i get the number 64 on the screen.
How, what, where should I write to get "hello world"?
Thanks

Hi Cliff,
Thanks for your Hints. Now i am able to remove all the errors. But the
program is not working.
I want to transmit 'a' on UART0. I am using ATmega128 & AVR Studio4. I
don't get pulses at TXD0 pin on C.R.O.
Program control is remaining in -- " while (!(UCSR0A & (1 << UDRE0)) ) {};
" loop continuously.
What could be the problem?

#define F_CPU 8000000UL


#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#include
#include
#include
int main (void)
{
char ReceivedByte;
ReceivedByte='A';
UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into
the low byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and
reception circuitry
UCSR0C |= (1 << UMSEL0) | (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit
character sizes
for (;;) // Loop forever
{
while (!(UCSR0A & (1 << UDRE0)) ) {}; // Do nothing until UDR is ready for
more data to be written to it
UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}
}

#include
#include
#include
#include
#include
#define FOSC 18432000// Clock Speed
#define BAUD 115200
#define MYUBRR FOSC/16/BAUD-1
//unsigned char buf[];
void usart_init(void);
void usart_Tx(unsigned char data);
unsigned char usart_Rx(void);
int main( void )
{
unsigned char *data,ptr[]="string to send",c;
data=ptr;
usart_init();
while(*data){
c=*data;
usart_Tx(c);
data++;}
while(1){
c =usart_Rx();
usart_Tx(c);}
return 0;
}
void usart_init( void )
{
unsigned int ubrr=MYUBRR;
printf("%d",ubrr);
UBRR0H = (unsigned char)(ubrr>>8); /* Set baud rate */
UBRR0L = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = 0x06;
/*Disabling the interrrupts*/
}
void usart_Tx( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR0 = data;
printf("%c",data);
}
unsigned char usart_Rx( void )
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
return UDR0;
}
i have written a program for send info from atmega 64 to hyper terminal and from
hyperterminal to atmega64. but it is displying junk values even i have selected
115200,8,none,1,flow control also none.wt is the proble could u tell me please.

Hi. I'm using an ATMega8 with a 16 MHz external crystal. I set the
SUT_CKSEL to Ext. Crystal/Resonator High Freq. and I can get the tutorial
code to work. It echos back the keys I hit. Now, I'm trying to get the value of
OCR1A sent to the terminal. All I get though, is a repeating
ZZZZZZZZZZZZZZZ. Any ideas?

#include

#define F_CPU 16000000

#include

#include

void sendStream(char c[], int length) {

int i;

for (i = 0; i < length; i++) {

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = c[i];

int main (void)

{
char buff[4];

DDRB |= (1 << PB1);

ICR1 = 40000;

TCCR1A |= (1<<COM1A1) | (1<<WGM11);

TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS11);

UCSRB |= (1 << RXEN) | (1 << TXEN);

UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);

UBRRL = 103;

while(1)

for(OCR1A=2000;OCR1A<=4000;OCR1A++){

_delay_ms(1);

itoa(OCR1A,buff,10);

sendStream(buff,4);

for(OCR1A=4000;OCR1A>=2000;OCR1A--){

_delay_ms(1);

itoa(OCR1A,buff,10);

sendStream(buff,4);

}
#include

#include

#include

#include

#define F_CPU 1000000UL

#define USART_BAUDRATE 4800

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

int main(void)

char recieveddata;

/* Enable Rx and Tx */

UCSRB |= (1<<RXEN) | (1<<TXEN);

/* Set no of bits to be Transmitted/recieved = 8 */


UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);

/* Set the Baud Rate in UBRR Registers */

UBRRL = BAUD_PRESCALE; /* Load the Lower Bits of


BAUD_PRESCALE */

UBRRH = (BAUD_PRESCALE >> 8); /* Load the Upper 8 Bits of BAUD_PRESCALE


*/

while (1);{

/* Recieve Data and Store in variable called "recieveddata" */

While ( (UCSRA & (1<<RXC)) == 0 ) ;{}

recieveddata = UDR;
/* Add 1 to the last recieved byte and transmit it back */

While ( (UCSRA & (1<<TXC)) == 0 ) ;{}

UDR = recieveddata +1;

I'm using a Parallel Programmer made by following the instructions here to


program a attiny2313.
I have so far tried basic I/O operations on the tiny2313 with great success.
I'm interested in trying USART communication between a PC and a tiny2313.
If i take the above code , put it in WinAvr , use this makefile , will it be
possible for me to do USART communication?
I am only interested in transferring a few bytes of data for proof of concept.
I'm running my tiny2313's as they are bought without any fuse changes or
anything. I just plug in the parallel port cable and transfer the program.
So , based on what i've read , my tiny2313 will be operating at 8MHz/8 =
1MHz with the RC Oscillator.
So , i've chosen a baud rate of 4800 as to get the UBRR value as ~12.0
I read in your tutorial that RC oscillators cannot be used for USART
communication.
which of the two do you actually mean?
1) It works , but the chances of error are high
2) it doesnt work at all.
Please do tell me if i can procceed trying with the RC Oscillator and if
anything is wrong with my code...

Hi Cliff, thanks for having the patience to reply to my basic newbie questions!
I have tried 9600 but I received nothing on HyperT as well(with everything
on HyperT setup correctly, flow control-NONE).
Well, I am using a prescalar to get 2Mhz but the OSCCAL option that you
suggested is a bit too complicated for me to understand so I think I would
like to opt that out.
I am not sure if it is the problem with my code. I tried using synchonise
mode before but I couldn’t see any waveforms coming out on the
oscilloscope. So I modified my code to make it async. I don’t know if
there’s something I missed out during this modification – I changed the
register, added in SREG |=(1<<7) to enable interrupt as told on the
datasheet so that I can use Rx, Tx, Empty enables/flag enables. I am not
sure if I need any XCK clock settings for this so I omitted that. Can you spot
any mistakes in doing this?

] //setup usart in spi mode for adc interfacing

void Setup_USART_As_SPI(void)

UCSR0B =

USART_CSR_B_Receive_Interrupt_EN |

USART_CSR_B_Transmit_Interrupt_EN |

USART_CSR_B_Data_Register_Empty_EN |

0;

//ensure transmitter and reciever disabled

UCSR0B &= ~(

USART_CSR_B_Receiver_EN |

USART_CSR_B_Transmitter_EN

);

//run usart at max baud rate

UBRR0 = 0;

UCSR0C =

USART_CSR_C_Master_SPI |
USART_CSR_C_CLK_Phase_Falling |

0;

//USART_CSR_C_CLK_Polarity_High |

//USART_CSR_C_MSB_Last |

//ensure transmitter and receiver ensabled

UCSR0B |= (

USART_CSR_B_Receiver_EN |

USART_CSR_B_Transmitter_EN

);

};

//setup usart for rs232

void Setup_Usart(void)

//setup global interrupt in SREG

//requirement for Rx and Tx Enable

SREG |= (1 << 7);

//disable the reciever and transmitter

UCSR1B &=

~(

USART_CSR_B_Receiver_EN |

USART_CSR_B_Transmitter_EN

);
//set the Control status register B

UCSR1B =

0;

//set the Control status register C

UCSR1C =

USART_CSR_C_USART_NumStopBits(1) |

USART_CSR_C_USART_Parity_None |

USART_CSR_C_USART_ModeSelect_ASync |

USART_CSR_C_USART_CharSize_Max8(8) |

0;

//set the baud rate register Sync

UBRR1L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate


value into the low byte of the UBRR register

UBRR1H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud


rate value into the high byte of the UBRR register

//enable the reciever and transmitter

UCSR1B |=

USART_CSR_B_Receiver_EN |

USART_CSR_B_Transmitter_EN |

USART_CSR_B_Data_Register_Interrupt_Empty_EN

);
};

That was for setup. Now this is the functions I called.

//function for reading data from adc using usart spi

void USARTSPI_ReadADS1252(void)

//declare 8bit WatchDRDY to detect DRDY mode

unsigned char WatchDRDy;

//Watch for Data ready

WatchDRDy = (PINC & 0x02 );

//if Data ready occurs, do nothing

while (WatchDRDy == (PINC & 0x02 ))

//do nothing

};

// make the whole delay to 22us to pass through the DRDY


mode

_delay_us ( 4);

//PORTC0 = 0

PORTC ^= (1);

//Write to data register to initiate data transfer

//flush adc

UDR0= 0;
//Wait till you've received 8 bits

//Do nothing when Receive Complete Flag is ZERO ( means


when it has not yet completely received data)

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

//Read the data

//UDR0 is the 8- bit USART Data Register

Data[2] = UDR0;

//flush register

UDR0 = 0;

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

Data[1] = UDR0;

//flush register

UDR0 = 0;

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

Data[0] = UDR0;

//interfacing with rs232

void USART_RS232_Interfacing(void)

//formula to mask and count 8 times


int Loop = (Loop + 1) & 7;

//at the 8th count, Loop will give 0

if ( Loop == 0 )

//get Data[] into another variable ToUsart1[]

ToUsart1[0] = Data[0];

ToUsart1[1] = Data[1];

ToUsart1[2] = Data[2];

//stream location counter initialisation

int streamLoc = 0;

//stream out data from ToUsart1[0..2]

while (streamLoc < 3)

// Do nothing until UDR is ready for more data to be


written to it by checking register empty flag

while ((UCSR1A & USART_CSR_A_Data_Register_Empty_Flag )


== 0) {};

// Send out the byte value in the variable ToUsart[0..2]


to data register of Usart_RS232

UDR1 = ToUsart1[streamLoc];

// increment stream location counter 0..2

streamLoc++;
}

};

Can you see any mistakes in the data sending flow?


I have just received a 1.8432MHz oscillator (Analog Electronics) this morning
and I am wondering if I should try that one. If I were to be using external
oscillator, do you think it will solve the problem or was it mistakes in my
code?
Many many thanks!

Right thanks. I wil try that later as I just found some other errors on my
system.
With my ADC reading, I got nice and expected waveforms on oscilloscope.
This is roughly how my code looks like.

]//function for reading data from adc using usart spi

void USARTSPI_ReadADS1252(void)

//declare 8bit WatchDRDY to detect DRDY mode

unsigned char WatchDRDy;

//Watch for Data ready

WatchDRDy = (PINC & 0x02 );

//if Data ready occurs, do nothing

while (WatchDRDy == (PINC & 0x02 ))

//do nothing

};

// make the whole delay to 22us to pass through the DRDY


mode

_delay_us ( 4);
//PORTC0 = 0

PORTC ^= (1);

//Write to data register to initiate data transfer

UDR0= 0;

//Wait till you've received 8 bits

//Do nothing when Receive Complete Flag is ZERO ( means


when it has not yet completely received data)

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

//Read the data

//UDR0 is the 8- bit USART Data Register

Data[2] = UDR0;

UDR0 = 0;

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

Data[1] = UDR0;

UDR0 = 0;

while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)

}
Data[0] = UDR0;

This works fine.


But when I include this USART_RS232_interfacing function after the adc
reading function, I got waveforms that shows that my ADC is not reading
data at the same intervals! (Time intervals between each "sample instant"
are different). I don't know what the code has done to my system. Here is
the code.

]//interfacing with rs232

void USART_RS232_Interfacing(void)

//formula to mask and count 8 times

int Loop = (Loop + 1) & 7;

//at the 8th count, Loop will give 0

if ( Loop == 0 )

//get Data[] into another variable ToUsart1[]

ToUsart1[0] = Data[0];

ToUsart1[1] = Data[1];

ToUsart1[2] = Data[2];

//stream location counter initialisation

int streamLoc = 0;

//stream out data from ToUsart1[0..2]

while (streamLoc < 3)

{
// Do nothing until UDR is ready for more data to be
written to it by checking register empty flag

while ((UCSR1A & USART_CSR_A_Data_Register_Empty_Flag )


== 0) {};

// Send out the byte value in the variable ToUsart[0..2]


to data register of Usart_RS232

UDR1 = ToUsart1[streamLoc];

// increment stream location counter 0..2

streamLoc++;

};

Both these adc read and rs232 functions are included in an infinite loop.
Please advice. Thanks!
Hello
Can anybody just have a look in my code to find the bug.
I try to transmit 8 bytes in the shape of a char[9] from one atmega164p to
another using usart.
I know the baud settings are correct because one byte works fine to
transmit, several bytes not.
Sender side:
char output[9];
void USART_vInit(void)
{
// Set baud rate
UBRR1H = (uint8_t)(USART_UBBR_VALUE>>8);
UBRR1L = (uint8_t)USART_UBBR_VALUE;
// Set frame format to 8 data bits, no parity, 2 stop bit
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
// Enable receiver and transmitter
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
}
void usart_send_string(char * str) {
while (*str) { // keep going until NULL terminator found
usart_send_char(*str++);
}
}
void usart_send_char(uint8_t byte) {
while ((UCSR1A & (1 << UDRE1)) == 0);
UDR1 = byte;
}
int main()
{
USART_vInit();
while(1)
{
output[0] = 2;
output[1] = 4;
output[2] = 6;
output[3] = 8;
output[4] = 10;
output[5] = 12;
output[6] = 14;
output[7] = 16;
usart_send_string(output);
}
}
Receiver side:
char input[9];
void USART_vReceiveByte()
{
int temp = 0;
while (UDR1 != '\0')
{
// Wait until a byte has been received
while((UCSR1A&(1<<RXC1)) == 0) ;
// Return received data
input[temp] =UDR1;
temp ++;
}
return 1;
}
void USART_vInit(void)
{
// Set baud rate
UBRR1H = (uint8_t)(USART_UBBR_VALUE>>8);
UBRR1L = (uint8_t)USART_UBBR_VALUE;
// Set frame format to 8 data bits, no parity, 2 stop bit
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
// Enable receiver and transmitter
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
}
int main(void)
{
DDRB = 0xFF; // port B output
PORTB = 0x00;
// Initialise USART
USART_vInit();
for(;;)
{
USART_vReceiveByte();
PORTB = input[0];
}
}
Using AVRstudio with Gcc and JTAG MKII
Please help :)

[NOTE: I originally posted this in AVR-GCC, but then browsing the tutorials
found this thread and thought it significantly more relevant. Apologies for the
double post]
Hello,
I have been following the sparkfun "Beginning Embedded Electronics" as well
as this thread tutorial and have overall been successful. I can read adn write
bytes at a time and have no problem receiving/sending from the terminal.
Unfortunately, when I output a chunk of data from the AVR rapidly (say 10
bytes) the code continually finds something to read and loops even though I
do not send it any data. If however, I place a delay in the putchar function of
"5ms" (according to the code - completely uncalibrated obviously) the code
works as advertised.
It seems like something is getting out of sync and my send is clobbering my
receive.
The question: what is going on and how do I get things to work properly with
out the artificial delay?
I am a software engineer by trade trying to learn about microprocessors, so
the hardware side is all new to me (read: ripe for newbie errors). Thinking
this might have had something to do with buffered IO (i.e. stdio.h) I rewrote
printf, etc, but I got the same exact behavior. It seems that when I output a
certain amount of data quickly the chip seems to set the flag that there is
data available. When I print out the UCSR0A, I see that the DOR0 bit is set.
May be relevant?
Anyway, I reverted back to the sparkfun code in order to keep things simple
for debugging. For reference, here is the tutorial:
http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=105
and here is the link to the tutorial code (my code is below)
http://www.sparkfun.com/tutorial/BeginningEmbedded/5-Compiling/basic-in-
atmega168.zip
I am using:
avr-gcc 4.0.2
atmega168
16 Mhz crystal
fuse set correctly ( 0xE6 )
avrdude 5.5
ispmkii programmer
USB BUB for usb->serial communication (also tried a FTDI cable)
Mac OSX with zterm and screen (tried both)
9600 Baud (in code and terminal)
Anything else that would be useful to know?
Here is the code:

/*

5-10-07

Copyright Spark Fun Electronics© 2007

Nathan Seidle

nathan at sparkfun.com

Example basic printf input/output

*/

#include

#include

#define FOSC 16000000

#define BAUD 9600

#define MYUBRR FOSC/16/BAUD-1

#define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))

#define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))

#define STATUS_LED 0

//Define functions

//======================

void ioinit(void); // initializes IO

static int uart_putchar(char c, FILE *stream);

uint8_t uart_getchar(void);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);

void delay_ms(uint16_t x); // general purpose delay

//======================

int main (void)

uint8_t key_press;

ioinit(); //Setup IO pins and defaults

printf("Waiting for input:\n");

while(1)

key_press = uart_getchar();

// [percent] in lieu of the symbol for posting

printf("I heard : [percent]c\n", key_press);

if(key_press == 'g') printf(" GO!\n");

if(key_press == 'X') printf(" EXIT\n");

if(key_press == 13) printf(" RETURN\n");

return(0);
}

void ioinit (void)

//1 = output, 0 = input

DDRB = 0xEF; //0b11101111; //PB4 = MISO

DDRC = 0xFF; // 0b11111111; //

DDRD = 0xFE; // 0b11111110; //PORTD (RX on PD0)

//USART Baud rate: 9600

UBRR0H = MYUBRR >> 8;

UBRR0L = MYUBRR;

UCSR0B = (1<<RXEN0)|(1<<TXEN0);

stdout = &mystdout; //Required for printf init

static int uart_putchar(char c, FILE *stream)

if (c == '\n') uart_putchar('\r', stream);

// NOTE: This the the delay that makes everything 'work'

delay_ms(5);

loop_until_bit_is_set(UCSR0A, UDRE0);

UDR0 = c;
return 0;

uint8_t uart_getchar(void)

while( !(UCSR0A & (1<<RXC0)) );

return(UDR0);

//General short delays

void delay_ms(uint16_t x)

uint8_t y, z;

for ( ; x > 0 ; x--){

for ( y = 0 ; y < 80 ; y++){

for ( z = 0 ; z < 40 ; z++){

asm volatile ("nop");

Thanks for any pointers or help!


-stephen

hi all
i debugged USART register via simulator which integrated AVRstudio.I fould
the strange of register like that. i dont know why.

void USART_Init(int port, unsigned int baudrate )


{

unsigned int ubrr ;

ubrr=F_CPU/16/baudrate-1;

//ubrr=51 with baudrate=19200

/* Set baud rate */

UBRR0H = (unsigned char)(ubrr>>8);

//UBRR0H=0;

UBRR0L = (unsigned char)ubrr;

//UBRR0L=0x33 (51)

/* Enable receiver and transmitter */

UCSR0B = (1<<RXEN)|(1<<TXEN);

/* Set frame format: 8data, 2stop bit */

UCSR0C = (0<<USBS)|(3<<UCSZ0);

/*After above command, UBRR0H is changed,

UBRR0H=0x06=>ubrr is wrong, but load this

code to MCU, it works good. So, why is

UBRR0H changed after setup UCSR0C ?

*/

when i start debug, UCSR0C=0x06 (i think,it must be UCSROC =0x00 when


start debugging

I want to send some AT Commands to mi mobile using mi ATMEGA32.


The parameters of the protocol:
19200 bauds
8 Bits
As I've read in datasheet:

This is what I've choosen:

Now, this is my code:

// Frequency needed by the delay function.


// The chip is factory set to run on internal

// oscillator at 4 MHz so the value is 4000000UL

#define F_CPU 4000000UL

#define USART_BAUDRATE 19200

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

#include

#include

int main(void)

UCSRB |= (1 << RXEN) | (1 << TXEN); //Habilito el circuito de


transmisión y recepción

UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);//8 bits

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

DDRA = 0xFF; // PA0-PA4 output

while (1){

_delay_ms(5000); // esperamos 5 segundos

PORTA = 0xFF;

while ((UCSRA & (1 << UDRE)) == 0) {};


UDR = 'A';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = 'T';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = '^';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = 'S';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = 'M';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = 'S';

while ((UCSRA & (1 << UDRE)) == 0) {};

UDR = 'O';

PORTA = 0x00;}

return 0;

The problem is that, my mobile recives some like this:

when should recive this A^TSMSO.


Other problem comes with delay, I've been choosen 15000ms, but this delay
less than 1 sec.
Any idea???? Thanks.

hello everybody, im working in serial transmision using a keyboard 4x4, i


have this code and i have proved it in proteus but it doesnt work, it compiles
perfectly in avrstudio 4. I still dont know what the problem is, if someone can
help me to figure out. the keyboard routine works perfectly using a LCD, but
it doesnt work using serial transmision...What is happening?.....im working
with atmega 16
[code]
#include
#include
#define USART_BAUDRATE 2400
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#define F_CPU 1000000
#define teclado_PORT_OUT PORTB
#define teclado_PORT_IN PINB
#include
void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRRH = (unsigned char)(baud>>8 );
UBRRL = (unsigned char)baud;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR = data;
}
unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}
int main(void)
{
USART_Init(BAUD_PRESCALE);
unsigned char upperNibble, codigotecla, Tecla, i;
while(1)
{
upperNibble = 0xff;
for(i=0; i<4; i++)
{
_delay_ms(1);
teclado_PORT_OUT = ~(0x01 << i);
_delay_ms(1); //delay for port o/p settling
upperNibble = teclado_PORT_IN | 0x0f;
if (upperNibble != 0xff)
{
_delay_ms(20); //key debouncing delay
upperNibble = teclado_PORT_IN | 0x0f;
if(upperNibble == 0xff) goto OUT;
codigotecla = (upperNibble & 0xf0) | (0x0f & ~(0x01 << i));
while (upperNibble != 0xff)
upperNibble = teclado_PORT_IN | 0x0f;
_delay_ms(20); //key debouncing delay
switch (codigotecla)
{
case (0xee): Tecla = '0';
break;
case (0xed): Tecla = '1';
break;
case (0xeb): Tecla = '2';
break;
case (0xe7): Tecla = '3';
break;
case (0xde): Tecla = '4';
break;
case (0xdd): Tecla = '5';
break;
case (0xdb): Tecla = '6';
break;
case (0xd7): Tecla = '7';
break;
case (0xbe): Tecla = '8';
break;
case (0xbd): Tecla = '9';
break;
case (0xbb): Tecla = 'A';
break;
case (0xb7): Tecla = 'B';
break;
case (0x7e): Tecla = 'C';
break;
case (0x7d): Tecla = 'D';
break;
case (0x7b): Tecla = 'E';
break;
case (0x77): Tecla = 'F';
break;
default : Tecla = 'X';
}
USART_Transmit(Tecla);
OUT:;
}
}
}
}
Hello everyone,
I am able to send characters from AVR to Terminal but I have a problem
sending it from PC to AVR when I try to echo the character. I don't know
what's going wrong. Please can someone help me.

#include

void USART_Init(unsigned int baudrate) // UBRR Value not baudrate

// Set baud rate

UBRR0H = (unsigned char)(baudrate>>8);

UBRR0L = (unsigned char)baudrate;

// Enable receiver and transmitter

UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(0<<RXCIE0)|(0<<UDRIE0);

void Usart_Tx(char data)

while (!(UCSR0A & (1<<UDRE0)));

UDR0 = data;

char Usart_Rx(void)
{

while (!(UCSR0A & (1<<RXC0)));

return UDR0;

int main(void)

char c;

USART_Init(51); // Baud rate = 9600bps, 8MHZ, u2x=0

for (;;) // Main loop

c=Usart_Rx();

Usart_Tx(c);

} //End Main loop

return 0;

I have followed this thread from page 1. It's been a great learning
experience to see the potential pitfalls before I actually started to try using
the USART feature of my AVR. I do have a problem that I haven't figured out
yet. Maybe someone might see something that I am not seeing. Transmitting
one character results in a different character being received. The received
character does not change unless the transmitted character is changed. I'm
sure this has to be a timing issue of some sort.
My board uses a 16.000MHz crystal. This AVR has no internal oscillator.
Pages 36-44 in the ATMega128 reference manual describe clock divisors and
such, but none are programmed in my case. The JTAG connector is removed
after programming so as not to interfere with the USART operation.
All I am attempting to do is get my AVR to communicate like a loopback
connector to HyperTerminal in Windows. I am using an ATMega128 (MAVRIC
IIb board) with an Atmel JTAGICE MKII programmer. The code used is based
on the examples provided in this thread. I believe the registers are correctly
adjusted for the ATMega128.
There is a DB9 connector attached to the AVR as follows:
DB9 Pinout
Pin 2 (RD) to TX0 of AVR
Pin 3 (TD) to RX0 of AVR
Pins 4-6 (DTR-DSR)
Pin 5 (GND) to GND of AVR
Pins 7-8 (RTS-CTS)
HyperTerminal and the USB COM Port of my PC are configured to 38400
baud, 8N1 (8 bits / No Parity / 1 Stop bit).
When pin 2 and 3 of the USB COM Port are connected together in a loop-
back fashion, the characters typed do echo back.
From HyperTerminal, in a full loopback form using the AVR as the loopback:
When 'f' is sent, '6' is looped back.
Then if I program the AVR as transmit only to HyperTerminal:
When '0' (zero) is sent, the omega character is returned.
The code shown has the receive section removed for now until I know I can
reliably transmit a character from the AVR to HyperTerminal.

// Includes to make the code work

#include

// Defines / Declarations

#define F_CPU 16000000UL

#define USART_BAUDRATE 38400UL

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

int main (void)

// char ReceivedByte;

// Turn on the transmission and reception

UCSR0B |= (1 << RXEN0) | (1 << TXEN0);

UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);


UBRR0L = BAUD_PRESCALE;

UBRR0H = (BAUD_PRESCALE >> 8);

for (;;) // Loop forever

// while ((UCSR0A & (1 << RXC0)) == 0)

// {

// };

// ReceivedByte = UDR0;

while ((UCSR0A & (1 << UDRE0)) == 0)

};

UDR0 = '0'; // This is hard coded for now

This should be very straight-forward. Any ideas on what I am overlooking?

Hello everyone,
I am using the atmega8515 and can open up brays terminal and I believe
everything is working fine. My questions are when i send a phrase like hello,
it echoes it back, but when i check the hex that is being sent it doesn't match
up with the ascii? my second question is why can i only open it up in brays
terminal and not in hyper terminal.

#include

#define USART_BAUDRATE 9600

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


int main (void)

char ReceivedByte;

UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission


and reception circuitry

UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ0); /* Set frame format:


8data, 1stop bit */

UBRRL = BAUD_PRESCALE;

UBRRH = (BAUD_PRESCALE >> 8);

for(;;)

while((UCSRA & (1<< RXC)) == 0) {};

ReceivedByte = UDR; // fetch back byte

while ((UCSRA & (1 << UDRE)) == 0) {}; //Wait for


UDR, when ready more data can be written

UDR = ReceivedByte; //echo back byte

}
}

why is the following code not transmitting any data through ATMEGA2560 -
STK600......suggest me any changes
frequency : 16000000hz
baud :9600
PIN0 OF PORTE is connected to TXD pin of stk600
PIN1 OF PORTE is connected to RXD pin of stk600
suggest me any further changes required...
code:
Code:

//=====================================================================
=============================//

// INCLUDING HEADER FILES & OTHER GLOBAL DECLARATIONS


//

//=====================================================================
=============================//

#include // including the input/output files of avr

#include //including the interrupt files of avr

#include //including the special function registers

#include //including the delay function from util


directory

#define FOSC 16000000L //clock speed of 8MHz

#define BAUD 9600 //baud rate

#define MYUBRR ((FOSC/(16*BAUD))-1) //defnining the USART BAUD


RATE REGISTER

void transmit(unsigned char ); // function for transmitting


the at command to GSM for initialization

void start_commandat(); //declaration of the function which sends 'AT'


command

void USART_Init(unsigned int); //declaration of the 'USART


INITIALISATION' function
unsigned char m;

//unsigned char t;

int p=0;//declaration of the required variables

//*********************************************************************
*****************************//

// MAIN PROGRAM
//

//*********************************************************************
*****************************//

int main( ) //start of the program

USART_Init(MYUBRR);//function call for the USART initialisation

// sei();//set the global interrupt

for(;;)

m='A';

while ( !( UCSR0A & (1<<UDRE0)) )

/* Put data into buffer, sends the data */

UDR0 =m;

_delay_ms(1);

//transmit(m);

}
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////

/// USART INITILISATION FUNCTION


//

///////////////////////////////////////////////////////////////////////
///////////////////////////////

void USART_Init(unsigned int ubrr)

UBRR0H =(unsigned char)(ubrr>>8);//setting the baud rate

UBRR0L =(unsigned char)ubrr;//setting the baud rate

UCSR0B = (1<<RXEN0)|(1<<TXEN0);//ENABLING THE TRANSMITTER AND


RECEIVER

UCSR0C =
(0<<UMSEL01)|(0<<UMSEL00)|(0<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01)|(0<<UCSZ02
);//SETTING THE FRAME FORMAT WITH 8 DATA AND 1 STOP BITS

UCSR0A = (1<<UDRE0);

}
///////////////////////////////////////////////////////////////////////
///////////////////////////////

/// TRANSMIT FUNCTION


//

///////////////////////////////////////////////////////////////////////
///////////////////////////////

/*void transmit( unsigned char data )

while ( !( UCSR0A & (1<<UDRE0)) )

UDR0 = data;

}*/

in the programmer part::


advanced tab:calibrate for frequency is 8MHz(no option to select other
frequency)
fuses:
CKDIV8,JTAGEN,SPIEN are enabled
extended - 0xFF, high - 0x99, low - 0x62;
HW SETTINGS::
clock generator is 16.01MHz
in the simulator part::
if we give ubrr=103 directly then UBRR0H - 0x00,UBRR0L- 0x67; and
nothing(not even the garbage values) will be displayed in the hyperterminal
but if we give ubrr after calculating it with (F_CPU/((baud*16)-1)) then
UBRR0H - 0X00,UBRR0L-0x05.
;and some garbage values are displayed in the hyperterminal
this is what actually happening.
Serial communication (Data receive) using AVR Microcontroller
(ATmega16) USART

Communication between two entities is important for the information flow to take

place. In general the information transport system can be parallel in which the

complete byte of data is sent at a time, with each bit having a separate dedicated

line or it can be serial where only one communication line is available which is

shared by all the bits sequentially. The pros and cons of these two systems are

equivalent and selection between the two depends on the application.

Data can be exchanged using parallel or serial techniques. Setup for parallel data

transfer is not cost effective but is a very fast method of communication. Serial

communication is cost effective because it requires only a single line of connection

but on the other hand is a slow process in comparison to parallel communication.

This article explains serial communication of AVR microcontroller (ATmega16) with

PC. The data is transmitted from the controller using RS232 standard and displayed

on the PC using Hyper Terminal.


There are two methods for serial data communication (i) Synchronous and (ii)
Asynchronous communication. In Synchronous communication method complete
block (characters) is sent at a time. It doesn’t require any additional bits (start, stop
or parity) to be added for the synchronization of frame. The devices are
synchronized by clock. And in asynchronous communication data transmission is
done byte by byte i.e., one byte at a time. The additional bits are added to complete
a frame.

In synchronous communication the frame consists of data bits while in asynchronous


communication the total number of bits in a frame may be more than the data bits.

There are three ways in which serial communication can be done


i. Simplex: Transmission is done in one direction.
ii. Half duplex: Transmission can be done in both the direction but one side at
a time.

iii. Full duplex: Transmission can be done in both the direction simultaneously.

Atmega16 is equipped with three different kinds of serial communication peripheral


systems:
i. Serial USART
ii. SPI (Serial Peripheral Interface)
iii. TWI (Two wire Interface)

SERIAL USART (universal synchronous asynchronous receiver and transmission/

transmitter):

Serial USART provides full-duplex communication between the transmitter and


receiver. Atmega16 is equipped with independent hardware for serial USART
communication. Pin-14 (RXD) and Pin-15 (TXD) provide receive and transmit
interface to the microcontroller.
Atmega16 USART provides asynchronous mode of communication and do not have
a dedicated clock line between the transmitting and receiving end. The
synchronization is achieved by properly setting the baud rate, start and stop bits in a
transmission sequence.
Start bit and stop bit: These bits are use to synchronize the data frame. Start bit is
one single low bit and is always given at the starting of the frame, indicating the next
bits are data bits. Stop bit can be one or two high bits at the end of frame, indicating
the completion of frame.

Baud Rate: In simple words baud rate is the rate at which serial data is being
transferred.
Atmega16 USART has following features:
· Different Baud Rates.
· Variable data size with options ranging from 5bits to 9bits.
· One or two stop bits.
· Hardware generated parity check.
· USART can be configured to operate in synchronous mode.
· Three separate interrupts for RX Complete, TX complete and TX data register
empty.

USART Registers

To use the USART of Atmega16, certain registers need to be configured.

UCSR: USART control and status register. It’s is basically divided into three parts
UCSRA, UCSRB and UCSRC. These registers are basically used to configure the
USART.
UBRR: USART Baud Rate Registers. Basically use to set the baud rate of USART
UDR: USART data register

i. UCSRA: (USART Control and Status Register A)

RXC (USART Receive Complete): RXC flag is set to 1 if unread data exists in
receive buffer, and set to 0 if receive buffer is empty.
TXC (USART Transmit complete): TXC flag is set to 1 when data is completely
transmitted to Transmit shift register and no data is present in the buffer register
UDR.
UDRE (USART Data Register Empty): This flag is set to logic 1 when the transmit
buffer is empty, indicating it is ready to receive new data. UDRE bit is cleared by
writing to the UDR register.
ii. UCSRB: (USART Control and Status Register B)

RXCIE: RX Complete Interrupt Enable,


When 1 -> RX complete interrupt is enabled.
When 0 -> RX complete interrupt is disabled.
TXCIE: TX Complete Interrupt Enable,
When 1 -> TX complete interrupt is enabled
When 0-> TX complete interrupt is disabled
UDRIE: USART Data Register Empty Interrupt Enable,
When 1 -> UDRE flag interrupt is enabled.
When 0 -> UDRE flag interrupt is disabled.
RXEN: Receiver Enabled,
When 1 -> USART Receiver is enabled.
When 0 -> USART Receiver is disabled.
TXEN: Transmitter Enabled,
When 1 -> USART Transmitter is enabled.
When 0 -> USART Transmitter is disabled.

iii. UCSRC: (USART Control and Status Register C)


The transmitter and receiver are configured with the same data features as
configured in this register for proper data transmission.
URSEL: USART Register select. This bit must be set due to sharing of I/O location
by UBRRH and UCSRC
UMSEL: USART Mode Select,
When 1 -> Synchronous Operation
When 0 -> Asynchronous Operation
UPM[0:1]: USART Parity Mode, Parity mode selection bits.
USBS: USART Stop Select Bit,
When 0-> 1 Stop Bit
When 1 -> 2 Stop Bits
UCSZ[0:1]: The UCSZ[1:0] bits combined with the UCSZ2 bit in UCSRB sets size of
data frame i.e., the number of data bits. The table shows the bit combinations with
respective character size.

UCSZ2 UCSZ1 UCSZ0 Character Size


0 0 0 5-bit
0 0 1 6-bit
0 1 0 7-bit
0 1 1 8-bit
1 0 0 Reserved
1 0 1 Reserved
1 1 0 Reserved
1 1 1 9-bit
iv. UDR: (USART Data Register)

The USART Data receive and data transmit buffer registers share the same address
referred as USART UDR register, when data is written to the register it is written in
transmit data buffer register (TXB). Received data is read from the Receive data
buffer register (RXB).

v. UBRRH & UBRRL (USART Baud Rate Registers)

The UBRRH register shares the same I/O address with the UCSRC register, The
differentiation is done on the basis of value of URSEL bit.
When URSEL=0; write operation is done on UBRRH register.
When URSEL=1; write operation is done on UCSRC register.

The UBRRH and UBRRL register together stores the 12-bit value of baud rate,
UBRRH contains the 4 most significant bits and UBRRL contains the other 8 least
significant bits. Baud rates of the transmitting and receiving bodies must match for
successful communication to take place.

UBRR register value is calculated by the following formula:


The Connection of MAX232 and ATmega16 is shown in the circuit diagram. The
MAX232 is used for level conversion. The reader can refer the component section
for further details on MAX 232.The T1IN (pin11) of Max232 is connected to Tx
(pin15) of AVR and R1IN(pin12) is connected to Rx(pin14) of AVR. The
HyperTerminal software is used to send data to microcontroller via COM port.

Code Explanation:
Step 1: First step is to select the Baud rate. Baud rate of two devices must match or
else they will not be able to synchronize with each other.
#define USART_BAUDRATE 9600
Step2: To set a particular Baud Rate in ATmega16, write the corresponding UDRR
value. The UDRR value is calculated by using the formula
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

Step3: To initialize the USART


i. Turn on transmission and reception circuitry.
ii. Select the number of stop bits.
iii. Set the size of data.
iv.Load the value of UBRR to set the baud rate.
void usart_init()

UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (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
}

Step4: Get the data from USART


Monitor the status of RXC (receiver complete) flag . RXC becomes high when it
receives the stop bit signal. So if RXC is high it means that the data is loaded into
UDR register. Collect the data from UDR or else it might get lost or overwritten with
the next incoming data.
unsigned int usart_getch()

while ((UCSRA & (1 << RXC)) == 0);


// Do nothing until data has been received and is ready to be read from UDR
return(UDR); // return the byte
}
// Program to receive data from USART and displaying it on LCD

/*
Receive data from serial port and display it on LCD
LCD DATA port----PORT A
ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
using external clock frequency 12MHz
*/

#define F_CPU 12000000UL


#define USART_BAUDRATE 9600 // Baud Rate value
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTA //LCD data port

#define ctrl PORTB


#define en PB2 // enable signal
#define rw PB1 // read/write signal
#define rs PB0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_clear();

void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();

int main()
{
unsigned char value;
DDRA=0xff; // LCD_DATA port as output port
DDRB=0x07; // signal as out put
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 milli seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // Call a function to get data from serial port
LCD_cmd(0xC0); // to go in second line and zeroth position on LCD
LCD_write(value); // write data to LCD
}
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in 8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);

LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 is for 0th position


_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (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
}

unsigned int usart_getch()


{
while ((UCSRA & (1 << RXC)) == 0);
// Do nothing until data has been received and is ready to be read from UDR
return(UDR); // return the byte
}

Komunikasi pake INTRUPt


//Program to get a serial data from RS232 (using
HyperTerminal)..
// and sending it back to the RS232 (to HyperTerminal).
#include<avr/io.h>
#include<avr/interrupt.h>

#define USART_BAUDRATE 9600


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

void usart_init();

// --------------------------------------------
int main()
{
usart_init(); // initialization of USART

sei(); // Enable global interrupt


for (;;) // infinite loop
{
// Do Nothing
}
}

void usart_init()
{
UCSRB |= (1<<RXCIE) | (1 << RXEN) | (1 << TXEN); // Turn on
//
circuitry and receiver interrupt
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
}

ISR (USART_RXC_vect)
{
unsigned char value;
value = UDR; // Fetch the received byte
value into the variable "value"
UDR = value; //Put the value to UDR

}
This article covers data transmission using 8 bit USART. The readers should have a

basic understanding of serial communication and how to receive the serial data

output. More details on these topics are available on Serial communication using

AVR Microcontroller USART.

// Program to receive data from USART and displaying that..


// data on LCD and sending the same data on HyperTerminal.
/*
get data from serial port and displaying it on LCD and send back to the
HyperTerminal
LCD DATA port----PORT A
ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
@ external clock frequency 12MHz
*/
#define F_CPU 12000000UL

#define USART_BAUDRATE 9600


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

#include<avr/io.h>
#include<util/delay.h>

#define LCD_DATA PORTA // LCD data port


#define ctrl PORTB
#define en PB2 // enable signal
#define rw PB1 // read/write signal
#define rs PB0 // register select signal

void LCD_cmd(unsigned char cmd);


void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_clear();

void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();

int main()
{
unsigned char value;
DDRA=0xff;
DDRB=0x07;
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 mili seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // get data from serial port
LCD_cmd(0xC0);
LCD_write(value); // write data to LCD
usart_putch(value); // send data back to the PC (HyperTerminal)
}
return 0;
}

void init_LCD(void)
{
LCD_cmd(0x38); //initialization of 16X2 LCD in 8bit mode
_delay_ms(1);

LCD_cmd(0x01); // clear LCD


_delay_ms(1);
LCD_cmd(0x0E); // cursor ON
_delay_ms(1);

LCD_cmd(0x80); // ---8 go to first line and --0 is for 0th position


_delay_ms(1);
return;
}

void LCD_cmd(unsigned char cmd)


{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl =(0<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return;
}

void LCD_write(unsigned char data)


{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en);
_delay_ms(1);
ctrl = (1<<rs)|(0<<rw)|(0<<en);
_delay_ms(50);
return ;
}

void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and reception circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (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_putch(unsigned char send)


{
while ((UCSRA & (1 << UDRE)) == 0); // Do nothing until UDR is ready..
// for more data to be written to it
UDR = send; // Send the byte
}
unsigned int usart_getch()
{
while ((UCSRA & (1 << RXC)) == 0);
// Do nothing until data have been received and is ready to be read from UDR
return(UDR); // return the byte
}

SERIAL PORT c#:

using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);

[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}

private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");

// Attach a method to be called when there


// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);

// Begin communications
port.Open();

// Enter an application loop to keep this thread alive


Application.Run();
}

private void port_DataReceived(object sender,


SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}

To start off, here is sample code in a terminal application which you can try out to see how the
SerialPort class is used. This requires Visual Studio 2010 to compile, which can be obtained free
via C# Express. It is just a simple little application with basic support for text or binary (hex)
modes to send and receive data. A nice feature or two is auto-detection of installed COM ports
that update at runtime if you plugin or remove USB-to-Serial adapters, also you can change the
DTR and RTS levels and monitor the CTS, DSR, and CD lines.

Build Note: You will receive an error that Visual Studio isn't able to find NoahCode.pfx. This is
expected as it is the click-once certificate for publishing and is NOT NEEDED for normal code use.
Just go to Project Properties > Signing > Click on Create Test Certificate. that’s it

Get Connected
You can obtain USB to Serial adapters and have just about as many ports on your PC as you like. I
carry around two adapters with a null modem (wikipedia) between them so I can create a
loopback to send & receive through to separate ports on most any computer. I'd recommend doing
the same for when writing code for the serial port.

If you'd like to quickly and easily create your own external devices to communicate with the PC, I
recommend starting with the Arduino, NetDuino (like an Arduino but programmed in C#),
or Parallax BASIC Stamp modules. All three have many accessories and sensors available (such as
LCDs, RF, Sounds, AD & DA, etc). sparkfun.com is a great place to look. After that you could
migrate to an Atmel Microcontroller (recommended) or Microchip PIC.

Write Data Out


Here is an example of how easy it is to use the new SerialPort control. Very simply, here is how
you can send a bit of data out the port.

// This is a new namespace in .NET 2.0


// that contains the SerialPort class
using System.IO.Ports;

private static void SendSampleData()


{
// Instantiate the communications
// port with some basic settings
SerialPort port = new SerialPort(
"COM1", 9600, Parity.None, 8, StopBits.One);

// Open the port for communications


port.Open();

// Write a string
port.Write("Hello World");

// Write a set of bytes


port.Write(new byte[] {0x0A, 0xE2, 0xFF}, 0, 3);

// Close the port


port.Close();
}

Listing Available Ports


One of the (several) new methods that is supported, and one I'm very glad is finally here, is the
ability to obtain a list of the COM ports installed on the computer (ex: COM1, COM2, COM4). This
is definately helpful when you want to present the list of ports avalible for the user to select from
(as in the SerialPortTerminal.zip Win App example).

foreach (string s in SerialPort.GetPortNames())


Console.WriteLine(s);

Sending Files
Here are two helpful little methods for sending files through the serial port. Of course, these are
the bare essentials and as always, you should check to make sure the port is open first
(port.IsOpen) and use try/catch around trying to open a file, but you get the gist with this code.
The binary sending routine is limited to about 2GB (the size of an int), but this should be okay for
most uses.

using System.IO;

private static void SendTextFile(


SerialPort port, string FileName)
{ port.Write(File.OpenText(FileName).ReadToEnd()); }

private static void SendBinaryFile(


SerialPort port, string FileName)
{
using (FileStream fs = File.OpenRead(FileName))
port.Write((new BinaryReader(fs)).ReadBytes(
(int)fs.Length), 0, (int)fs.Length);
}

RS-232 Project Photos


Each of these involve RS-232 serial port communications.
Just what's needed to get started with microcontrollers,
a Basic Stamp, mini LCD display, power, and RS-232 port.

Two USB to Serial adapters with a null modem


to loopback and test your serial software.
The brains to a mini automated radio station that let me
control my PC & home using my HAM radio from around town.

Port Wiring Notes

DB9 Male (Pin Side) DB9 Female (Pin Side)


DB9 Female (Solder Side) DB9 Male (Solder Side)
------------- -------------
\ 1 2 3 4 5 / \ 5 4 3 2 1 /
\ 6 7 8 9 / \ 9 8 7 6 /
--------- ---------

DB9 Female to DB9 Female Null-Modem Wiring


2 | 3 | 7 | 8 | 6&1| 5 | 4
---- ---- ---- ---- ---- ---- ----
3 | 2 | 8 | 7 | 4 | 5 | 6&1

9-pin 25-pin Assignment From PC


------ ------ ------------------------- ------------
Shield 1 Case Ground Gnd
1 8 DCD (Data Carrier Detect) Input
2 3 RX (Receive Data) Input
3 2 TX (Transmit Data) Output
4 20 DTR (Data Terminal Ready) Output
5 7 GND (Signal Ground) Gnd
6 6 DSR (Data Set Ready) Input
7 4 RTS (Request To Send) Output
8 5 CTS (Clear To Send) Input
9 22 RI (Ring Indicator) Input

- RTS & DTR are binary outputs that can be manually set and held
- DCD, DSR, CTS, and RI are binary inputs that can be read
- RX & TX can not be set manually and are controlled by the UART
- maximum voltages are between -15 volts and +15 volts
- binary outputs are between +5 to +15 volts and -5 to -15 volts
- binary inputs are between +3 to +15 volts and -3 to -15 volts
- input voltages between -3 to +3 are undefined while output voltages
between -5 and +5 are undefined
- positive voltages indicate ON or SPACE, negative voltages indicate
OFF or MARK

Protocol Development
If you are making your own serial interface/protocol, you really must have a good standard in
place. Serial data flows into the com port byte by byte and must be buffered and parsed correctly.
Think of it this way, if a terminal sent your computer "Hello World" it may come in as four
OnComm triggers: "H", "ello", " Wo", and "rld"

The best protocols are usually a mix of these methods. Here are three simple protocol techniques:

1. Beginning and Ending ("Start" & "Stop") Codes


This is good for sending text as it lets everybody know when text starts and ends. You
simply tack on a non-normal byte at the beginning and end of the text. For example, you'd
use '---' to signify the start of the string and '===' to signify the end. So you would use:
com.Output = "---Hello World===";

2. Fixed Length Codes


Used for specific commands. You can create your own codes to send and specify what they
mean. Say I want to control the lighting in a house, I'd setup a protocol of commands like
this:
1st byte = House Code, 2nd byte = Light Code, 3rd byte = On or Off (0 for off, 1 for on)
So to turn on the 11th light in my house (house code #3) I'd use:
com.Output = new byte[] {3, 11, 0};
3. Prefixed Data Packet
This is probably the most common and flexible but requires the most coding. Just prefix
your data packet with the length of the data. The prefix must be a fixed size, such as two
bytes which would allow a data packet of up to 65,535 bytes. Then the receiver knows how
much data is in the packet because it always takes the first two bytes and uses the rest as
the data packet.
Example: com.Output = ((char) 00) + ((char) 11) + "Hello World";

Im making a WindowsForm app to simulate current values to a meter. I dont know how
to take the values from the text box and send it trough the COM port. this is the code i
got at the moment

namespace ValueSim1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{

private void label1_Click(object sender, EventArgs e)


{

private void comboBox1_DropDown(object sender, EventArgs e)


{
// Get all serial ports name
string[] ports = SerialPort.GetPortNames();

// Clear comboBox list to get latest serial ports in each dropdown.


comboBox1.Items.Clear();

foreach (string port in ports)


{
// Output serial port to dropdown list.
comboBox1.Items.Add(port);
}
}

private static SerialPort serialPort1;

private void button1_Click(object sender, EventArgs e)


{

if (comboBox1.Text != "")
{
serialPort1.PortName = comboBox1.Text; //comboBox1.Text set to PortName

serialPort1.BaudRate = 19200; //Baudrate is set (fix.)

//if serial port has opened, it must be closed at first.


if (serialPort1.IsOpen == true)
{
serialPort1.Close();
}
//open the serial port after confirmation serial port closed.
if (serialPort1.IsOpen == false)
{
serialPort1.Open();

if (serialPort1.IsOpen == true) //message window shows serial port status.


{
MessageBox.Show("Open Success\n" + serialPort1.PortName.ToString() + " " +
serialPort1.BaudRate.ToString());
}
else
{
MessageBox.Show("COM Port error");
}
}
}
}

private void groupBox1_Enter(object sender, EventArgs e)


{

private void textBox5_TextChanged(object sender, EventArgs e)


{

private void textBox1_TextChanged(object sender, EventArgs e)


{
}
}
}

Вам также может понравиться