Hands On AVR

From SGMK-SSAM-WIKI

Jump to: navigation, search

Contents

Overview

This wiki page is dedicated to AVR development with focus on the ATtiny13 and ATtiny85 (has more memory... naaaiiice)

Links

wanna use the arduino programming language? check this

Memory

The ATtiny13 has two main memories:

Program memory is 1K Bytes. It's organized as 512x16 Bits, because all AVR instructions are 16 or 32 bits wide.

Tiny13-progmem.jpg

Data memory is 64 bytes of SRAM (internal memory) + 64 I/O Registers + 32 general purpose registers.

Tiny13-datamem.jpg

Furthermore there's electrically erasable programmable read-only memory (EEPROM) of 64 Bytes. Single bytes can be read and written.

I/O Ports

Individual I/O ports can be set as input or output. Each output can deliver 40mA.

The ATtiny13 has 6 I/O pins named: PB0, PB1, PB2, PB3, PB4 and PB5. Generally AVR ports are named Pxn, x is the letter of the port, n is the pin number.

All pins of PORTB of the attiny13 can be configured with only three registers:

Notes:


ArduinoISP

ArduinoISP Steckplatine.png ArduinoISP Aufbau.jpg

Arduino can be used as an In-system programming (ISP) interface for the ATtiny and ATmega microcontrollers.

Here are step-by-step instructions on how to program an attiny13 with an LED blinking program:

the code:

/*
hello, LED!
 
attiny13 Pins:
 
1: RESET (Arduino 10)
2: NC (not connected)
3: R (470Ω) to LED to GND
4: GND (Arduino Gnd)
5: MOSI (Arduino 11)
6: MISO (Arduino 12)
7: SCK (Arduino 13)
8: VCC (Arduino 5V)
 
*/
 
#define F_CPU 9600000	// Define software reference clock for delay duration
 
#include <avr/io.h>
#include <util/delay.h>
 
#define LED PB4 // Define led output on PB4
 
int main()
{
	DDRB |= (1 << LED); // Set direction to output for LED
 
	for (;;) {	// forever
		PORTB ^= (1 << LED);  // toggle pin
		_delay_ms(1000);
	}
	return 0;
}

avrdude -P COM1 -b 19200 -c avrisp -p attiny13 -U flash:w:led.hex:i

linux: use /dev/ttyUSB.. instead of COM1.

We have to change the fuse bits.

ISP Programming

AVR can be programmed using the In-System-Programming interface ISP. Different programmers are available: AVR pocket programmer, USBtinyISP, official Atmel programmers.

Breadboard setup:

Attiny13-ISP-breakout.png 6pinAVRproghead.jpg

Solder a breakout cable. You could also connect the lines from the programmer directly to the tiny pins. If you're too lazy, buy the sparkfun Programming Adapter.

LED Example:

Note: other programmers can be defined, if you are for example using the "AVR Pocket programmer", AVRDUDE_PROGRAMMER must be set to "usbtiny", for "AVRISP mkII", set it to 'stk500'. all programmers can be listed with the command avrdude -c ?

We have to change the fuse bits.

High Voltage Fuse Resetter

IMAG0467.jpg

If the fusebits are messed up, the AVR can be factory resetted. This can be done with "high-voltage serial programming". Here is a excellent project to reset attiny13/25/45/85 chips: hvsp fuse resetter

tips:

Links

Tutorials

fusecalc - make sure u dont burn the wrong fuses :-)

AVR Programmers

AVR Pocket Programmer Windows Driver: [1]

LadyAda USBtinyISP Windows Driver: [2]

SGMK tiny

SGMKtinyuoino v03.jpg

easy to use on breadboards with onboard connected ISP port

Pin Layout

Tinyuino5 labels.png

Mask

More Code Examples

Heartbeat PWM out

/* 
Heartbeat - Hello World
PWM LED at OC0A (PB0) - Pin 5
*/  
 
#define F_CPU 9600000UL     // Define software reference clock for delay duration 1 MHz
 
#include <avr/io.h> 
#include <util/delay.h> 
 
#define PWM0 PB0
 
int i; 
int delay;
 
void pwm_init() {   //PWM Init 
 
   TCCR0A |= (1 << COM0A1) | (1 << COM0A0);    // COM0A1 - COM0A0 (Set OC0A on Compare Match, clear OC0A at TOP) 
   TCCR0A |= (1 << WGM01) | (1 << WGM00);   // WGM01 - WGM00 (set fast PWM) 
   OCR0A   = 0;                                // initialize Output Compare Register A to 0 
 
   //TCCR0B |= (1 << CS00);                      // Start timer at Fcpu / 1
   TCCR0B |= (1 << CS01);                    // Start timer at Fcpu / 8
   //TCCR0B |= (1 << CS02) | (1 << CS00);      // Start timer at Fcpu / 1024
 
} 
 
int main(void) { 
 
//Initialization: 
 
   DDRB |= (1 << PWM0);    // OC0A on PB0
   pwm_init();
 
//Actual Program: 
   while (1) {            // loop forever 
 
    for (i=0; i<=255; i++) { 
 
     OCR0A = (i); 
     _delay_us (200);
    }
 
    for (i=254; i>=0; i--) { 
 
     OCR0A = (i); 
     _delay_us (200);
    }
 
  } 
}

2 x better Analog-in 10-bit & 2 x PWM out & threshold value

/* 
Analog sensor input at ADC3 (PB3) - Pin 2
Analog sensor input at ADC1 (PB2) - Pin 7
PWM LED at OC0A (PB0) - Pin 5
PWM LED at OC0A (PB1) - Pin 6
Digital FAN at (PB4) - Pin 3
*/  
 
#define F_CPU 9600000UL     // Define software reference clock for delay duration 1 MHz
 
#include <avr/io.h> 
#include <util/delay.h> 
 
#define ADC3 PB3
#define ADC1 PB7
#define FAN PB4
#define PWM0 PB0
#define PWM1 PB1
 
unsigned int read_adc(unsigned char channel);
 
int i; 
unsigned int sensorValue; //16bit 
unsigned int temperatureValue; //16bit
unsigned int outputVoltage;
 
void adc_init() {   //ADC init
 
   ADMUX =  0b00000011; //ADC3 (default),right,VCc
   //ADMUX =  0b00100011; //ADC3 (default),ADLAR left,VCc
   ADCSRA = 0b10000010; //prescaled by 4
}
 
void pwm_init() {   //PWM Init 
 
   TCCR0A |= (1 << COM0A1) | (1 << COM0A0);    // COM0A1 - COM0A0 (Set OC0A on Compare Match, clear OC0A at TOP) 
   TCCR0A |= (1 << COM0B1) | (1 << COM0B0);    // COM0B1 - COM0B0 (Set OC0B on Compare Match, clear OC0B at TOP) 
 
   TCCR0A |= (1 << WGM01) | (1 << WGM00);   // WGM01 - WGM00 (set fast PWM) 
 
   OCR0A   = 0;                                // initialize Output Compare Register A to 0 
   OCR0B   = 0;                                // initialize Output Compare Register B to 0 
 
   //TCCR0B |= (1 << CS00);                      // Start timer at Fcpu / 1
   TCCR0B |= (1 << CS01);                    // Start timer at Fcpu / 8
   //TCCR0B |= (1 << CS02) | (1 << CS00);      // Start timer at Fcpu / 1024
 
} 
 
int main(void) { 
 
//Initialization: 
   DDRB &= ~(1 << ADC3);  // Set direction of (PB3) to input for ADC3
   DDRB |= (1 << FAN);    // Set direction of (PB4) to output for FAN
   DDRB |= (1 << PWM0) | (1 << PWM1);    // OC0A on PB0 & P01
 
   adc_init(); 
   pwm_init();
 
//Actual Program: 
   while (1) {            // loop forever 
 
     sensorValue = read_adc(3);  
 
     OCR0A = (255-(sensorValue>>2)); 
     OCR0B = ((sensorValue>>2));  
 
     temperatureValue = read_adc(1);
 
     // map it to the range 0 to 5000 mV:
     //outputVoltage = ((sensorValue*50) / 255);  
 
     // Calculate Temperature, 10mV/°C -50°C for TMP36, check data sheet
     //temperatureValue = (2 + (outputVoltage*10));
 
     if (temperatureValue >= sensorValue) {
       PORTB = (1 << FAN);
       } 
 
     else {
       PORTB = (0 << FAN);
       }
  } 
}
 
 
unsigned int read_adc(unsigned char channel) {
 
	unsigned char k;
	unsigned int adcvalue=0;
	ADMUX = ADMUX&(0b11111100); //clear channel select bits
	ADMUX |= channel; 	
 
	//neglect first reading after changing channel
	ADCSRA |= 1<<ADSC;
	while(ADCSRA&(1<<ADSC));//Wait
	adcvalue=ADCL + (ADCH<<8);
	adcvalue=0;//neglectreading
	for(k=0;k<=7;k++)
	{
		ADCSRA |= 1<<ADSC;
		while(ADCSRA&(1<<ADSC));//Wait
		adcvalue += (ADCL + (ADCH<<8));
                _delay_ms (2);
	}
	return (adcvalue>>3); //divide by 8
 
}

Analog in & PWM out

/* 
Analog sensor input at ADC3 (PB3) - Pin 2
PWM LED at OC0A (PB0) - Pin 5
Digital FAN at (PB4) - Pin 3
*/  
 
#define F_CPU 9600000UL     // Define software reference clock for delay duration 1 MHz
 
#include <avr/io.h> 
#include <util/delay.h> 
 
#define FAN PB4
#define PWM PB0
 
int i ; 
int TEMP; 
 
void adc_init() {    //ADC Init. 
 
   ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2) | (1<<ADATE);   //Turn on ADC, with prescaler 64 
   ADCSRB= 0x00;   //Free running mode 
   ADMUX= 0x23;   //VCC Reference, Left Adjust, Channel: PB3 (ADC3) 
   DIDR0= 0x04;   //Disable Digital Input on PB3 
   ADCSRA |= (1 << ADSC); //start adc conversion
 
} 
 
void pwm_init() {   //PWM Init 
 
   DDRB |= (1 << PWM);                       // OC0A on PB0 
   TCCR0A |= ((1 << COM0A1) | (1 << COM0A0)  // COM0A1 - COM0A0 (Set OC0A on Compare Match, clear OC0A at TOP) 
       | (1 << WGM01)    | (1 << WGM00)); // WGM01 - WGM00 (set fast PWM) 
   OCR0A   = 0;                              // initialize Output Compare Register A to 0 
   TCCR0B |= (1 << CS01);                    // Start timer at Fcpu / 256 
 
} 
 
int main(void) { 
 
//Initialization: 
   adc_init(); 
   pwm_init();
   DDRB |= (1 << FAN);    // Set direction of (PB4) to output for FAN
 
//Actual Program: 
   while (1) {            // loop forever 
 
     OCR0A = (255-(ADCH)); 
     TEMP = (2 + (2*ADCH));
 
     if (TEMP >= 28) {
       PORTB = (1 << FAN);
       } 
 
     else {
       PORTB = (0 << FAN);
       }
  } 
}
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox