Tipps und Tricks

Diese Seite ist lediglich eine Sammlung von Befehlen, Codeschnipseln sowie Bauteilen bzw. Schaltungen, die ich häufiger verwende. Eine weitaus umfangreiche Sammlung gibt es zum Beispiel auf mikrocontroller.net.



AVR Controllertypen

Typ Flash EEPROM SRAM Anzahl I/O maximale Taktfrequenz
AT90S2323 2 kB 128 B 128 B 3 10 MHz
AT90S2343 2 kB 128 B 128 B 5 10 MHz
ATtiny26 2 kB 128 B 128 B 15 16 MHz
ATmega8 8 kB 512 B 1 kB 22 16 MHz
ATmega16 16 kB 512 B 1 kB 32 16 MHz


1-Wire Temperatursensoren

Typ Temperaturbereich Genauigkeit Auflösung
DS1820 -55°C bis +125°C ±0.5°C 9 Bit
DS18S20 -55°C bis +125°C ±0.5°C 9 Bit
DS18B20 -55°C bis +125°C ±0.5°C 9/12 Bit
DS1822 -55°C bis +125°C ±2.0°C 9/12 Bit

APPLICATION NOTE 4377 - Comparison of the DS18B20 and DS18S20 1-Wire Digital Thermometers


Standard-Transistoren

Typ Umax Imax NPN/PNP
BC 548 30 V 100 mA NPN
BC 337-25 45 V 800 mA NPN
BC 327-25 45 V 800 mA PNP


Standard-MOSFETs (N-Channel)

Typ Umax Imax Rds(on) Vgs(max) Vgs(th)
BUZ11 50 V 30 A 40 mΩ ±20 V ∼3 V
IRF540N 100 V 33 A 44 mΩ ±20 V ∼3 V


Transistor als Schalter


IO-Ports konfigurieren

DDRx = Datenrichtungsregister für Portx.
PORTx = Datenregister für Portx.

DDRx=0 DDRx=1
PORTx=0 Eingang Ausgang Low
PORTx=1 Eingang (Pull-Up) Ausgang High
// PB7,PB6,PB5,PB4=Ausgang(Low), PB3,PB2,PB1,PB0=Eingang(Pull-Up)
DDRB = 0xF0; // 1111 0000
PORTB= 0x0F; // 0000 1111


Digitale Eingänge

Prüfen ob Pin7 an PortB auf HIGH gesetzt ist:

if ( PINB & (1<<PB7) ) {
    // do something
}

Prüfen ob Pin7 an PortB auf LOW gesetzt ist:

if ( !(PINB & (1<<PB7)) ) {
    // do something
}

Warten bis Pin7 an PortB auf HIGH gesetzt wurde:

 while ( !(PINB & (1<<PB7)) ); // busy waiting 

Warten bis Pin7 an PortB auf LOW gesetzt wurde:

 while ( PINB & (1<<PB7) ); // busy waiting 


Digitale Ausgänge

Pin4 und Pin5 an PortB auf HIGH setzen:

 PORTB |= (1<<PB4) | (1<<PB5); 

Pin4 und Pin5 an PortB auf LOW setzen:

 PORTB &= ~((1<<PB4) | (1<<PB5)); 

Pin4 an PortB invertieren:

 PORTB ^= (1<<PB4); 


Timer Interrupt

In diesem Beispiel wird der Timer0 des Mikrocontrollers dazu benutzt, um jede Millisekunde einen Interrupt auszulösen. Beim Timer0 handelt es sich um einen 8-bit Timer, der immer genau dann einen Interrupt auslöst, wenn das 8-bit Zählregister (TCNT0) überläuft. Würde man das Zählregister des Timers synchron zum Prozessortakt (in diesem Fall 8 MHz) hochzählen, dann würde alle 32 µS ein Interrupt ausgelöst werden. Um diese Rate zu verringern gibt es den sogenannten "Prescaler", mit dem man den Prozessortakt um einen bestimmten Faktor teilen kann. Stellt man den Prescaler beispielsweise auf 8, so wird Zählregister des Timers nur bei jedem achten Impuls vom Prozessortakt um 1 erhöht.

Mögliche Werte für den Prescaler von Timer0:

CS02 CS01 CS00
0 0 0 STOP (Timer stopped)
0 0 1 CLK/0 (No prescaling)
0 1 0 CLK/8 (From prescaler)
0 1 1 CLK/64 (From prescaler)
1 0 0 CLK/256 (From prescaler)
1 0 1 CLK/1024 (From prescaler)
Taktfrequenz CLK / 0 CLK / 8 CLK / 64 CLK / 256 CLK / 1024
1 MHz 1000000.00 125000.00 15625.00 3906.25 976.56
Overflows/Sek 3906.25 488.28 61.04 15.26 3.81
2 MHz 2000000.00 250000.00 31250.00 7812.50 1953.13
Overflows/Sek 7812.50 976.56 122.07 30.52 7.63
4 MHz 4000000.00 500000.00 62500.00 15625.00 3906.25
Overflows/Sek 15625.00 1953.13 244.14 61.04 15.26
8 MHz 8000000.00 1000000.00 125000.00 31250.00 7812.50
Overflows/Sek 31250.00 3906.25 488.28 122.07 30.52
10 MHz 10000000.00 1250000.00 156250.00 39062.50 9765.63
Overflows/Sek 39062.50 4882.81 610.35 152.59 38.15
16 MHz 16000000.00 2000000.00 250000.00 62500.00 15625.00
Overflows/Sek 62500.00 7812.50 976.56 244.14 61.04

Für den Timer Interrupt muss also zunächst ein passender Prescaler festgelegt werden. In diesem Beispiel soll jede Millisekunde ein Interrupt ausgelöst werden, was einer Frequenz von 1000 Hz entspricht. Die Anzahl der notwendigen Inkrementierungen, um einen Timer Overflow Interrupt auszulösen muss kleiner oder gleich dem höchsten Wert des Zählregister sein.

Bei einem Prozessortakt von 8 MHz ergeben sich folgende Werte für die Anzahl der notwendigen Inkrementierungen:

Prescaler Timer-Takt Timer-Takt / 1000 Hz (1 ms) Bemerkung
CLK/0 8.000.000,0 Hz 8.000 nicht geeignet, da > 256
CLK/8 1.000.000,0 Hz 1.000 nicht geeignet, da > 256
CLK/64 125.000,0 Hz 125 geeigneter Wert für den Prescaler
CLK/256 31.250,0 Hz 31,25 nicht geeignet, da nicht ganzzahlig
CLK/1024 7.812,5 Hz 7,8125 nicht geeignet, da nicht ganzzahlig

Anhand der Tabelle ist ersichtlich, dass in dem Fall nur ein Prescaler von 64 geeignet ist. Damit der Timer Overflow Interrupt nach genau einer Millisekunde ausgelöst wird, muss das Zählregister in diesem Fall noch mit dem Wert 131 (256-125) vorgeladen werden.

#include <avr/interrupt.h>
 
volatile uint32_t millis = 0;
 
ISR (TIMER0_OVF0_vect) {
    millis++;
    TCNT0 = 131;
}
 
int main (void) {
 
    TIMSK |= (1<<TOIE0);            // enable Timer 0 Overflow Interrupt
    TCCR0 |= (1<<CS01) | (1<<CS00); // set prescaler to 64
    TCNT0 = 131;                    // set preload value
 
    sei(); // enable interrupts
 
    while(1) {
        // do something
    }
 
    return 0;
}

Weiterführende Links zum Thema Timer:
heise Developer: Timer, Counter und Interrupts
Prescaler - Berechnung für AVR - Timer


PWM (Pulse Width Modulation)

In diesem Beispiel wird der Timer1 des Mikrocontrollers dazu benutzt, um ein PWM-Signal mit variablem Tastverhältnis zu erzeugen. Die resultierende PWM-Frequenz ist abhängig vom Prozessortakt, dem Prescaler und der Auflösung der PWM. Der Prescaler für den Timer sollte dabei so hoch wie möglich gewählt werden, um die Prozessorlast durch die Interrupt-Routine (Timer Overflow) so gering wie möglich zu halten.

Die Formel zur Berechnung der PWM-Frequenz lautet:

PWM-Frequenz = Prozessortakt / Prescaler / Schritte bis Timer-Overflow / PWM-Schritte

Prozessortakt Prescaler Auflösung/Schritte PWM-Frequenz
8.000.000 Hz 1 0-255 (8-bit) 122.07 Hz
8.000.000 Hz 1 0-127 (7-bit) 244.14 Hz
8.000.000 Hz 1 0-63 (6-bit) 488.28 Hz
8.000.000 Hz 1 0-31 (5-bit) 976.56 Hz
8.000.000 Hz 2 0-255 (8-bit) 61.03 Hz
8.000.000 Hz 2 0-127 (7-bit) 122.07 Hz
8.000.000 Hz 2 0-63 (6-bit) 244.14 Hz
8.000.000 Hz 2 0-31 (5-bit) 488.28 Hz
8.000.000 Hz 4 0-255 (8-bit) 30.51 Hz
8.000.000 Hz 4 0-127 (7-bit) 61.03 Hz
8.000.000 Hz 4 0-63 (6-bit) 122.07 Hz
8.000.000 Hz 4 0-31 (5-bit) 244.14 Hz
#include <avr/interrupt.h>
 
#define PWM_MAX 100
volatile uint8_t pwmCounter = 0;
uint8_t pwmValue = 0;
 
ISR (TIMER1_OVF1_vect) {
    if (++pwmCounter > PWM_MAX) {
        pwmCounter = 0;
    }
    if ( (pwmCounter == 0) && (pwmValue > 0) ) {
        // set output high
    } else if ( (pwmCounter == pwmValue) && (pwmValue < PWM_MAX) ) {
        // set output low
    }
}
 
int main (void) {
 
    TIMSK |= (1<<TOIE1); // enable Timer 1 Overflow Interrupt
    TCCR1B |= (1<<CS10); // set prescaler to 1
 
    sei(); // enable interrupts
 
    while(1) {
        // do something (e.g. set pwmValue)
    }
 
    return 0;
}
  • Last modified: 2018/04/10 19:58