Skip to content

Instantly share code, notes, and snippets.

@ichpuchtli
Created April 21, 2013 14:21
Show Gist options
  • Save ichpuchtli/5429759 to your computer and use it in GitHub Desktop.
Save ichpuchtli/5429759 to your computer and use it in GitHub Desktop.
atmega48 example code
#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