Created
April 21, 2013 14:21
-
-
Save ichpuchtli/5429759 to your computer and use it in GitHub Desktop.
atmega48 example code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define F_CPU 16000000UL | |
#include <avr/io.h> | |
#include "util/delay.h" | |
void init_ADC(void){ | |
// ADC voltage reference | |
// REFS1 REFS0 Description | |
// 0 0 AREF | |
// 0 1 AVcc | |
// 1 0 Reserved | |
// 1 1 Internal 1.1V | |
// When ADLAR = 1 (Left Adjusted) | |
//--------------------------------------------------------- | |
//| ADC9 | ADC8 | ADC7 | ADC6 | ADC5 | ADC4 | ADC3 | ADC2 | ADCH | |
//--------------------------------------------------------- | |
//| ADC1 | ADC0 | | | | | | | ADCL | |
//--------------------------------------------------------- | |
// ADCH:ADCL = Vin * 1024 / VREF << 6 | |
// When ADLAR = 0 | |
//--------------------------------------------------------- | |
//| | | | | | | ADC9 | ADC8 | ADCH | |
//--------------------------------------------------------- | |
//| ADC7 | ADC6 | ADC5 | ADC4 | ADC3 | ADC2 | ADC1 | ADC0 | ADCL | |
//--------------------------------------------------------- | |
// ADCH:ADCL = Vin * 1024 / VREF | |
// Aref, No left adjust suitable for 10bit accumulation | |
ADMUX = (0<<REFS1)|(0<<REFS0)|(0<<ADLAR); | |
// Select ADC Channel 0 Initially | |
ADMUX |= 0; | |
// ADC Prescaler Selections | |
// ADPS2 ADPS1 ADPS0 Division Factor | |
// 0 0 0 2 | |
// 0 0 1 2 | |
// 0 1 0 4 | |
// 0 1 1 8 | |
// 1 0 0 16 | |
// 1 0 1 32 | |
// 1 1 0 64 | |
// 1 1 1 128 | |
// Enable ADC, Enable Interrupt and 128 clk division factor | |
ADCSRA = (1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADIE)|(0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0); | |
// ADC Auto Trigger Sources | |
// ADTS2 ADTS1 ADTS0 Trigger Source | |
// 0 0 0 Free Running mode | |
// 0 0 1 Analog Comparator | |
// 0 1 0 External Interrupt Request 0 | |
// 0 1 1 Timer/Counter0 Compare Match A | |
// 1 0 0 Timer/Counter0 Overflow | |
// 1 0 1 Timer/Counter1 Compare Match B | |
// 1 1 0 Timer/Counter1 Overflow | |
// 1 1 1 Timer/Counter1 Capture Event | |
// Timer/Counter 0 prepared for 38Hz ADC polling | |
ADCSRB = (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0); | |
// Disable all ADC channels but channel 0 | |
DIDR0 = (1<<ADC5D)|(1<<ADC4D)|(1<<ADC3D)|(1<<ADC2D)|(1<<ADC1D)|(0<<ADC0D); | |
} | |
uint8_t read_ADC(uint8_t channel){ | |
// Clear MUX | |
ADMUX &= 0xF0; | |
// Enable Channel | |
ADMUX |= ( channel & 0x0F ); | |
// Start Conversion | |
ADCSRA |= (1<<ADSC); | |
// Wait for Conversion to finish | |
while(ADCSRA & (1 << ADSC)); | |
// Return ADC Value | |
return ADCH; | |
} | |
void trigger_ADC(uint8_t channel){ | |
// Clear MUX | |
ADMUX &= 0xF0; | |
// Enable Channel | |
ADMUX |= ( channel & 0x0F ); | |
// Start Conversion | |
ADCSRA |= (1<<ADSC); | |
} | |
void init_timer0(void) | |
{ | |
// Freq = F_CPU / prescaler / 255 | |
// Freq = 20000000 / 256 / 255 = 306Hz | |
// CS02 CS01 CS00 Description | |
// 0 0 0 No Clock Source (Timer/Counter stopped) | |
// 0 0 1 No Prescaling | |
// 0 1 0 clk/8 | |
// 0 1 1 clk/64 | |
// 1 0 0 clk/256 | |
// 1 0 1 clk/1024 | |
// 1 1 0 External T0 pin failing edge | |
// 1 1 1 External T0 pin rising edge | |
//OCR0A = 255; | |
// Normal Port operation | |
TCCR0A = 0x00; | |
// No prescaling | |
TCCR0B = (0<<CS02)|(0<<CS01)|(1<<CS00); | |
// Use overflow, Output Compare A interrupt | |
TIMSK0 = (0<<OCIE0B)|(1<<OCIE0A)|(1<<TOIE0); | |
} | |
void init_timer1(void){ | |
// CS12 CS11 CS10 Description | |
// 0 0 0 No Clock Source (Timer/Counter stopped) | |
// 0 0 1 No Prescaling | |
// 0 1 0 clk/8 | |
// 0 1 1 clk/64 | |
// 1 0 0 clk/256 | |
// 1 0 1 clk/1024 | |
// 1 1 0 External T1 pin failing edge | |
// 1 1 1 External T1 pin rising edge | |
// Freq = F_CPU / prescaler / OCR1A | |
OCR1AH = (unsigned char) ( ((F_CPU / 1024) >> 8) + 1 ); | |
/* Ideal */ | |
/* OCR1AL = (unsigned char) (F_CPU / 1024); */ | |
/* Actuall */ | |
OCR1AL = (unsigned char) 16; | |
// Normal Port operation | |
TCCR1A = 0x00; | |
// 1024 Prescaler & Enable CTC E.G. reset timer on OCR match | |
TCCR1B = (1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10); | |
TCCR1C = 0x00; | |
// Don't need overflow or OCRB Compare match interrupt | |
TIMSK1 = (0<<OCIE1B)|(1<<OCIE1A)|(0<<TOIE1); | |
} | |
void init_timer2(void){ | |
// Freq = F_CPU / prescaler / 2 * OCR2A | |
// OCR2A = F_CPU / prescaler / Freq / 2 | |
// CS22 CS21 CS20 Description | |
// 0 0 0 No Clock Source (Timer/Counter stopped) | |
// 0 0 1 No Prescaling | |
// 0 1 0 clk/8 | |
// 0 1 1 clk/32 | |
// 1 0 0 clk/64 | |
// 1 0 1 clk/128 | |
// 1 1 0 clk/256 | |
// 1 1 1 clk/1024 | |
// Freq = 125Hz | |
OCR2A = 250; | |
// Normal port operation and enable CTC reset timer of OCR2A match | |
TCCR2A = 0x00; | |
// 1024 prescaler, freq = F_CPU / 1024 / 256 | |
TCCR2B = (1<<CS22)|(1<<CS21)|(0<<CS20); | |
// Use OCR2A Compare match interrupt | |
TIMSK2 = (0<<OCIE2B)|(1<<OCIE2A)|(0<<TOIE2); | |
} | |
int main(void) { | |
/* TODO: Attempt to use all aspects of timer configuration */ | |
init_timer0(); | |
init_timer1(); | |
init_timer2(); | |
/* TODO: Test a range of ADC Settings look for realistic conversion speeds etc.*/ | |
init_ADC(); | |
/* TODO: frames per second loop or basic loop speed control */ | |
/* TODO: test both _delay_ms() and _delay_us() */ | |
for(;;) asm("nop"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment