Sei sulla pagina 1di 37

Introduction to programming AVR devices in C using AVR studio

Prepared by

A.V.Microtech
Noida (India)
Rev A-1001110
Software packages
You will need functional installation of the following packages.

1) AVR studio
Source Atmel Website :- Installs as ICON

Sreenshot of AVR studio. It comes with a good set of documentation found under Help

2) WinAVR
Source sourceforge.net

The package includes:-

AVR-GCC free GNU c-compiler


AVRdude free AVR flash downloader

To check successful install

Type “avr-gcc” at command prompt and you get (avr-gcc: no input files)

Type “avrdude” at command prompt and you get a list of avrdude flags.

The avrdude documents can be found at C:\winAVR-YYYYMMDD\doc\avrdude\avrdude.pdf


Hardware details

Bootloader:- Microcontrollers like Atmega328p have a portion of flash that can be programmed
with bootloader code to auto download hex program into the main flash (0000 onwards). The
bootloader behave as though you have an in-circuit programmer between your PC and the
atmega328 board.

Upon hardware reset program counter jumps to the start of bootloader. The bootloader waits for
approx 2 sec for the PC (infact avrdude) to establish communication and if no sync character
received in 2 sec, it jumps to 0000 to start executing the code. The bootloader that Arduino board
comes programmed with can only communicate with avrdude.

Fuses :- From the Atmega328 datasheet you can see that it has configurable fuses which decide on
various runtime configuration. For example you can run it from internal clock or various types of
external clocks. Please do not change fuses when operating from bootloader.

We will use USB atmega328 board as shown in picture above. This board works with Arduino and
with a simple customization, seamlessly with AVR studio.

The Arduino environment (IDE) controls DTR signal and with boards having the DTR tied to reset
pin of atmega328, it is easy to bring the device into bootloader when required.

AVR Studio. AVRstudio by default uses STK500. Hence to download data we must come out
from AVR studio and activate avrdude to help us download data into atmega328. For this we will
write a batchfile in the default sub folder of the project directory. The reason being that AVRstudio
C project, keeps its hex file in a subfolder named default. The batchfile content are as below

avrdude -P com1 -b 57600 -p m328p -c AVRISP -F -e -U flash:w:firstcblinky.hex


Shown in the picture is default sub folder of our project “FirstCblinky”

Further we will use a simple hardware configuration to lock the bootloader permanently so that we
do not have the limitation of 2 sec. To enter into locked bootloader mode we will jumper the
Arduino pin12 with RESET as shown in figure below. Upon activating the reset button the
atmega328 will enter into bootloader indefinitely till either code is downloaded or the jumper is
removed.
AVRdude Programmer

The Atmega328 board can also be converted into programmer. Arduino 0018 comes with a sketch
called “Arduino ISP” that converts the board into avrdude USB programmer identified as avrisp
by avrdude. The default baud rate is 19600.

After downloading the Arduino ISP sketch please remove “AUTO” jumper and change the
adjacent jumper from AR to P as shown in picture below. Removing AUTO jumper will prevent
the board into entering bootloader unnecessarily.

Please note this is a complete programmer and can do any modification to Fuse and lockbits. You
can again create a batch file to execute your commands repeatedly.

avrdude -P com1 -b 19600 -p m328p -c AVRISP -F -e -U flash:w:firstcblinky.hex


A typical C program is as shown below:-
******************************************************************************************************

#define F_CPU 16000000

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <math.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>

//function declaration

void PortInit(void);

int main(void) // Main entry into the program


{
PortInit();
uint8_t b; //(8 bit variable just like int a;)
double d;
b = 0b01010101;

while(1) // Loop to run continuously


{
d = 5000;
while(d>0){d = d-1;}
PORTB = b;

d = 5000;
while(d>0){d = d-1;}
PORTB = ~b;

}
}

void PortInit(void)
{
DDRB = 7; //Set port B
}

****************************************************************************************************
int main(void) is the main entry point and is a must for every WinAVR C program. While(1) is a non
terminating loop to keep running untill the reset is pressed.

Port registers are addressed direct (sfr_defs.h). The AVR registers from R1 to R32 are however not
available. In similar way some of the useful instructions like SETB and CLRB also seems to have been lost
but are offered in more usefull way through a mechanism like
PORTB |= _BV(PB1) for sbi (sfr,bit)
PORTB &= ~(_BV(PB1)) for cbi(sfr,bit)

Another C program showing the usage of Interrupts.

#define F_CPU 16000000

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <math.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>

//#define DDRD _SFR_IO8(0x11)

void PortInit(void);
void TimerInit(void);

int main(void)
{
PortInit();
TimerInit();
uint8_t b;//(8 bit variable just like int a;)
//double d;
b = 0b01010101;

while(1)
{
if ((PINB & 1) == 1){

b = ~b;
//b = b & 0b11111110;
PORTB = b & 0b11111110;
}

}
}

void PortInit(void)

{
DDRB = 0b00001111;

ISR(TIMER1_OVF_vect)
{
TCNT1H = 0xF0;
TCNT1L = 0x00;
PORTB |= _BV(0);

void TimerInit(void)
{
//TCCR1A
TCCR1B = 0b00000101;
TIMSK1 |= _BV(0);
sei();

}
Attiny2313 based Character LCD controller
Index
 Introduction page 1
 SPI LCD controller page 2
 Serial LCD controller page 3
 WinAVR C code (atmega328) page 4
 Arduino code page 9
Connecting LCD display is one of the complex interconnection in
a microcontroller project and taking up valuable I/O for small
devices like Atmega168/328. This controller works in two modes
as shown in the pictures below. The Serial mode can be
connected using the Tx out of microcontroller only.

This controller works by using hex code 250 to differentiate


between writing instruction register and data register. Using two
consecutive bytes, hex 250 followed by instruction data byte will
write to instruction register of the LCD. Every data to be sent to
Instruction register must be constructed this way using two bytes.
For Example:-
First command
Serial.write(CR); //where CR is defined as 250
Serial.write(L1);

Second command
Serial.write(CR);
Serial.write(L2);

Any data without hex 250 will be sent to data display register.
The display data (data register) can be send as continuous string.
sprintf(c,"CPU Temp %u%cC ",analogRead(8)/2,0xdf);
Serial.print(c);

This way you can also re-initialize the LCD display from your
code as shown in the Arduino sketch below. The controller has
been tested with many 16x2 LCD display from different
manufacturer.
Important :- The configuration change must always be done in power down mode.
The controller cannot change configuration in power up mode.

Notes

1) Move the three jumper to short D0, D1,D2


2) Use D3 as Chip select signal. If you do not have any other SPI device than this can be pulled low
permanently.
3) The backlight resistor is 500 ohm and it works perfectly with new LCD with high efficiency LED
backlight. However this can be sorted also. Infact this was designed for automatic backlight control
using BC547 transistor. Hence you can replace the resistor with BC547 and connect the base to
AVR/PIC PWM output through 2K resistor.
4) The reset button will also reset the AVR device.
Notes

1) Move the three jumper to short B7, B6,B5


2) Pull D2 to ground as it is polled at the start to configure the controller to either serial or SPI
interface.
3) The backlight resistor is 500 ohm and it works perfectly with new LCD with high efficiency LED
backlight. However this can be sorted also . Infact this was designed for automatic backlight
control using BC547 transistor. Hence you can replace the resistor with BC547 and connect the
base to AVR/PIC PWM output through 2K resistor.
4) Connect Tx out of microcontroller to D0.
WinAVR C Code

#define F_CPU 16000000UL

#define CR 250
#define CD 1

#define L1 0X80 //ROW 0 COL 0


#define L2 0XC0 //ROW 1 COL 0

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <math.h>
#include <stdio.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#include <avr/wdt.h>
//#include <uart.h>

void ADC_InitA (void);


void PWM_Init (void);
void WDT_off(void);
void WDT_Prescaler_Change(void);
int ADC_Meas(void);
void Comm_write( const char* myval, int b);
void Comm_Transmit( char myval, int b);
void SPI_MasterInit(void);
void SPI_MasterTransmit(char cData);
void USART_Init( );
void USART_Transmit( unsigned char data);

int main(void)
{
USART_Init();
SPI_MasterInit();

int d, b;
char c[30] ;
//************************
//b = 0 for serial
//b = 1 for SPI
b = 1;
//******************************
//Clear Display
USART_Transmit( CR );
_delay_us(50);
USART_Transmit( CD );
_delay_us(50);

d = 0;
while(1){
d++;

Comm_Transmit( CR,b );
_delay_us(50);
Comm_Transmit( L1,b );
_delay_us(50);
sprintf(c,"Good welldone!!");
Comm_write( c,b );

Comm_Transmit( CR,b );
_delay_us(50);
Comm_Transmit( L2,b );
_delay_us(50);
sprintf(c,"The Value - %u%cC. ",d, 0xdf);
Comm_write( c,b );

if (d>9){
d = 0;
}

_delay_ms(500);

void USART_Init( )
{
/* Set baud rate */
UBRR0H = 0;
UBRR0L = 103;
UCSR0A &= !(1<<U2X0);//U2X0 = 0
/* Enable Receiver and Transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
//UCSR0B = _BV(TXEN0) | _BV(RXEN0);
/* Set frame format: 8data, 1stop bit */
UCSR0C = (3<<UCSZ00);
//OSCCAL = 0XB0;

void USART_Transmit( unsigned char data )


{
/* Wait for empty transmit buffer */
//! Not. And USCRA with the bit position UDR0E
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}

void Comm_write(const char* myval, int b)


{
int a = 0;
while (a<strlen(myval)){
if (b == 0){
USART_Transmit(myval[a]);
a++;}
if (b > 0){
SPI_MasterTransmit(myval[a]);
a++;}
}
}
void Comm_Transmit( char myval, int b)
{
if (b == 0){
USART_Transmit(myval);
}
if (b > 0){
SPI_MasterTransmit(myval);
}

void SPI_MasterInit(void)
{

/* Set MOSI and SCK output, all others input */


DDRB |=(1<<PORTB2)|(1<<PORTB3)|(1<<PORTB5);//Keep portb2 as output
PORTB = (1<<PORTB4);
/* Enable SPI, Master, set clock rate fck/16 - SPR0 = 1, fck/64- SPR1 = 1*/
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData)


{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
_delay_ms(1);
}
Note:- You may receive new Arduino sketch without the need of HEspi
library(no library will be sent). This is just for the convenience of the user
as otherwise you have to ensure that the library is installed on all the
machines that you are working on. We have retained the code below just
to show the library usage.

Arduino Sketch

Requirement:-

HEspi Library to setup the SPI communication. Please note that the library does not assert any
chip_select . Hence the same library can control many SPI connected device by asserting the pins using
Digital I/O.

//***************************************************
#include <avr/io.h>
#include <stdlib.h>
#include <HEspi.h>

/*LCD CONTROL
CONTROL CHARACTER DECIDED BY INTERNAL OPERATION OF
ATTINY2313 SPI LCD / RS232 CONTROLLER
T0 SEND CONTROL CHARACTERS.
Serial.write(CR);
Serial.write(CD);
OR
Comm (CD,0) (0 for SPI and 1 for RS232)

SEND ASCII 250 AND THEN ANY CONTROL CHARACTER */

#define CR 250 //TO ACCESS CONTROL REGISTER

/*SEE PAGE 191,192,193 OF HITACHI LCD CONTROLLER HD44780 DATSHEET


0 0 0 0 0 0 0 1 */
#define CD 1 //CLEAR DISPLAY

//1 ADD ADD ADD ADD ADD ADD ADD


#define L1 0X80 //ROW 0 COL 0
#define L2 0XC0 //ROW 1 COL 0

// 0 0 0 0 1 D C B
#define CBY 0X0F //CURSOR ON BLINK ON 00001DCB
#define CBN 0X0C //CURSOR 0FF BLINK 0FF
int RCByte;
int TCByte = 0xff;
int mv = 0;
char c[30];
HEspi myspi;
void setup()
{
Serial.begin(9600);
pinMode(6,OUTPUT); //To SPI LCD
pinMode(7,OUTPUT); //To SPI I/O Board.
digitalWrite(7,HIGH);
digitalWrite(6,LOW);
LCD_Reset(0);
LCD_Reset(1);

void loop() // run over and over again


{

digitalWrite(7,HIGH);
digitalWrite(6,LOW);

myspi.write(CR); // | Alternate |
myspi.write(CD); // | Comm(CD) |

Serial.write(CR);
Serial.write(L1);

myspi.print("HobbyElectronic");
sprintf(c,"Trimmer Val %u%% ",analogRead(0)/10);
Serial.print(c);
myspi.write(CR);
myspi.write(L2);
Serial.write(CR);
Serial.write(L2);

myspi.print("support LCD 1");


//Serial.print("support LCD 2");
//
sprintf(c,"CPU Temp %u%cC ",analogRead(8)/2,0xdf);
Serial.print(c);

delay(500);

myspi.write(CR);
myspi.write(CBN);

//digitalWrite(6,HIGH);
//digitalWrite(7,LOW);
////BLINK LED CONNECTED TO ATTINY2313 SPI OPTOISOLATED I/O BOARD
//for (int i=0; i <= 5; i++){

//TCByte = 0;
//RCByte = myspi.Transmit(TCByte);
//delay(500);

//TCByte = 0XFF;
//RCByte = myspi.Transmit(TCByte);

//delay(500);
//}

void LCD_Reset(uint8_t inter) //inter is for interface: 0 for SPI: 1 for RS232
{
Comm(0b00110000,inter);
delay(5);
Comm(0b00110000,inter);
delayMicroseconds(100);
Comm(0b00110000,inter);
Comm(0b00111000,inter);
Comm(0b00001100,inter);
Comm(0b00000001,inter);
Comm(0b00000110,inter);

void Comm(uint8_t mval, uint8_t inter){


if (inter == 0){
myspi.write(CR);
myspi.write(mval); }
if (inter == 1){
Serial.write(CR);
Serial.write(mval);
}
}

//****************************************************************
Line follower Infrared sensor

Arduino Sketch
#include <LiquidCrystal.h>
//The test was done with 33K and 10K resistor. The 33K gives longer range
//but 10k is more immune to reflected sunlight i.e in a well lit room.
// but still can give reasonable 4cm distance sensing.

// LiquidCrystal display with:


// rs on pin 12
// rw on pin 11
// enable on pin 10
// d0, d1, d2, d3 on pins 5, 4, 3, 2
LiquidCrystal lcd(10, 9, 8, 5, 4, 3, 2);
int aval1 =0;
int aval2 = 0;
int refval = 0;
int r=0;
int s=0;
int t=0;
char* str1[] = {"CHANNEL A", "CHANNEL B", "CHANNEL C"};
int lf = 0;
int rg = 0;
int st = 0;

void setup()
{
// Print a message to the LCD.
lcd.print(str1[st]);
lcd.print(analogRead(0));
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
pinMode(11,OUTPUT);
pinMode(7,INPUT);
digitalWrite(12,LOW);
}

void loop()
{
st = 0;
aval1 = 0;
aval2 = 0;
digitalWrite(11,HIGH);
while (st < 10)
{
st++;
digitalWrite(11,HIGH);
delayMicroseconds(10);
aval1 = aval1+analogRead(0);
digitalWrite(11,LOW);
delayMicroseconds(10);
aval2 = aval2+analogRead(0);

}
refval = analogRead(1);
if (abs(aval2-aval1)>refval)
{
digitalWrite(13,HIGH);

}
else
{
digitalWrite(13,LOW);
}
lcd.clear();
lcd.print(str1[0]);
lcd.setCursor(1,1);
lcd.print("Analog=");
lcd.print(aval2-aval1);
lcd.print(" : ");
lcd.print(refval);
delay(100);
}
Attiny2313 Twin DC Motor Driver
Robots like line follower require twin differential DC motor driver. This intelligent board does high speed
processing (16Mhz crystal) and reduces the number of I/O and processing overhead otherwise required by
the main CPU ( AVR or PIC ). Free from latchups and resets, this board offers the highest immunity to
electrical noise. This board can support low voltage motors from Tamiya. It can work as standalone fully
functional Robot controller. Like line tracing, obstacle avoidance or light following robot. This board can
also be run from 3.3V to be compatible with ARM devices.
Web Server

A simple web server that shows the value of the analog input pins, and set Digital
outputs on Attiny23213 Board. In the Demo sketch, only four outputs can be toggled,
however you can easily increase it 8.

This Sketch is currently configured to run on local network. You can plug a straight cable
directly to your PC LAN card. Cross cable is not required (most system can take care of
that).

Kindly ensure that your PC does not use the IP address 192.168.1.110 but another IP
address within the subnet mask 255.255.0.0 for example 192.168.1.120.

The power supply required for arduino board is 6V DC and power required by I/O board
(outputs) is 6V to 12V (DC Power jack). The Wiznet board is supplied with 3.3volts.

Procedure for a proper reset

Hard Reset -> Power off and on.

Soft Reset
1) Press first button on Add on Board (near 5V). This resets Wiznet board
Wait for a few seconds..............
2) Press Reset on I/O board. This resets Arduino 328 board and I/O board.
Interfacing Bootboard with SD Card

This is a functional hardware to connect Bootboard to an SD card. The card tested


was 128MB Panasonic SD card.

SD card pinout and corresponding Arduino and AVR pins are shown below. AVR
uses SPI interace to communicate with SD card.
A regulator like 78M33 can be used to produce 3.3V required for SD card. The
Mosfet used during trial was 2N7000. You also need 10K resistors as shown in
figure below. The DO pin can be directly connected to AVR MISO as 3.3V is logic 1
for AVR. However all the outputs of AVR (Clock, Chip select and MOSI) must use
level converter as shown below. Resistors based level converter are also
suggested by some, but not yet used by us.
Note :-

Please set CPOL and CPHA in SPI setting very carefully the default value is 0, 0 but
many times configuration 1, 1 is the acceptable one. Read the SD card technical
information carefully.

Please contact your seller if you need any further clarification.


Arduino as a Programmer

With Arduino release-0018 it is possible to down load


programming sketch in a AVR and use it to burn programs
or bootloaders in other devices. We have tested the sketch
with Atmega8-16 and the size fits in.You will need a standard
6 pin (2x3) ISP cable.
The step by step instruction is as below.

Step 1) Prepare your Arduino as programmer i.e burn a


programming sketch. Connect you programming board to
your PC as you would do normally to burn sketches. Go to
examples and select ArduinoISP (new in Arduino 0018).
Click upload as you do normally to upload the sketch to your
board. After completion your Programmer is ready.
Step 2) Connect the Target Board ( blank AVR )as in picture
below.
Please maintain the direction of programming cable. Further
the pin1 of programmer’s ISP header must match with Pin1
of target board’s ISP header. Move jumper as in picture
above. Auto Jumper can be removed.
Step 3) Select the correct Board in the Arduino IDE (change
the AVR if you are burning Atmega8-16 / 168 etc).
Upon clicking the button you will see the bootloader being
burnt (flashed) in the target board.
Step 4) Remove all the connection and connect the target
board to the PC and down load your famous blinky to test if
all went well.
Jumper configuration

Potrebbero piacerti anche