• Home   /  
  • Archive by category "1"

Atmega16 Uart Sample Cover Letter

Till now we have seen the basics of RS232 communication, the function of level converter and the internal USART of AVR micro. After understanding the USART of AVR we have also written a easy to use function to initialize the USART. That was the first step to use RS232. Now we will see how we can actually send/receive data via rs232. As this tutorial is intended for those who are never used USART we will keep the things simple so as to just concentrate on the "USART" part. Of course after you are comfortable with usart you can make it more usable my using interrupt driven mechanism rather than "polling" the usart.

So lets get started! In this section we will make two functions :-

  • USARTReadChar() : To read the data (char) from the USART buffer.
  • USARTWriteChar(): To write a given data (char) to the USART.

This two functions will demonstrate the use of USART in the most basic and simplest way. After that you can easily write functions that can write strings to USART.

Reading From The USART : USARTReadChar() Function.

This function will help you read data from the USART. For example if you use your PC to send data to your micro the data is automatically received by the USART of AVR and put in a buffer and bit in a register (UCSRA) is also set to indicate that data is available in buffer. Its now your duty to read this data from the register and process it, otherwise if new data comes in the previous one will be lost. So the funda is that wait until the RXC bit (bit no 7) in UCSRA is SET and then read the UDR register of the USART.

(See the full description of USART registers)

Writing to USART : USARTWriteChar()

This function will help you write a given character data to the USART. Actually we write to the buffer of USART and the rest is done by USART, that means it automatically sends the data over RS232 line. One thing we need to keep in mind is that before writing to USART buffer we must first check that the buffer is free or not. It its not we simply wait until it is free. If its not free it means that USART is still busy sending some other data and once it finishes it will take the new data from buffer and start sending it.

Please not that the data held in the buffer is not the current data which the USART is busy sending. USART reads data from the buffer to its shift register which it starts sending and thus the buffer is free for your data. Every time the USART gets it data from buffer and thus making it empty it notifies this to the CPU by telling "USART Data Register Ran Empty" (UDRE) . It does so by setting a bit (UDRE bit no 5) in UCSRA register.

So in our function we first wait until this bit is set (by the USART ), once this is set we are sure that buffer is empty and we can write new data to it.

(See the full description of USART registers)

Note: Actually their are two separate buffers, one for transmitter and one for receiver. But they share common address. The trick is that all "writes" goes to the Transmitter’s buffer while any "read" you performs comes from the receiver’s buffer.

That means if we read UDR we are reading from receivers buffer and when we are writing to UDR we are writing to transmitters buffer.

UDR=some_data; //Goes to transmitter

some_data=UDR; //Data comes from receiver

(See the full description of USART registers)

Sample program to use AVR USART

The following program makes use of the two functions we developed. This program simply waits for data to become available and then echoes it back via transmitter but with little modification. For example if you send "A" to it, it will send you back "[A]" that is input data but surrounded by square bracket. This program is enough to test the USART yet easy to understand.

Downloads

Running the USART Demo

You can run the above program in a ATmega8, ATmega16, ATmega32 cpu running at 16MHz without any modification. If you are using different clock frequency you have to change the UBRR value that we are passing to USARTInit() function. See previous tutorial for calculating UBRR value. AVR running the USART demo program can be interface to PC using following three ways.

  • Connect to a Physical COM Port.

    If you are lucky and own a really old PC then you may find a Physical COM port on your PC’s back. It is a 9 pin D type male connector. In this case you have to make a RS232 to TTL converter and connect the MCU to COM port via it.

  • Connect to a Virtual COM Port.

  • Those who are not so lucky may buy a Virtual COM port. Again in this case too you need to built a RS232 to TTL converter and connect the MCU to COM port via it.

    Fig. USB to Serial Converter

     

  • Connect Via a Chip CP2102.

    CP2102 is single chip USB to UART Bridge by SiLabs. This chip can be used to connect your embedded applications to USB port and enable them to transfer data with PC. It is the easiest path to build PC interfaced projects, like a PC controlled robot. We have a very good CP2102 module that can be used right out of the box. We have done all PCBs and fine SMD soldering for you.

    CP2102 Based Module.

     

    Female sides provide easy connection to headers.

     

    xBoard MINI v2.0 with ATmega8 MCU

     

    ATmega8 Connected to CP2102

     

  • Connect via Chip PL2303

    PL2303 is yet another low cost chip for USB to serial (TTL Level) conversion. We also have a complete board for it too !

    PL2303 based USB to USART Module

Finding the COM port number of Serial Port

A PC can have several COM ports, each may have some peripheral connected to it like a Modem. Serial Ports on PC are numbered like COM1, COM2 … COMn etc. You first need to figure out in which COM port you have connected the AVR. Only after you have a correct COM port number you can communicate with the AVR using tools such as Hyperterminal. The steps below shows how to get COM port number in case of Virtual COM Ports.

Right Click on "My Computer" icon in Windows Desktop.

My Computer Icon on Windows Desktop

Select "Properties"

System Context Menu

The System Properties will open up. Go to the "Hardware" Tab.

System Properties.

In Hardware tab select "Device Manager" button. It will open up device manager.

Open Device Manager

In Device Manager Find the Node "Ports (COM & LPT)"

Expand the PORT node in Device Manager

Depending on whether you are using a "USB to Serial Converter" or "CP2102 USB/USART Bridge Module" you have to find the port with following name.

Note down the COM port number next to the port name. You need to open this Port in Hyperterminal.

COM Port Number

 

COM Port Number

Communication using a Terminal Program on PC.

Since this is the introductory article about serial communication, we won’t be going in much detail on PC end COM port programming. For this reason we will be using a ready made software for sending and receiving serial data. I will be showing how to use two different terminal program to exchange data with embedded application.

Windows Hyperterminal

This is a default terminal program shipped with Windows OS. You can start it from

Start Menu->All Programs->Accessories->Communication->Hyperterminal.

Hyperterminal is not available in Windows Vista or Windows 7 so you have to use other terminal programs like RealTerm.

On startup it will ask for a connection name. Here we will enter AVR

Create New Connection

After that select a COM port you want to use. If you are using USB to serial adaptor please confirm which COM port number it is using. Other COM ports are usually connected to some device say an Internal modem etc. While some others are Bluetooth COM ports. Don’t use them. If you have a physical com port then most probably it will be COM1. If you select wrong COM port during this step you won’t be able to communicate with the AVR MCU and won’t get expected results.

Select COM Port

Now setup the COM port parameters as follows.

  • Bits per second: 19200
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • Flow Control: None

Setting up the COM port

HyperTerminal is ready for communication now! If everything went right HyperTerminal and AVR will talk happily and AVR will send the following message as we have programmed it.

Screenshot of Hyperterminal Showing the message received from AVR

If the screen shows similar message then you have successfully created a link between PC and your AVR micro. It shows that PC can read the data sent by AVR. To test if the AVR can also read Hyperterminal, press some keys on PC keyboard. Hyperterminal will send them over COM port to the AVR mcu where AVR will process the data. In the simple test program this processing includes returning the same data but enclosed inside [ and ], so if you press ‘k‘ then AVR will return [k]. If you are able to see this on PC screen then you are sure that AVR is receiving the data correctly.

That’s it! It fully tests the Serial Communication Routine and your hardware setup.

Setting Up Realterm and using it to communicate with AVR

If you are running Windows Vista or Windows 7 then the Hyperterminal Program may not be available. So in place of it you can use Realterm. It can be downloaded from here.

Start Realterm from its Desktop Icon. You will get a screen similar to this. Increase the Value of Row to 40 to see whole message.

Screenshot of Realterm Showing the message received from AVR

Setup Realterm as follows. Go to the Port Tab and set it as follows.

  • Baud: 19200
  • Port: Port where you have connected the AVR
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • Hardware Flow Control: None

 

Screenshot of Realterm Setup

After setting up Realterm connect the AVR board with COM port and switch it on. Rest process is same as given above for Hyperterminal.

See Also

JLCPCB - Prototype PCBs for $2 + Free Shipping on First Order

China’s Largest PCB Prototype Manufacturer, 290,000+ Customers & 8000+ Online Orders Per Day

10 PCBs Price: $2 for 2-layer, $15 for 4-layer, $74 for 6-layer

Facing problem with your embedded, electronics or robotics project? We are here to help!
Post a help request.

Avinash

Avinash Gupta is solely focused on free and high quality tutorial to make learning embedded system fun !

More Posts - Website

Follow Me:

The USART of the AVR

Hey folks! Lets continue with our tutorials on Serial Communication. Until now, we have seen a general introduction to serial communication, followed by a tutorial on the concepts of RS-232 communication. So here we are with the AVR communication protocols series, starting with the most basic ones, UART and USART! We will move on to SPI and TWI (I2C) later.

Some images used in this tutorial are taken directly from (and are a courtesy of) the AVR datasheets for ATMega8 and ATMega16/32 microcontrollers.

Contents

UART and USART

The UART and USART have already been discussed here. Anyways, lets have a quick recap.

UART stands for Universal Asynchronous Receiver/Transmitter. From the name itself, it is clear that it is asynchronous i.e. the data bits are not synchronized with the clock pulses.

USART stands for Universal Synchronous Asynchronous Receiver/Transmitter. This is of the synchronous type, i.e. the data bits are synchronized with the clock pulses.

If you refer to the USART section in the datasheet of any AVR microcontroller, you will find several features listed there. Some of the main features of the AVR USART are:

  • Full Duplex Operation (Independent Serial Receive and Transmit Registers)
  • Asynchronous or Synchronous Operation
  • Master or Slave Clocked Synchronous Operation
  • High Resolution Baud Rate Generator
  • Supports Serial Frames with 5, 6, 7, 8, or 9 Data bits and 1 or 2 Stop Bits

USART Layout – How to set it up?

Before we continue, please note that the AVR USART is fully compatible with the AVR UART in terms of register bit locations, baud rate generation, transmitter/receiver operations and buffer functionality. So let us now have a quick look at how to set up USART in general. We will discuss in detail later.

  1. The first step is to set the baud rate in both, the master and the slave. The baud rate has to be the same for both – master and slave.
  2. Set the number of data bits, which needs to be sent.
  3. Get the buffer ready! In case of transmission (from AVR to some other device), load it up with the data to be sent, whereas in case of reception, save the previous data so that the new received data can be overwritten onto it.
  4. Then enable the transmitter/receiver according to the desired usage.

One thing to be noted is that in UART, there is no master or slave since master is defined by the MicroController, which is responsible for clock pulse generation. Hence Master and Slave terms occur only in the case of USART.

Master µC is the one which is responsible for Clock pulse generation on the Bus.

USART Pin Configuration

Now lets have a look at the hardware pins related to USART. The USART of the AVR occupies three hardware pins pins:

  1. RxD: USART Receiver Pin (ATMega8 Pin 2; ATMega16/32 Pin 14)
  2. TxD: USART Transmit Pin (ATMega8 Pin 3; ATMega16/32 Pin 15)
  3. XCK: USART Clock Pin (ATMega8 Pin 6; ATMega16/32 Pin 1)

Modes of Operation

The USART of the AVR can be operated in three modes, namely-

  1. Asynchronous Normal Mode
  2. Asynchronous Double Speed Mode
  3. Synchronous Mode

Asynchronous Normal Mode

In this mode of communication, the data is transmitted/received asynchronously, i.e. we do not need (and use) the clock pulses, as well as the XCK pin. The data is transferred at the BAUD rate we set in the UBBR register. This is similar to the UART operation.

Asynchronous Double Speed Mode

This is higher speed mode for asynchronous communication. In this mode also we set the baud rates and other initializations similar to Normal Mode. The difference is that data is transferred at double the baud we set in the UBBR Register.

Setting the U2X bit in UCSRA register can double the transfer rate. Setting this bit has effect only for the asynchronous operation. Set this bit to zero when using synchronous operation. Setting this bit will reduce the divisor of the baud rate divider from 16 to 8, effectively doubling the transfer rate for asynchronous communication. Note however that the Receiver will in this case only use half the number of samples (reduced from 16 to 8) for data sampling and clock recovery, and therefore a more accurate baud rate setting and system clock are required when this mode is used. For the Transmitter, there are no downsides.

Synchronous Mode

This is the USART operation of AVR. When Synchronous Mode is used (UMSEL = 1 in UCSRC register), the XCK pin will be used as either clock input (Slave) or clock output (Master).

Baud Rate Generation

The baud rate of UART/USART is set using the 16-bit wide UBRR register. The register is as follows:

UBRR Register (Click to Enlarge)

Since AVR is an 8-bit microcontroller, every register should have a size of 8 bits. Hence, in this case, the 16-bit UBRR register is comprised of two 8-bit registers – UBRRH (high) and UBRRL (low). This is similar to the 16-bit ADC register (ADCH and ADCL, remember?). Since there can be only specific baud rate values, there can be specific values for UBRR, which when converted to binary will not exceed 12 bits. Hence there are only 12 bits reserved for UBRR[11:0]. We will learn how to calculate the value of UBRR in a short while in this post.

The USART Baud Rate Register (UBRR) and the down-counter connected to it functions as a programmable prescaler or baud rate generator. The down-counter, running at system clock (FOSC), is loaded with the UBRR value each time the counter has counted down to zero or when the UBRRL Register is written. A clock is generated each time the counter reaches zero.

This clock is the baud rate generator clock output (). The transmitter divides the baud rate generator clock output by 2, 8, or 16 depending on mode. The baud rate generator output is used directly by the receiver’s clock and data recovery units.

Below are the equations for calculating baud rate and UBRR value:

Baud Rate Calculation (Click to Enlarge)

  1. BAUD = Baud Rate in Bits/Second (bps) (Always remember, Bps = Bytes/Second, whereas bps = Bits/Second)
  2. FOSC  = System Clock Frequency (1MHz) (or as per use in case of external oscillator)
  3. UBRR = Contents of UBRRL and UBRRH registers

Frame Formats

A frame refers to the entire data packet which is being sent/received during a communication. Depending upon the communication protocol, the formats of the frame might vary. For example, TCP/IP has a particular frame format, whereas UDP has another frame format. Similarly in our case, RS232 has a typical frame format as well. If you have gone through the loopback test discussed in the previous tutorial, you will notice that we have chosen options such as 8 bits data, 1 stop bit, no parity, etc. This is nothing but the selection of a frame format!

A typical frame for USART/RS232 is usually 10 bits long: 1 start bit, 8 data bits, and a stop bit. However a vast number of configurations are available… 30 to be precise!

Frame Format (Click to Enlarge)

Order of Bits

  1. Start bit (Always low)
  2. Data bits (LSB to MSB) (5-9 bits)
  3. Parity bit (optional) (Can be odd or even)
  4. Stop bit (1 or 2) (Always high)

A frame starts with the start bit followed by the least significant data bit. Then the next data bits, up to a total of nine, are succeeding, ending with the most significant bit. If enabled, the parity bit is inserted after the data bits, before the stop bits. When a complete frame is transmitted, a new frame can directly follow it, or the communication line can be set to an idle (high) state. Here is the frame format as mentioned in the AVR datasheet-

Frame Format (Click to Enlarge)

Note:The previous image (not the above one, the one before that) of Frame Format has a flaw in it! If you can find it, feel free to comment below! Let me see how many of you can spot it! And I’m not kidding, there is a mistake! ;)

Setting the Number of DATA Bits

The data size used by the USART is set by the UCSZ2:0, bits in UCSRC Register. The Receiver and Transmitter use the same setting.

Note: Changing the settings of any of these bits (on the fly) will corrupt all ongoing communication for both the Receiver and Transmitter. Make sure that you configure the same settings for both transmitter and receiver.

Data Bit Settings (Click to Enlarge)

Setting Number of STOP Bits

This bit selects the number of stop bits to be inserted by the transmitter. The Receiver ignores this setting. The USBS bit is available in the UCSRC Register.

Stop Bit Settings (Click to Enlarge)

Parity Bits

Parity bits always seem to be a confusing part.  Parity bits are the simplest methods of error detection. Parity is simply the number of ‘1’ appearing in the binary form of a number. For example, ‘55’ in decimal is 0b00110111, so the parity is 5, which is odd.

Even and Odd Parity

In the above example, we saw that the number has an odd parity. In case of even parity, the parity bit is set to 1, if the number of ones in a given set of bits (not including the parity bit) is odd, making the number of ones in the entire set of bits (including the parity bit) even. If the number of ones in a given set of bits is already even, it is set to a 0. When using odd parity, the parity bit is set to 1 if the number of ones in a given set of bits (not including the parity bit) is even, making the number of ones in the entire set of bits (including the parity bit) odd. When the number of set bits is odd, then the odd parity bit is set to 0.

Still confused? Simply remember – even parity results in even number of 1s, whereas odd parity results in odd number of 1s. Lets take another example. 0d167 = 0b10100111. This has five 1s in it. So in case of even parity, we add another 1 to it to make the count rise to six (which is even). In case of odd parity, we simply add a 0 which will stall the count to five (which is odd). This extra bit added is called the parity bit! Check out the following example as well (taken from Wikipedia):

7 bits of data

(count of 1 bits)8 bits including parity
even

odd

000000000000000000000001
101000131010001110100010
110100141101001011010011
111111171111111111111110

But why use the Parity Bit?

Parity bit is used to detect errors. Lets say we are transmitting 0d167, i.e. 0b10100111. Assuming an even parity bit is added to it, the data being sent becomes 0b101001111 (pink bit is the parity bit). This set of data (9 bits) is being sent wirelessly. Lets assume in the course of transmission, the data gets corrupted, and one of the bits is changed. Ultimately, say, the receiver receives 0b100001111. The blue bit is the error bit and the pink bit is the parity bit. We know that the data is sent according to even parity. Counting the number of 1s in the received data, we get four (excluding even parity bit) and five (including even parity bit). Now doesn’t it sound amusing? There should be even number of 1s including the parity bit, right? This makes the receiver realize that the data is corrupted and will eventually discard the data and wait/request for a new frame to be sent. This is explained in the following diagram as well-

Why do we need Parity Bit? (Click to Enlarge)

Limitations of using single parity bit is that it can detect only single bit errors. If two bits are changed simultaneously, it fails. Using Hamming Code is a better solution, but it doesn’t fit in for USART and is out of the scope of this tutorial as well!

The Parity Generator calculates the parity bit for the serial frame data. When parity bit is enabled (UPM1 = 1), the Transmitter control logic inserts the parity bit between the last data bit and the first stop bit of the frame that is sent. The parity setting bits are available in the UPM1:0 bits in the UCSRC Register.

Parity Settings (Click to Enlarge)

Although most of the times, we do not require parity bits.

Register Description

Now lets learn about the registers which deal with the USART. If you have worked with ADC and timers before, you would know that we need to program the registers in order to make the peripheral work. The same is the case with USART. The USART of AVR has five registers, namely UDR, UCSRA, UCSRB, UCSRC and UBBR. We have already discussed about UBBR earlier in this post, but we will have another look.

UDR: USART Data Register (16-bit)

UDR – UART Data Register (Click to Enlarge)

The USART Transmit Data Buffer Register and USART Receive Data Buffer Registers share the same I/O address referred to as USART Data Register or UDR. The Transmit Data Buffer Register (TXB) will be the destination for data written to the UDR Register location. Reading the UDR Register location will return the contents of the Receive Data Buffer Register (RXB).

For 5-, 6-, or 7-bit characters the upper unused bits will be ignored by the Transmitter and set to zero by the Receiver.

UCSRA: USART Control and Status Register A (8-bit)

UCSRA – USART Control and Status Register A (Click to Enlarge)

  • Bit 7: RxC – USART Receive Complete Flag: This flag bit is set by the CPU when there are unread data in the Receive buffer and is cleared by the CPU when the receive buffer is empty. This can also be used to generate a Receive Complete Interrupt (see description of the RXCIE bit in UCSRB register).
  • Bit 6: TxC – USART Transmit Complete Flag: This flag bit is set by the CPU when the entire frame in the Transmit Shift Register has been shifted out and there is no new data currently present in the transmit buffer (UDR). The TXC Flag bit is automatically cleared when a Transmit Complete Interrupt is executed, or it can be cleared by writing a one (yes, one and NOT zero) to its bit location. The TXC Flag can generate a Transmit Complete Interrupt (see description of the TXCIE bit in UCSRB register).
  • Bit 5: UDRE – USART Data Register Empty: The UDRE Flag indicates if the transmit buffer (UDR) is ready to receive new data. If UDRE is one, the buffer is empty, and therefore ready to be written. The UDRE Flag can generate a Data Register Empty Interrupt (see description of the UDRIE bit in UCSRB register). UDRE is set after a reset to indicate that the Transmitter is ready.
  • Bit 4: FE – Frame Error: This bit is set if the next character in the receive buffer had a Frame Error when received (i.e. when the first stop bit of the next character in the receive buffer is zero). This bit is valid until the receive buffer (UDR) is read. The FE bit is zero when the stop bit of received data is one. Always set this bit to zero when writing to UCSRA.
  • Bit 3: DOR – Data Overrun Error: This bit is set if a Data OverRun condition is detected. A Data OverRun occurs when the receive buffer is full (two characters), and a new start bit is detected. This bit is valid until the receive buffer (UDR) is read. Always set this bit to zero when writing to UCSRA.
  • Bit 2: PE – Parity Error: This bit is set if the next character in the receive buffer had a Parity Error when received and the parity checking was enabled at that point (UPM1 = 1). This bit is valid until the receive buffer (UDR) is read. Always set this bit to zero when writing to UCSRA.
  • Bit 1: U2X – Double Transmission Speed: This bit only has effect for the asynchronous operation. Write this bit to zero when using synchronous operation. Writing this bit to one will reduce the divisor of the baud rate divider from 16 to 8 effectively doubling the transfer rate for asynchronous communication.
  • Bit 0: MPCM – Multi-Processor Communication Mode: This bit enables the Multi-processor Communication mode. When the MPCM bit is written to one, all the incoming frames received by the USART Receiver that do not contain address information will be ignored. The Transmitter is unaffected by the MPCM setting. This is essential when the receiver is exposed to more than one transmitter, and hence must use the address information to extract the correct information.

UCSRB: USART Control and Status Register B (8-bit)

UCSRB – USART Control and Status Register B (Click to Enlarge)

  • Bit 7: RXCIE – RX Complete Interrupt Enable: Writing this bit to one enables interrupt on the RXC Flag. A USART Receive Complete interrupt will be generated only if the RXCIE bit is written to one, the Global Interrupt Flag in SREG is written to one and the RXC bit in UCSRA is set. The result is that whenever any data is received, an interrupt will be fired by the CPU.
  • Bit 6: TXCIE – TX Complete Interrupt Enable:  Writing this bit to one enables interrupt on the TXC Flag. A USART Transmit Complete interrupt will be generated only if the TXCIE bit is written to one, the Global Interrupt Flag in SREG is written to one and the TXC bit in UCSRA is set. The result is that whenever any data is sent, an interrupt will be fired by the CPU.
  • Bit 5: UDRIE – USART Data Register Empty Interrupt Enable: Writing this bit to one enables interrupt on the UDRE Flag (remember – bit 5 in UCSRA?). A Data Register Empty interrupt will be generated only if the UDRIE bit is written to one, the Global Interrupt Flag in SREG is written to one and the UDRE bit in UCSRA is set. The result is that whenever the transmit buffer is empty, an interrupt will be fired by the CPU.
  • Bit 4: RXEN – Receiver Enable: Writing this bit to one enables the USART Receiver. The Receiver will override normal port operation for the RxD pin when enabled.
  • Bit 3: TXEN – Transmitter Enable: Writing this bit to one enables the USART Transmitter. The Transmitter will override normal port operation for the TxD pin when enabled.
  • Bit 2: UCSZ2 – Character Size: The UCSZ2 bits combined with the UCSZ1:0 bits in UCSRC register sets the number of data bits (Character Size) in a frame the Receiver and Transmitter use. More information given along with UCSZ1:0 bits in UCSRC register.
  • Bit 1: RXB8 – Receive Data Bit 8: RXB8 is the ninth data bit of the received character when operating with serial frames with nine data bits. It must be read before reading the low bits from UDR.
  • Bit 0: TXB8 – Transmit Data Bit 8: TXB8 is the ninth data bit in the character to be transmitted when operating with serial frames with nine data bits. It must be written before writing the low bits to UDR.

UCSRC: USART Control and Status Register C (8-bit)

The UCSRC register can be used as either UCSRC, or as UBRRH register. This is done using the URSEL bit.

UCSRC – USART Control Register C (Click to Enlarge)

  • Bit 7: URSEL – USART Register Select: This bit selects between accessing the UCSRC or the UBRRH Register. It is read as one when reading UCSRC. The URSEL must be one when writing the UCSRC.
  • Bit 6: UMSEL – USART Mode Select: This bit selects between Asynchronous and Synchronous mode of operation.

    Synchronous/Asynchronous Selection (Click to Enlarge)

  • Bit 5:4: UPM1:0 – Parity Mode: This bit helps you enable/disable/choose the type of parity.

    Parity Settings (Click to Enlarge)

  • Bit 3: USBS – Stop Bit Select: This bit helps you choose the number of stop bits for your frame.

    Stop Bit Settings (Click to Enlarge)

  • Bit 2:1: UCSZ1:0 – Character Size: These two bits in combination with the UCSZ2 bit in UCSRB register helps choosing the number of data bits in your frame.

    Data Bit Settings (Click to Enlarge)

  • Bit 0: UCPOL – Clock Polarity:  This bit is used for Synchronous mode only. Write this bit to zero when Asynchronous mode is used. The UCPOL bit sets the relationship between data output change and data input sample, and the synchronous clock (XCK).

    UCPOL Bit Settings (Click to Enlarge)

UBRR: USART Baud Rate Register (16-bit)

UBRR Register (Click to Enlarge)

We have already seen this register, except the URSEL bit.

  • Bit 15: URSEL: This bit selects between accessing the UBRRH or the UCSRC Register. It is read as zero when reading UBRRH. The URSEL must be zero when writing the UBRRH.

Let’s code it!

Now its been enough of theory. Let’s get our hands dirty with some actual code! Here is how we will structure out code – first initialize UART, then read from it, and then write to it.

Initializing UART

Initializing UART involves the following steps:

  1. Setting the Baud Rate
  2. Setting Data Size (5/6/7/8/9 bits)
  3. Enabling Reception/ Transmission (In the TXEN and RXEN bits in UCSRB)
  4. Setting parity, and number of Stop Bits.

Below is the code to initialize UART, explanation follows it. You can scroll the code sideways in order to view it completely.

// define some macros #define BAUD 9600 // define baud #define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) // set baud rate value for UBRR // function to initialize UART void uart_init (void) { UBRRH = (BAUDRATE>>8); // shift the register right by 8 bits UBRRL = BAUDRATE; // set baud rate UCSRB|= (1<<TXEN)|(1<<RXEN); // enable receiver and transmitter UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); // 8bit data format }

Explanation

The variable (or macro) used to set the baud rate is . The variable (or macro) is defined as per the calculations according to which, the baud rate is set in the registers.

One thing to note is that and share the same I/O location in the memory.  So, the bit that controls the selection/switching of the registers is the Bit in the register. This creates a lot of confusion, and if this bit is not handled properly, UART doesn’t work! So pay attention to the code initialization.

If is zero during a write operation, the value will be updated. If is one, the setting will be updated. This means that while bit is 0, and even if we are addressing , will be addressed, which would in turn result in setting up of wrong, non standard baud rates, and everything getting messed up! Since the default value of is 0, it is safe to first use , and then use the Register.

The bits and are set to 1 to enable UART transmission and reception.

The Bits and are used to select the number of data bits to be transmitted. As per the table, we have set the two bits to transmit/receive 8 bits.

Transmission/Reception Code

The following code is for transmitting data, explanation follows it. You can scroll the code sideways in order to view to code completely.

// function to send data void uart_transmit (unsigned char data) { while (!( UCSRA & (1<<UDRE))); // wait while register is free UDR = data; // load data in the register }

The following code is for transmitting data, explanation follows it. You can scroll the code sideways in order to view to code completely.

// function to receive data unsigned char uart_recieve (void) { while(!(UCSRA) & (1<<RXC)); // wait while data is being received return UDR; // return 8-bit data }

Explanation

The above code snippets are to transmit and receive data respectively. In both of them, we first wait for the flag bits denoting data register empty bit , and receive complete bit respectively to get set, and then take the next action.

When we transmit the data, we load the 8-bit data into the (UART Data Register) to be transmitted.

When we want to receive data, we wait for the whole data to be received first, and then return the value of the received data stored in .

Problem Statement

Let’s take a problem statement now. Let’s say we have to send serial data through a serial terminal emulator on a PC, and receive it on a AVR microcontroller, and display it on an LCD. The displayed values should be in ASCII format.

Methodology

For this, we need to connect an LCD to our microcontroller, and configure the LCD header file accordingly. To learn about interfacing LCD with AVR, read this tutorial written by Mayank. We will also need to connect the USB-UART Bridge with the microcontroller. If you have followed the loopback test of the previous tutorial, then this will be easy for you. Here is the methodology you need to follow:

  1. Send data from your PC using a serial terminal emulator. This has been discussed in the loopback test.
  2. Connect your microcontroller to your PC using the USB-UART Bridge. Schematics follow.
  3. Connect your LCD with your microcontroller. Schematics follow.
  4. Receive serial data through the RxD pin of your microcontroller.
  5. Process the data.
  6. Display the data in the LCD.

Hardware Connections

Here is the schematics which shows how to connect LCD and USB-UART Bridge with your microcontroller. Remember, the TX of USB-UART bridge is connected to the RX of the microcontroller, and vice versa.

UART-LCD Schematics (Click to Enlarge)

Coding

I have made some changes in the LCD header file (lcd.h), so that the LCD is operated by 2 ports (PORTB and PORTD) instead of a single port. Following are the changes: (refer to this tutorial to know more)

#define LCD_PORT1 PORTD /**< port1 for the LCD lines */ #define LCD_PORT2 PORTB /**< port2 for the LCD lines */ #define LCD_DATA0_PORT LCD_PORT2 /**< port for 4bit data bit 0 */ #define LCD_DATA1_PORT LCD_PORT2 /**< port for 4bit data bit 1 */ #define LCD_DATA2_PORT LCD_PORT2 /**< port for 4bit data bit 2 */ #define LCD_DATA3_PORT LCD_PORT2 /**< port for 4bit data bit 3 */ #define LCD_DATA0_PIN 0 /**< pin for 4bit data bit 0 */ #define LCD_DATA1_PIN 1 /**< pin for 4bit data bit 1 */ #define LCD_DATA2_PIN 2 /**< pin for 4bit data bit 2 */ #define LCD_DATA3_PIN 3 /**< pin for 4bit data bit 3 */ #define LCD_RS_PORT LCD_PORT1 /**< port for RS line */ #define LCD_RS_PIN 5 /**< pin for RS line */ #define LCD_RW_PORT LCD_PORT1 /**< port for RW line */ #define LCD_RW_PIN 6 /**< pin for RW line */ #define LCD_E_PORT LCD_PORT1 /**< port for Enable line */ #define LCD_E_PIN 7 /**< pin for Enable line */

What I am going to demonstrate here is very simple. We just need to configure LCD, UART, and its done! Below is the full code. The code is commented well, and doesn’t need any further explanation (provided you have understood all the concepts till now, which I truly believe!). In case you need any help in comprehending the code, feel free to comment below. You can scroll the code sideways in order to view to code completely.

Full Code

You can also find the code on pastebin, and the AVR code gallery. The AVR code gallery contains the LCD files as well. To learn how to write, build, compile and execute your code using Atmel Studio 6, view this tutorial.

#include <avr/io.h> #include <util/delay.h> #include <stdlib.h> #include "lcd.h" // include LCD library #define BAUD 9600 // define baud #define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) // set baudrate value for UBRR #ifndef F_CPU #define F_CPU 16000000UL // set the CPU clock #endif // function to initialize UART void uart_init (void) { UBRRH=(BAUDRATE>>8); UBRRL=BAUDRATE; //set baud rate UCSRB|=(1<<TXEN)|(1<<RXEN); //enable receiver and transmitter UCSRC|=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);// 8bit data format } // function to send data - NOT REQUIRED FOR THIS PROGRAM IMPLEMENTATION void uart_transmit (unsigned char data) { while (!( UCSRA & (1<<UDRE))); // wait while register is free UDR = data; // load data in the register } // function to receive data unsigned char uart_recieve (void) { while(!(UCSRA) & (1<<RXC)); // wait while data is being received return UDR; // return 8-bit data } // main function: entry point of program int main (void) { unsigned char a; char buffer[10]; uart_init(); // initialize UART lcd_init(LCD_DISP_ON_CURSOR); // initialize LCD lcd_home(); // goto LCD Home while(1) { a=uart_recieve(); // save the received data in a variable itoa(a,buffer,10); // convert numerals into string lcd_clrscr(); // LCD clear screen lcd_home(); // goto LCD home lcd_puts(buffer); // display the received value on LCD _delay_ms(100); // wait before next attempt } return 0; }

Hardware Setup

My hardware setup looked something like this–

AVR USART Hardware Setup (Click to Enlarge)

Video

Here is a short video of the implementation of the above code.

Can you do it?

Alright, so this was just an introduction. You can try out the following things as well by modifying the above code:

  1. Extend the above problem statement by sending back the data you received from the computer with some alterations. For example, if you send from your PC, you should receive back from the microcontroller, which should be displayed in the serial terminal console window.
    Hint: While sending the received data, send it in between and . a. Receive Data b. Send '[' c. Send received Data back d. Send ']' e. Repeat this forever
  2. Send data from one microcontroller to another microcontroller, and display the result using an LCD.
    Hint: You should connect the TXD of one microcontroller to RXD of another microcontroller. You can use wired connection for now.
  3. Extend the above to a full-duplex communication. Two microcontrollers send and receive data simultaneously.
    Hint: Connect TXD of one microcontroller to RXD of other. You can use wired connection for now.

Do it and show the world that you are awesome!

If you have tried any of the above three challenges, then you are most welcome to record a video of your implementation, post it on YouTube and share the link below as comment! This will ensure that the world looks at your awesomeness. But wait, its not over yet! Your video might get featured just below this line as well! So, what are you waiting for?

Summary

Now that we have come to an end of another long post, let’s summarize what we have learnt–

  • We know what’s UART and USART.
  • We know how to set up USART, its pin configuration and three modes of operation.
  • We learnt how to set baud rate for a USART data transfer.
  • We learnt how to send the data – frame formats, data bits, stop bits, and about parity.
  • We got familiarized with different USART registers – UDR, UCSRA, UCSRB, UCSRC and UBRR.
  • We saw some sample codes, and then implemented a problem statement as well.
  • We learnt how to make hardware connections as well.

So folks, that’s it for now. We will return back soon with more tutorials! :) So subscribe to stay updated! And don’t forget to share your views and questions as comments below! :)

Written By-
Yash Tambi
VIT University, Vellore
tambi@maxEmbedded.com

Mayank Prasad
Arizona State University
max@maxEmbedded.com

Like this:

LikeLoading...

Related

One thought on “Atmega16 Uart Sample Cover Letter

Leave a comment

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *