0% found this document useful (0 votes)
76 views

Basic C AVR

The document discusses common tasks when programming microcontrollers in C such as setting and clearing bits in registers and checking bit values. It provides details on working with registers in C, including: - Registers represent connections between a CPU and peripheral devices and are used to configure and control peripherals. - Binary, hexadecimal, and left shift operators are used to set, clear, and check bits in registers. - The "|" and "&" operators are used to set and clear bits respectively while preserving other bit values. - The "&&" operator is used to check if a specific bit in a register is a 1 or 0.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
76 views

Basic C AVR

The document discusses common tasks when programming microcontrollers in C such as setting and clearing bits in registers and checking bit values. It provides details on working with registers in C, including: - Registers represent connections between a CPU and peripheral devices and are used to configure and control peripherals. - Binary, hexadecimal, and left shift operators are used to set, clear, and check bits in registers. - The "|" and "&" operators are used to set and clear bits respectively while preserving other bit values. - The "&&" operator is used to check if a specific bit in a register is a 1 or 0.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 30

Here I will highlight some features of C language commonly used in 8 bit embedded

platforms like 8051, AVR and PICs. While programming microcontrollers in C most of the
time we have to deal with registers. Most common tasks are setting and clearing bits in a
register and check whether a bit is 0 or 1 in a given register. So here I will give detail on
those topics, it will help you if you are new to embedded programming in C and if you get
confused when you see some codes.

A Register
A register is simply a collection of some bits (mostly 8 bits in case of 8bit MCUs). Either
each different bit in a register has some purpose or the register as a whole holds a value.
Registers serves as connection between a CPU and a Peripheral device (like ADC or
TIMER). By modifying the register the CPU is actually instructing the PERIPHERAL to do
something or it is configuring it in some way. And by reading a register, the CPU can know
the state of peripheral or read associated data.

Fig.: CPU writing to Peripheral Register

 
Fig.: CPU Reading from Peripheral Register

Binary Numbers in C
When you write a=110; in C it means you are setting the value of variable"a" to "one
hundred and ten" (in decimal). Many time in embedded programming we are not interested
in the value of a variable but the state of each bits in the variable. Like when you want to set
the bits of a register (MYREG) to a bit pattern like 10010111 (binary). Then you cannot write
MYREG=10010111. Because compiler will interpret 10010111 as decimal. To specify a
binary number in C program you have to prefix it with 0b (zero followed by b). So if you
write

MYREG=0b10010111;

it assigns the bit pattern 10010111 to the bits of Register MYREG.

HEX Numbers in C
In same way if you prefix a number by 0x (a zero followed by x) then compiler interpret it
like a HEX number. So

MYREG=0x10; (10 in HEX is 16 in decimal)

MYREG=0xFF;(Set all bits to 11111111 or decimal 255)

Setting a BIT in Register


Here our aim is to set (set to logical 1) any given bit (say bit 5) of a given register (say
MYREG). The syntax is

MYREG=MYREG | 0b00100000;

The above code will SET bit 5 to 1 leaving all other bits unchanged. What the above code
does is that it ORs each Bit of MYREG with each bit of 0b00100000 and store the value back
in MYREG. If you know how logical OR works then you will get it.

In short you can write the same code as

MYREG|=0b00100000;

Now lets come to practical usage. In practice each bit has got a name according to its
work/function. Say our BIT (the 5th bit) has got name ENABLE, and what it does is clear by
its name,when we set it to 1 it enables the peripheral and when cleared (0) it disables it. So
the right way to set it is.

MYREG|=(1<<ENABLE);

The << is called left shift operator. It shifts the bits of LHS variable left by the amount on its
RHS variable. If you write

b=1<<3;

then, 1 whose binary value is 00000001 is shifted 3 places to left which results in 00001000

So if ENABLE is defined as 5 (as enable is 5th bit) then

MYREG|=(1<<ENABLE);

will result in

MYREG|=(1<<5);

which again result in

MYREG|=(0b00100000);

Now a beginner would ask "What's the Advantage ?". And once you know it you would
realize that advantage is immense!

1. Readability of code: MYREG|=(1<<ENABLE); gives a clue that we are enabling the


peripheral while MYREG|=0b00100000; does not give any clue what it is doing, we
have to go to data sheet and find out which bit actually ENABLEs the peripheral.
While ENABLE=5 is already defined in header files by the developer of compiler by
carefully studying the datasheets of device.
2. Easier Portability: Suppose you use this code many times in your program (and your
program is reasonably large and uses other register also) and you now want the same
code to run on some other MCU model. The new MCU is of similar family but has
slightly different bit scheme, say ENABLE is bit 2 instead of bit 5. Then you have to
find all occurrence of MYREG|=(0b00100000); and change that to MYREG|
=(0b00000100); But if you have used the other method then you simply need to
inform the compiler (by its setting options) that you are going to use the other MCU
and compiler will automatically get the definitions for the new device. And in this
definition ENABLE=2 will already be defined by the compiler developer. So it will
be lot easier.

Clearing a BIT in Register


For clearing a bit logical AND(symbol &) operator is used in place of logical OR (symbol |).
The syntax is as follows

MYREG&=~(1<<ENABLE);

Fig.: How to clear (0) a bit in C language.

This will clear (i.e. set to value 0) a given bit (identified by name ENABLE) in a register
called MYREG. This operation will not affect any other bits of register except ENABLE.

Let us see how it works with the help of following diagram.


Fig.: "Clearing a BIT" how it works?

So now you know how you can selectively clear any bit in any given register. If you want to
clear more than one bit at a time you can write like this

//This will clear bits ENABLE,FAST_MODE and BUSY, leaving all other bits
untouched
MYREG&=(~((1<<ENABLE)|(1<<FAST_MODE)|(1<<BUSY)));

Similarly the syntax for setting(set to 1) multiple bits at a time is as follows

//This will set bits ENABLE,FAST_MODE and BUSY, leaving all other bits
untouched
MYREG|=((1<<ENABLE)|(1<<FAST_MODE)|(1<<BUSY));
Testing The Status of a Bit.
Till now we were modifying the registers either setting or clearing bits. Now we will learn
how can be know that a specific bit is 0 or 1. To Know if a bit is 0 or 1 we AND it with a
AND MASK. Suppose if we want to check bit 5 of a register MYREG then the AND MASK
would be 0b00100000. If we AND this value with the current value of MYREG then result
will be non-zero only if the 5th bit in MYREG is '1' else the result will be '0'.

The syntax would be like this.

if(MYREG & (1<<ENABLE))


{
//ENABLE is '1' in MYREG
...
}
else
{
//ENABLE is '0' in MYREG
}

So now you know the basic operation on bits, they are widely used in firmware programming
and will help you understand other codes on my web site. And Please don't forget to post
your comment regarding any doubts, or reporting errors in the above article, or simply to tell
how you liked the stuff.

Timers in Compare Mode – Part I


In last tutorials we discussed about the basics of TIMERs of AVR. In this tutorial we will go
a step further and use the timer in compare mode . In our first tutorial on timer we set the
clock of the timer using a prescaler and then let the timer run and whenever it overflowed it
informed us. This way we computed time. But this has its limitations we cannot compute
time very accurately. To make it more accurate we can use the compare mode of the timer. In
compare mode we load a register called Output Compare Register with a value of our choice
and the timer will compare the current value of timer with that of Output Compare Register
continuously and when they match the following things can be configured to happen.

1. A related Output Compare Pin can be made to go high,low or toggle automatically.


This mode is ideal for generating square waves of different frequency.
2. It can be used to generate PWM signals used to implement a DAC digital to analog
converter which can be used to control the speed of DC motors.
3. Simply generate an interrupt and call our handler.

On a compare match we can configure the timer to reset it self to 0. This is called CTC -
Clear Timer on Compare match.

The compare feature is not present in the 8 bit TIMER0 of the ATmega8 so we will use the
TIMER1 which is a 16 Bit timer. First we need to setup the timer's prescaler as described in
the Timer0 tutorial. Please see this tutorial for a basic introduction of TIMERs.

The TIMER1 has two compare units so it has two output compare register OC1A and OC1B.
The '1' in the name signifies that they are for timer '1'.

In this tutorial we will create a standard time base which will be useful for many projects
requiring timing such as clocks,timers,stopwatches etc. For this we will configure the timer to
generate an Compare match every millisecond and in the ISR we will increment a variable
clock_millisecond. In this way we will have a accurate time base which we can use for
computing time in seconds,minutes and hours.

References
For learning about the basic idea of peripherals and their use with AVRs please see this
tutorial.

For learning about basics of timers see this.

AVR's Timers1 Registers


I will state the meaning of only those bits which are required for this tutorial. These bits are
marked with a gray back ground in the table. For details about other bits please consult the
datasheets.

Timer/Counter1 Control Register A (TCCR1A)


This register is used to configure the TIMER1. It has the following bits
Bit 7 6 5 4 3 2 1 0
Name COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
InitialValue 0 0 0 0 0 0 0 0

COM1A1 and COM1A0 -

This are used to configure the action for the event when the timer has detected a "match". As
i told earlier the timer can be used to automatically set,clear or toggle the associated Output
compare pin this feature can be configured from here. The table below shows the possible
combinations.

COM1A1 COM1A0 Description


Normal Port Operation (The timer doesn't touches the
0 0
PORT pins).
0 1 Toggle OC1A Pin on match
1 0 Clear OC1A on match - set level to low (GND)
1 1 Set OC1A on match - set level to High(Vcc)

The OC1A pin is the Pin15 on ATmega8 and Pin19 on ATmega16/32. As you may guess that
we don't need any pin toggling or any thing for this project so we go for the first option i.e.
Normal Port Operation

As I have told you that the TIMER1 has two compare unit, the COM1B1/COM1B0 are
used exactly in same way but for the channel B.

WGM11 and WGM10 -

These combined with WGM12 and WGM13 found in TCCR1B are used for selecting proper
mode of operation. WGM= Waveform Generation Mode.

Timer/Counter1 Control Register B (TCCR1B)


This register is also used for configuration. The Bits are.

Bit 7 6 5 4 3 2 1 0
Name ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
InitialValue 0 0 0 0 0 0 0 0

The four bits

WGM13 - WGM12 - WGM11 - WGM10 are used to select the proper mode of operation.
Please refer to the datasheet for complete combinations that can be used. We need the CTC
mode i.e. clear timer on match so we set them as follows

WGM13=0
WGM12=1

WGM11=0

WGM10=0

This is the settings for CTC.

The CS12,CS11,CS10
These are used for selecting the prescalar value for generating clock for the timer. I have
already discussed them on TIMER0 tutorial. I will select the prescalar division factor as 64.
As the crystal we are using is of 16MHz so dividing this by 64 we get the timer clock as

F(timer)=16000000/64 = 250000Hz

so timer will increment its value @ 250000Hz

The setting for this is

CS12 CS11 CS10


0 1 1

So the final code we write is

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

TIMER Counter 1 (TCNT1)


TCNT1H (high byte) TCNT1L(low byte). This is the 16 Bit counter

Output Compare Register 1 A - OCR1A


(OCR1AH,OCR1AL)
You load them with required value. As we need a time base of 1ms and our counter is
running @ 250000Hz i.e. one increment take 1/250000 = 0.000004 Sec or 0.004 ms. So we
need 1ms/0.004 = 250 increments for 1ms. Therefore we set OC1A=250. In this way when
timer value is 250 we will get an interrupt and the frequency of occurrence is 1ms and we
will use this for incrementing a variable clock_millisecond.

Output Compare Register 1 B - OCR1A


(OCR1BH,OCR1BL)
 
Timer Counter Interrupt Mask (TIMSK)
This is the mask register used to selectively enable/disable interrupts. This register is related
with the interrupts of timers (all timers TIMER0,TIMER1,TIMER2).

Bit 7 6 5 4 3 2 1 0
Name OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 - TOIE0
InitialValue 0 0 0 0 0 0 0 0

Of all these bits 5,4,3,2 are for TIMER1 and we are interested in the OCIE1A which is
Output Compare Interrupt Enable 1 A. To enable this interrupt we write

TIMSK|=(1<<OCIE1A);

After enabling the interrupt we also need to enable interrupt globally by using the function

sei();

This function is part of AVR-GCC interrupt system and enables the interrupt globally.
Actually this translate in one machine code so there is no function call overhead.

RS232 Communication – The Basics


RS232 is a asynchronous serial communication protocol widely used in computers and digital
systems. It is called asynchronous because there is no separate synchronizing clock signal as
there are in other serial protocols like SPI and I2C. The protocol is such that it automatically
synchronize itself. We can use RS232 to easily create a data link between our MCU based
projects and standard PC. Excellent example is a commercial Serial PC mouse (not popular
these days, I had got one with my old PC which I bought in year 2000 in those days these
were famous). You can make a data loggers that reads analog value(such as temperatures or
light using proper sensors) using the ADC and send them to PC where a special program
written by you shows the data using nice graphs and charts etc.. actually your imagination is
the limit!

Basics of Serial Communication.


In serial communication the whole data unit, say a byte is transmitted one bit at a time.
While in parallel transmission the whole data unit, say a byte (8bits) are transmitted at once.
Obviously serial transmission requires a single wire while parallel transfer requires as many
wires as there are in our data unit. So parallel transfer is used to transfer data within short
range (e.g. inside the computer between graphic card and CPU) while serial transfer is
preferable in long range.

As in serial transmission only one wire is used for data transfer. Its logic level changes
according to bit being transmitted (0 or 1). But a serial communication need some way of
synchronization. If you don't understand what I mean by "synchronization" then don't worry
just read on it will become clear.

The animation below shows you how a serial transmission would look like (if you can see
electricity).

Fig- A Serial Line.(HIGH=RED & LOW=WHITE)

Can you make out what data is coming? No because you are not synchronized. You need a
way to know when a new byte start and when a bit ends and new bit start. Suppose the line is
low for some time that means a '0' but how many zeros? If we send data like 00001111 then
line is first low for some time and high after that. Then how we know it is four '0's and four
'1's?
Now if we add another line called the clock line to synchronize you then it will become very
easy. You need to note down the value of data line only when you see the "clock line"
high. Lets understand this with help of an animation.

Fig- A Serial Line.(HIGH=RED & LOW=WHITE)

Now you can see how the "clock" line helps you in "synchronizing" the incoming data. In this
way many serial busses like SPI and I2C works. But USART is different in USART there is
no clock line. So it is called UART - Universal Asynchronous Receiver Transmitter. In
USART a start bit and stop bits are used to synchronize the incoming data the.

RS232
In RS232 there are two data lines RX and TX. TX is the wire in which data is sent out to
other device. RX is the line in which other device put the data it need to sent to the device.

Fig- RS232 transmission. The arrows indicates the direction of data


transfer. In addition to RX/TX lines there is a third line i.e. Ground
(GND) or Common.

 
One more thing about RS232. We know that a HIGH =+5v and LOW=0v in TTL / MCU
circuits but in RS232 a HIGH=-12V and LOW=+12V. Ya this is bit weird but it increases
the range and reliability of data transfer. Now you must be wondering how to interface this to
MCUs who understand only 0 and 5v? But you will be very happy to know that there is a
very popular IC which can do this for you! It is MAX232 from Maxim Semiconductors. I
will show you how to make a level converter using MAX232 in next tutorial.

As there is no "clock" line so for synchronization accurate timing is required so transmissions


are carried out with certain standard speeds. The speeds are measured in bits per second.
Number of bits transmitted is also known as baud rate. Some standard baud rates are

 1200
 2400
 4800
 9600
 19200
 38400
 57600
 115200
 ... etc

For our example for discussion of protocol we chose the speed as 9600bps(bits per second).
As we are sending 9600 bits per second one bits takes 1/9600 seconds or 0.000104 sec or 104
uS (microsecond= 10^-6 sec).

To transmit a single byte we need to extra bits they are START BIT AND STOP BIT(more
about them latter). Thus to send a byte a total of ten bits are required so we are sending 960
bytes per second.

Note: The number of stop bits can be one or two (for simplicity we will be using single stop
bit)

There is one more bit the parity bit but again for simplicity we would not be using it)

RS232 Data Transmission.


The data transfer is done in following ways

Transmission

1. When there is no transmission the TX line sits HIGH (-12V See above para) ( STOP
CONDITION )
2. When the device needs to send data it pulls the TX line low for 104uS (This is the
start bit which is always 0)
3. then it send each bits with duration = 104uS
4. Finally it sets TX lines to HIGH for at least 104uS (This is stop bits and is always 1). I
said "at least" because after you send the stop bit you can either start new
transmission by sending a start bit or you let the TX line remain HIGH till next
transmission begin in this case the last bit is more than 104uS.
Fig- Data Transmission on RS232 line.

Reception

1. The receiving device is waiting for the start bit i.e. the RX line to go LOW (+12V see
above para).
2. When it gets start bit it waits for half bit time i.e. 104/2 = 51uS now it is in middle of
start bit it reads it again to make sure it is a valid start bit not a spike.
3. Then it waits for 104uS and now it is in middle of first bit it now reads the value of
RX line.
4. In same way it reads all 8 bits
5. Now the receiver has the data.
Fig- How the Receiver receives the data on RS232 RX li

RS232 Communication – The Level Conversion

Hello and welcome back. Continuing our discussion on RS232 serial communication in this
part we will make a RS232 level converter. In the last tutorial we saw that how RS232 level
signals differs from normal logic signals. So to interface RS232 level signals to our MCUs
we need a "Level converter". And in this tutorial we will make one.

What a level converter will do is to convert RS232 level signals (HIGH=-12V LOW=+12V)
from PC to TTL level signal (HIGH=+5V LOW=0V) to be fed to MCU and also the
opposite.
Fig - Working of RS232 level converter
 

As RS232 is such a common protocol there is a dedicated IC designed for this purpose of
"Level Conversion". This IC is MAX232 from Maxim. By using charge pumps it generates
high voltages(12V) and negative voltages(-12V).

Now lets make it!

Things you need


S.No Item Value Qty
1 MAX232 IC 1
2 Capacitors 1uF 4
3 10uF 1
4 DB9 Female Connector 1
5 General Purpose PCB 1
6 Some Wires - -

 
Fig - Stuffs required for RS232 level converter.
 

Now having all the stuffs in our working table lets begin.

The Schematic
Fig - Schematic for RS232 level converter.
 

Assembly
Assemble the circuit according to the schematic on a small piece of general purpose PCB.
Take out two wires for the power supply(5V) and two wire that connects to the MCUs
RX/TX lines. Connect a DB9 female connector with longer wires because it connects to your
PC. But don't make it too long keep it within 1.5 meter to 2 meter that will be enough.

Take care while connecting the DB9 connector wire must be connected to proper pins as
shown above. To help you the connector has pin numbering on it.

Fig - DB9 PIN Configuration.


 

After soldering wires put the plastic covering.


 
Fig - DB9 with Cover
 

Now the connector can be easily connected to your PC's COM port (Serial Port).
 
Fig - Fully assembled level converter.
 

Testing
It is always better to check each module separately. So we will test our converter to see if its
working fine. For testing we will use a Hyperterminal a Windows software that can be
quickly used to open COM ports and send and receive textual data. Right now you don't need
a MCU or any MCU programming. The theory of testing is that we will connect output
(RX/TX) together so any data written to COM port enters our circuit get converted to TTL
level and loops back and enter MAX232 get converted to RS232 level and enters COM port,
that's it.
Fig - Loop back testing.
 

Now open hyperterminal from Start Menu (All


Programs>Accessories>Communication>Hyperterminal)

1. Enter the name of connection say "testing" and select any icon for it.
Fig - Hyperterminal Main Window
 

2. Select your COM port in the "Connect Using Drop Down List". Note your PC might be
having more than one COM port but commonly only one is available outside the rest are
connected internally to modems etc.
Fig - Select COM port.
 

3) Select

Bits Per second = 9600

Data Bits = 8

Parity = None

Stop bits = 1

Flow control = None (important)

To know what they mean see previous tutorial ().

4) Now the HyperTerminal is ready. Make sure that Hyperterminal has the input focus and
type something on the keyboard, they should echo on screen. Now disconnect the RX from
TX and do the same. This time you should not see any thing on screen. Now your circuit is
ready and working correctly.

If the characters are not echoing to screen your circuit is not working as expected. Check
your connections and try changing the COM port in Hyperterminal.

Note: the circuit should be powered up(by 5V supply) during testing.


Using the USART of AVR Microcontrollers

Welcome to the third part of my RS232 serial communication tutorial. Till now we saw the
basics of RS232 communication and made our level converter. Now its time to understand
the USART of AVR microcontroller and write the code to initialize the USART and use it to
send and receive data.

Like many microcontrollers AVR also has a dedicated hardware for serial communication
this part is called the USART - Universal Synchronous Asynchronous Receiver Transmitter.
This special hardware make your life as programmer easier. You just have to supply the data
you need to transmit and it will do the rest. As you saw serial communication occurs at
standard speeds of 9600,19200 bps etc and this speeds are slow compared to the AVR CPUs
speed. The advantage of hardware USART is that you just need to write the data to one of the
registers of USART and your done, you are free to do other things while USART is
transmitting the byte.

Also the USART automatically senses the start of transmission of RX line and then inputs the
whole byte and when it has the byte it informs you(CPU) to read that data from one of its
registers.

The USART of AVR is very versatile and can be setup for various different mode as required
by your application. In this tutorial I will show you how to configure the USART in a most
common configuration and simply send and receive data. Later on I will give you my library
of USART that can further ease you work. It will be little complicated (but more useful) as it
will have a FIFO buffer and will use interrupt to buffer incoming data so that you are free to
anything in your main() code and read the data only when you need. All data is stored into a
nice FIFO(first in first out queue) in the RAM by the ISR.

USART of AVR Microcontrollers.


The USART of the AVR is connected to the CPU by the following six registers.

 UDR - USART Data Register : Actually this is not one but two register but when you
read it you will get the data stored in receive buffer and when you write data to it goes
into the transmitters buffer. This important to remember it.
 UCSRA - USART Control and status Register A : As the name suggests it is used to
configure the USART and it also stores some status about the USART. There are two
more of this kind the UCSRB and UCSRC.
 UBRRH and UBRRH : This is the USART Baud rate register, it is 16BIT wide so
UBRRH is the High Byte and UBRRL is Low byte. But as we are using C language it
is directly available as UBRR and compiler manages the 16BIT access.

So the connection of AVR and its internal USART can be visualized as follows.
Fig- AVR USART registers.

Registers Explained
In order to write programs that uses the USART you need to understand what each register's
importance. The scheme behind using the AVR USART is same as with any other internal
peripheral (say ADC). So if you are new to this topic please see this tutorial, it shows you the
basic idea of using peripherals.

I am not going to repeat what is already there in the datasheets, I will just tell about what is
required for a quick startup. The datasheets of AVR provides you with all the details of every
bit of every register so please refer to it for detailed info. Note bit names with RED
background are of our interest here.

UDR: Explained above.

UCSRA: USART Control and Status Register A

*****************************************

Bit No 7 6 5 4 3 2 1 0
Name RXC TXC UDRE FE DOR PE U2X MPCM
Initial Val 0 0 1 0 0 0 0 0

RXC this bit is set when the USART has completed receiving a byte from the host (may be
your PC) and the program should read it from UDR

TXC This bit is set (1) when the USART has completed transmitting a byte to the host and
your program can write new data to USART via UDR

 
UCSRB: USART Control and Status Register B

*****************************************

Bit No 7 6 5 4 3 2 1 0
Name RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8
Initial Val 0 0 0 0 0 0 0 0

RXCIE: Receive Complete Interrupt Enable - When this bit is written one the the
associated interrupt is enabled.

TXCIE: Transmit Complete Interrupt Enable - When this bit is written one the the
associated interrupt is enabled.

RXEN: Receiver Enable - When you write this bit to 1 the USART receiver is enabled. The
normal port functionality of RX pin will be overridden. So you see that the associated I/O
pin now switch to its secondary function,i.e. RX for USART.

TXEN: Transmitter Enable - As the name says!

UCSZ2: USART Character Size - Discussed later.

For our first example we won't be using interrupts so we set UCSRB as follows

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

UCSRC: USART Control And Status Register C

*****************************************

Bit No 7 6 5 4 3 2 1 0
Name URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL
Initial Val 0 0 0 0 0 0 0 0

IMPORTANT : The UCSRC and the UBRRH (discussed below) register shares same
address so to determine which register user want to write is decided with the 7th(last) bit of
data if its 1 then the data is written to UCSRC else it goes to UBRRH. This seventh bit is
called the

URSEL: USART register select.

UMSEL: USART Mode Select - This bit selects between asynchronous and synchronous
mode. As asynchronous mode is more popular with USART we will be using that.

UMSEL Mode
0 Asynchronous
1 Synchronous

USBS: USART Stop Bit Select - This bit selects the number of stop bits in the data transfer.

USBS Stop Bit(s)


0 1 BIT
1 2 BIT

UCSZ: USART Character size - These three bits (one in the UCSRB) selects the number of
bits of data that is transmited in each frame. Normally the unit of data in MCU is 8BIT (C
type "char") and this is most widely used so we will go for this. Otherwise you can select
5,6,7,8 or 9 bit frames!

UCSZ2 UCSZ1 UCSZ0 Character Size


0 0 0 5Bit
0 0 1 6Bit
0 1 0 7Bit
0 1 1 8Bit
1 0 0 Reserved
1 0 1 Reserved
1 1 0 Reserved
1 1 1 9Bit

So we set UCSRC as follows

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

UBRR: USART Baud Rate Register:

*********************************

This is the USART Baud rate register, it is 16BIT wide so UBRRH is the High Byte and
UBRRL is Low byte. But as we are using C language it is directly available as UBRR and
compiler manages the 16BIT access. This register is used by the USART to generate the data
transmission at specified speed (say 9600Bps). To know about baud rate see the previous
tutorial. UBRR value is calculated according to following formula.

Where fosc is your CPU frequency say 16MHz

Baud Rate is the required communication speed say 19200 bps (see previous tutorial for more
info).
Example:

For above configuration our UBRR value comes to be 51.083 so we have to set

UBRR=51;

in our initialization section. Note UBRR can hold only integer value. So it is better to use the
baud rates that give UBRR value that are purely integer or very close to it. So if your UBRR
value comes to be 7.68 and you decided to use UBRR=8 then it has high error percentage,
and communication is unreliable!

Initialization of USART
Before using the USART it must be initialized properly according to need. Having the
knowledge of RS232 communication and Internal USART of AVR you can do that easily.
We will create a function that will initialize the USART for us.

#include <avr/io.h>
#include <inttypes.h>

void USARTInit(uint16_t ubrr_value)


{

//Set Baud rate


UBRR= ubrr_value;

/*Set Frame Format

>> Asynchronous mode


>> No Parity
>> 1 StopBit
>> char size 8

*/

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

//Enable The receiver and transmitter


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

Now we have a function that initializes the USART with a given UBRR value.

You might also like