Search This Blog

Tuesday, September 4, 2012

Starting programming in C with AVR

Here are few examples related to various data typed in AVR. These are examples to get one started with using data types.

Data Types revisited
Data Type
Size in Bits
Data Range/Usage
Unsigned char
8 bit
0 to 255
Char
8 bit
-128 to +128
Unsigned int
16 bit
0 to 65535
Int
16 bit
-32768 to +32768
Unsigned long
32 bit
0 to 4,294,967,295
Long
32 bit
-2,147,483,648 to +2,147,483,648
Float
32 bit
1.175e-38 to 3.402e38
Double
32 bit
1.175e-38 to 3.402e38

Using Unsigned Char

Examples
Example 1
//send values 00 - ff to say port B
#include <avr/io.h> // standard avr header file

int main(void)
{
                unsigned char x;
                DDRB = 0xFF; // making all pins of port b as output
                for(x = 0; x<=255; x++)
                {
                                PORTB = x;
                }
                while(1);
                //remember x cannot store value > 255 as its an unsigned char
}
Example 2
// toggle pins of port b 100 times
#include <avr/io.h> // standard avr header file

int main(void)
{
                unsigned char x;
                DDRB = 0xFF; // making all pins of port b as output
                PORTB = 0xAA; // port b 10101010           
                for(x = 0; x<=100; x++)
                {
                                PORTB = ~PORTB;
                }
                while(1);
                //remember x cannot store value > 255 as its an unsigned char
}

Using Signed Char

Example
// program to send values -2 to 2 to port B
#include <avr/io.h>// standard avr header file

int main(void)
{
                char num[] = {-2,-1,0,1,2};
                unsigned char x;

                DDRB = 0xFF;
                // make all pins of port b output
                for(x = 0; x<5; x++)
                {
                                PORTB = num[x];
                }
               
                while(1);
                //remember num can store value between -128 to +128
                // and array in C starts for 0
}

Similarly we can use other data types. Here is toggling example at various values. Demonstrating when to use what type.

Examples
Unsigned int
// toggle pins of port b 50000 times
#include <avr/io.h> // standard avr header file

int main(void)
{
                unsigned int x;
                DDRB = 0xFF; // making all pins of port b as output
                PORTB = 0xAA; // port b 10101010           
                for(x = 0; x<=50000; x++)
                {
                                PORTB = ~PORTB;
                }
                while(1);
                //remember x cannot store value > 65535 as its an unsigned int
}
Unsigned long
// toggle pins of port b 5,00,000 times
#include <avr/io.h> // standard avr header file

int main(void)
{
                unsigned long x;
                DDRB = 0xFF; // making all pins of port b as output
                PORTB = 0xAA; // port b 10101010           
                for(x = 0; x<=500000; x++)
                {
                                PORTB = ~PORTB;
                }
                while(1);
                //remember x can have value  < 2,147,483,648 as its an unsigned long
}

Time Delay can be created
1)      Using a simple for loop
2)      Using predefined C functions
3)      Using AVR timers

I don’t use a simple for loop unless if its value is given along with the driver library. I only use predefined C function to create delay.
Using predefined C function to create a delay
//create 10 milli sec delay
#include <util/delay.h>
#include <avr/io.h>

// delay in milliseconds
void delay_ms(unsinged int t)
{
                _delay_ms(t);
}
int main(void)
{
                DDRB = 0xFF;
                //port b output
                while(1)
                {
                                PORTB = 0xFF;
                                delay_ms(10);
                                PORTB = 0X55;
                                delay_ms(10);
                }
}

Harvard and Von-Neumann Architecture

In processor we need 2 kind of memory spaces program(to store code) and data.
Code – provides instructions to CPU.
Data – provides information to be processed to CPU.

The CPU uses buses to access the code ROM and data RAM memory spaces. The early computers used the same bus for accessing both code and data. Such an architecture is commonly known as von-neumann architecture. This means in von-neumann architecture there is only 1 bus for both data and program code. Meaning its going to be slow down the CPU’s processing speed as one has to wait for other to finish using the buses.

So to speed up the things, harvard architecture was introduced. In this we have separate buses for both program code and data memory. This means we need four sets of buses.
1)      To carry data in and out of CPU.
2)      To carry code into CPU.
3)      To carry address for accessing data.
4)      To carry address for accessing code.

Harvard architecture is usually implemented on microcontrollers.
Von Neumann is usually implemented on processors like x86 etc etc.
But why??
Implementing Harvard on microcontroller is damn easy as both RAM and ROM are on the same chip with distance of micron scale. But implementing it on x86 type PC its very expensive as in x86 both RAM and ROM are outside the CPU. Separate buses(wire traces) will make the motherboard very large and expensive.

Say for example a Pentium processor with 64 bit data bus and 32 bit address bus would require say about 100 wire traces in case of Von Neumann which will become 200 if Harvard architecture is used.

Harvard architecture will make it necessary that large number of pins comes out of processor itself. So for this reason we donot see Harvard architecture on our desktops and laptops.

The AVR uses Harvard architecture internally, but they still use von Neumann architecture if they need external ROM or RAM.
Von-Neumann and Harvard Architecture

Saturday, August 4, 2012

Serial Communication Terminology

Asynchronous versus Synchronous Serial Transmission
In serial communications, the transmitting and receiving device must be synchronized to one another and use a common data rate and protocol. Synchronization allows both the transmitter and receiver to be expecting data transmission/reception at the same time.

There are two basic methods of maintaining ‘‘sync’’ between the transmitter and receiver: asynchronous and synchronous.

In an asynchronous serial communication system, such as the USART aboard theATmega16, framing bits are used at the beginning and end of a data byte. These framing bits alert the receiver that an incoming data byte has arrived and also signals the completion of the data byte reception. The data rate for an asynchronous serial system is typically much slower than the synchronous system, but it only requires a single wire between the transmitter and receiver.

A synchronous serial communication system maintains ‘‘sync’’ between the transmitter and receiver by employing a common clock between the two devices.Data bits are sent and received on the edge of the clock. This allows data transfer rates higher than with asynchronous techniques but requires two lines, data and clock, to connect the receiver and transmitter.
Baud Rate
Data transmission rates are typically specified as a baud or bits per second rate. For example, 9600 baud indicates data are being transferred at 9600 bits per second.
Full Duplex
Often, serial communication systemsmust both transmit and receive data. To do both transmission
and reception simultaneously requires separate hardware for transmission and reception. A single
duplex system has a single complement of hardware that must be switched from transmission
to reception configuration. A full duplex serial communication system has separate hardware for
transmission and reception.
Nonreturn to Zero Coding Format
There aremany different coding standards used within serial communications. The important point is the transmitter and receiver must use a common coding standard so data may be interpreted correctly at the receiving end. The Atmel ATmega16 uses a nonreturn to zero coding standard.
In nonreturn to zero, coding a logic 1 is signaled by a logic high during the entire time slot allocated for a single bit, whereas a logic 0 is signaled by a logic low during the entire time slot allocated for a single bit.
The RS-232Communication Protocol
When serial transmission occurs over a long distance, additional techniques may be used to ensure data integrity. Over long distances, logic levels degrade and may be corrupted by noise. At the receiving end, it is difficult to discern a logic high from a logic low. The RS-232 standard has been around for some time. With the RS-232 standard (EIA-232), a logic 1 is represented with a 12-VDC level, whereas a logic 0 is represented by a +12-VDC level. Chips are commonly available (e.g., MAX232) that convert the 5- and 0-V output levels from a transmitter to RS-232- compatible levels and convert back to 5- and 0-V levels at the receiver. The RS-232 standard also specifies other features for this communication protocol.
Parity
To further enhance data integrity during transmission, parity techniques may be used. Parity is an additional bit (or bits) that may be transmitted with the data byte. The ATmega16 uses a single parity bit. With a single parity bit, a single-bit error may be detected. Parity may be even or odd.

In even parity, the parity bit is set to 1 or 0, such that the number of 1’s in the data byte including the parity bit is even. Meaning number of 1’s in 8 data bit + that in parity bit must be even.
In odd parity, the parity bit is set to 1 or 0, such that the number of 1’s in the data byte including the parity bit is odd. Meaning number of 1’s in 8 data bits + that in parity bit must be odd.
At the receiver, the number of bits within a data byte including the parity bit are counted to ensure that parity has not changed, indicating an error, during transmission.

Serial Communications in AVR

Serial USART
The serial USART is used for full duplex (two-way) communication between a receiver and transmitter. This is accomplished by equipping the ATmega16 with independent hardware for the transmitter and receiver. The USART is typically used for asynchronous communication. That is, there is not a common clock between the transmitter and receiver to keep them synchronized with one another. To maintain synchronization between the transmitter and receiver, framing start and stop bits are used at the beginning and end of each data byte in a transmission sequence.

The ATmega16 USART is quite flexible. It has the capability to be set to a variety of data transmission rates known as the baud (bits per second) rate. The USART may also be set for data bit widths of 5 to 9 bits with one or two stop bits. Furthermore, the ATmega16 is equipped with a hardware-generated parity bit (even or  odd) and parity check hardware at the receiver. A single parity bit allows for the detection of a single bit error within a byte of data. The USART may also be configured to operate in a synchronous mode.
Serial Peripheral Interface
The ATmega16 SPI can also be used for two-way serial communication between a transmitter and a receiver. In the SPI system, the transmitter and receiver share a common clock source. This requires an additional clock line between the transmitter and receiver but allows for higher data transmission rates as compared with the USART.

The SPI may be viewed as a synchronous 16-bit shift register with an 8-bit half residing in the transmitter and the other 8-bit half residing in the receiver. The transmitter is designated the master because it provides the synchronizing clock source between the transmitter and the receiver. The receiver is designated as the slave.
Two-Wire Serial Interface
The TWI subsystem allows the system designer to network a number of related devices (microcontrollers, transducers, displays, memory storage, etc.) together into a system using a two-wire interconnecting scheme. The TWI allows a maximum of 128 devices to be connected together. Each device has its own unique address and may both transmit and receive over the two-wire bus at frequencies up to 400 kHz. This allows the device to freely exchange information with other devices in the network within a small area.
Analog-to-Digital Converter
The ATmega16 is equipped with an eight-channel ADC subsystem. The ADC converts an analog signal from the outside world into a binary representation suitable for use by the microcontroller. The ATmega16 ADC has 10-bit resolution. This means that an analog voltage between 0 and 5 V will be encoded into one of 1024 binary representations between (000)16 and (3FF)16. This provides the ATmega16 with a voltage resolution of approximately 4.88 mV.