Skip to content

Instantly share code, notes, and snippets.

@vindolin
Created April 28, 2015 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vindolin/7a08116ce926a596e6e0 to your computer and use it in GitHub Desktop.
Save vindolin/7a08116ce926a596e6e0 to your computer and use it in GitHub Desktop.
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/power.h>
const uint8_t MINPWM = 1;
const uint8_t MAXPWM = 255;
const uint8_t STEP = 1;
enum { UP, DOWN };
uint16_t ReadChannel(uint8_t mux) {
uint8_t i;
uint16_t result;
ADMUX = mux; // ADCn Kanal waehlen
ADMUX &= ~_BV(REFS1) | ~_BV(REFS0); // VCC als Referenzspannung
//ADMUX |= _BV(REFS1) | _BV(REFS0); // interne Referenzspannung nutzen
ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0); // Frequenzvorteiler setzen auf 8 (1) und ADC aktivieren (1)
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
ADCSRA |= _BV(ADSC); // eine ADC-Wandlung
while ( ADCSRA & _BV(ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
result = 0;
for(i=0; i<4; i++ ) {
ADCSRA |= _BV(ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & _BV(ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
result /= 4; // Summe durch vier teilen = arithm. Mittelwert
ADCSRA &= ~_BV(ADEN); // ADC deaktivieren (2)
return result;
}
uint16_t ReadTemp(void) {
uint8_t i;
uint16_t result;
ADMUX = 4; // ADCn Kanal waehlen
// ADC Voltage reference selection, internal 1.1v
ADMUX &= ~_BV(REFS0); //0
ADMUX |= _BV(REFS1); //1
ADMUX &= ~_BV(REFS2); //0
// Disable digital input of pin PB4 (ADC channel2)
DIDR0 |= _BV(ADC2D);
// Turn ADC on
ADCSRA |= _BV(ADEN);
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
ADCSRA |= _BV(ADSC); // eine ADC-Wandlung
while ( ADCSRA & _BV(ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
result = 0;
for(i=0; i<4; i++ ) {
ADCSRA |= _BV(ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & _BV(ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
result /= 4; // Summe durch vier teilen = arithm. Mittelwert
ADCSRA &= ~_BV(ADEN); // ADC deaktivieren (2)
return result;
}
ISR ( TIM0_OVF_vect ) {
static uint8_t direction = UP;
static uint8_t pwm = MINPWM;
if(direction == UP && pwm + STEP < MAXPWM) {
pwm+=STEP;
} else if(direction == DOWN && pwm - STEP > MINPWM) {
pwm-=STEP;
} else {
direction = !direction;
return;
}
// OCR0A = pwm;
OCR0B = ReadTemp() / 4;
}
void ioinit(void) {
// be green :)
if(1) {
power_timer1_disable();
power_usi_disable();
}
DDRB = _BV(PB0) | _BV(PB1) | _BV(PB2); // pins as output
PORTB |= _BV(PB2);
OCR0A = 0; // start value for PWM
OCR0B = 0; // start value for PWM
// WGM00,WGM01,WGM02 = mode 7, Fast PWM
// COM0B0, COM0B1 = set OC0A/OC0B on compare match
TCCR0A |= _BV(WGM00) | _BV(WGM01) | _BV(COM0A1) | _BV(COM0A0) | _BV(COM0B1) | _BV(COM0B0);
TCCR0B |= _BV(CS00) | _BV(CS01); // CLK/64 prescaler
TIMSK = _BV(TOIE0); // overflow interrupt
sei(); // enable interrupts
}
int main(void) {
ioinit();
for(;;) {
// PORTB ^= _BV(PB2); // toggle pin PB2
_delay_ms(1000);
sleep_mode();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment