Forum: Mikrocontroller und Digitale Elektronik Attiny 441 Register des Komparator 0


von Heiner (Gast)


Lesenswert?

Hallo
Da ich auf meinem Steckbrett die Ein- und Ausgänge des Komparators 0 und 
1 zuordnen konnte, bin ich jetzt beim Datenblatt. Möchte dazu den 
Komparator 0 verwenden. (Kapitel 14 des DB).
Im Register ACSR0A können die Einstellungen gemacht werden. Habe dazu 
die einzelnen Bits angeschaut.
Bit 7 - 0 = Komparator ein, 1 = Komparator aus, beim Start oder Reset 
automatisch 0
 ACSR0A = (1 << ACD0)  // AC aus
 ACSR0A = (0 << ACD0)  // AC ein
Bit 6  Auswahl ACPMUX2 // Eingang
 ACPMUX2 = (0 << ACPMUX2)
Einstellung ACSR0B
  ACPMUX1 = (0 << ACPMUX1)
  ACPMUX0 = (0 << ACPMUX0)
Damit erfolgt die Auswahl des Einganges - AIN00, PA1
Bei ACPMUX2 = (1 << ACPMUX2) erfolgt die Auswahl der internen Referenz
Bit 5 ACO0 - nur lesen, Ausgang festgelegt, PA5
Bit 1 und 0 - lesen und schreiben, definiert die Interrupt Auslösung 
nach Tabelle 14-2.

Leider ist mir die Anwendung der Bits 4, 3 und 2 dabei unklar.
Sie haben auf jeden Fall was mit Bit0 und 1 zu tun.
Doch was oder wie kann ich damit einstellen?
Habe mal meine übersetzung rangehängt, hoffe es hilft.

Bit 4 - ACI0 Analogkomparator-Interrupt-Flag: Dieses Bit wird von der 
Hardware gesetzt, wenn ein Komparator-Ausgangsereignis den durch ACIS01 
und ACIS00 definierten Interrupt-Modus triggert. Die 
Analogkomparator-Interrupt-Routine wird ausgeführt, wenn das ACIE0-Bit 
gesetzt ist und das I-Bit im SREG gesetzt ist. Dieses Bit wird von der 
Hardware gelöscht, wenn der entsprechende Interrupt-Behandlungsvektor 
ausgeführt wird. Alternativ wird das Bit gelöscht, indem eine logische 
Eins in das Flag geschrieben wird.

Bit 3 - ACIE0: Analog Comparator Interrupt Enable: Wenn dieses Bit 
gesetzt ist und das I-Bit im Statusregister gesetzt ist, wird der 
Analogkomparator-Interrupt aktiviert. Wenn dieses Bit gelöscht wird, ist 
der Interrupt deaktiviert.

Bit 2 - ACIC0: Analog Comparator Input Capture Enable: Wenn dieses Bit 
gesetzt ist, kann die Input Capture-Funktion von Timer/Counter1 durch 
den Analogkomparator ausgelöst werden. Der Komparatorausgang (ACO0) ist 
dann direkt mit der Eingangs-Capture-Frontend-Logik verbunden, so dass 
der Komparator die Rauschunterdrückungs- und Flankenauswahlfunktionen 
des Timer /Counter1-Eingangs-Capture-Interrupts nutzt. Damit der 
Komparator den Timer/Counter1-Input-Capture-Interrupt auslöst, muss das 
ICIEn-Bit gesetzt werden (siehe "TIMSKn – Timer /Counter Interrupt Mask 
Register" auf Seite 118); wenn dieses Bit gelöscht ist, besteht keine 
Verbindung zwischen dem Analogkomparator und der Input-Capture-Funktion.

LG Heiner

von Georg M. (g_m)


Lesenswert?

Heiner schrieb:
>   ACPMUX1 = (0 << ACPMUX1)
>   ACPMUX0 = (0 << ACPMUX0)

Ne-ne, so nicht.

1
 x |= (1 << Bitnummer);  // Hiermit wird ein Bit in x gesetzt
2
 x &= ~(1 << Bitnummer); // Hiermit wird ein Bit in x geloescht
https://de.wikibooks.org/wiki/C-Programmierung_mit_AVR-GCC/_Register

von Heiner (Gast)


Lesenswert?

Danke für deine Info

von Heiner (Gast)


Lesenswert?

Es geht dabei um diese:

ACI0
ACIE0
ACIC0

Kann mir jemand nähere Angaben dazu machen?

von Georg M. (g_m)


Lesenswert?

Heiner schrieb:
> Es geht dabei um diese:
>
> ACI0
> ACIE0
> ACIC0

Input Capture ist nur im Zusammenspiel mit dem Counter von Bedeutung.
Siehe dazu Figure 12-3. Input Capture Unit Block Diagram

Interrupt, Interrupt Enable, Interrupt-Flag sind allgemeine Begriffe der 
Mikrocontrollerprogrammierung, auch ohne Analogkomparator. Diese 
Kenntnisse muss man sich zuerst aneignen.

von c-hater (Gast)


Lesenswert?

Heiner schrieb:
> Es geht dabei um diese:
>
> ACI0
> ACIE0
> ACIC0
>
> Kann mir jemand nähere Angaben dazu machen?

Was willst du denn noch darüber wissen? Du hast doch schon eine gute 
Übersetzung des Originaltextes. Da steht eigentlich alles drin, was man 
über diese Bits wissen muss.

ACI0 und ACIE0, also Interrupt-Flag und Interrupt-Enable funktionieren 
so, wie bei unzähligen anderen Peripheriekomponenten auch. Du wirst doch 
schonmal einen Timer-Interrupt benutzt haben. Da ist das Prinzip ganz 
genau dasselbe.

Und was ACIC0 betrifft, das erspart einfach nur eine äußere physische 
Verbindung zwischen dem Ausgang des AC und dem InputCapture-Eingang 
eines Timers. Stell' dir einfach vor, du würdest mit dem Setzen dieses 
Bits genau dieses Stück Draht in dein Breakboard stecken.

Der Vorteil dieses Bits ist, dass man mit seiner Verwendung gleich zwei 
physische Pins für andere Zwecke frei machen kann, weil halt nicht mehr 
der Draht dort dran geklöppelt werden muss.

Oder andersrum: man kann das Bit nutzen, um die Input-Capture-Funktion 
eines Timers (abwechselnd) für zwei verschiedene Quellen benutzen, das 
Bit kann also als eine Art Multiplexer benutzt werden. Das ist 
insbesondere dann nützlich, wenn man nur einen Timer mit 
Input-Capture-Funktion zur Verfügung hat, aber zwei Quellen messen muss.

von Heiner (Gast)


Lesenswert?

Danke für eure Info

von Heiner (Gast)


Lesenswert?

Hallo
Habe die ersten Anweisungen für AC0 geschrieben.
1
void init_AC0()
2
  {
3
  ACSR0A &= ~(1<<ACD0);        // AC0 Analog Komparator einschalten, ACD auf 0
4
  ACSR0A &= ~(1 << ACPMUX2);      // ACPMUX2 auf 0 auf AIN00
5
  // ACSR0A |= (1 << ACPMUX2);    // Interne Reference voltage -> AIN00 ACPMUX auf 1
6
  ACSR0B &= ~((1<<ACPMUX1)|(ACPMUX0));// Verbindung zu AIN00 zu Pin PA1
7
  ACSR0B |=((1<<HSEL0)|(1<<HLEV0));  // Hysterese und 50mV einschalten im Register B  
8
  ACSR0B &= ~((1<<ACNMUX1)|(ACNMUX0));// Verbindung zu AIN01 zu Pin PA2
9
  ACSR0B |= (1<<ACOE1);        // Bit gesetzt für Ausgang auf PA5 im Register B
10
  }
Stimmt das so oder wieder was vergessen oder zuviel?

von Georg M. (g_m)


Lesenswert?

Heiner schrieb:
> oder wieder was vergessen

Ja: "1<<"


Heiner schrieb:
> oder zuviel?

Je nachdem.
Wenn nach dem Einschalten nichts geändert wurde, dann stehen vielleicht 
schon passende Werte in den Registern - "Initial Value".

von Heiner (Gast)


Lesenswert?

Danke für die Info. Ein Glück das du es gefunden hast.

von Heiner (Gast)


Lesenswert?

Das korregierte komplette Programm:
1
#define F_CPU 16000000UL    // Angabe der Quarzfrequenz, wichtig für die Zeit
2
#include <util/delay.h>      // Einbindung Datei Pause
3
#include <avr/io.h>        // Einbindung Datei Ausgänge
4
5
void init_AC0()
6
  {
7
  ACSR0A &= ~(1<<ACD0);          // AC0 Analog Komparator einschalten, ACD auf 0
8
  ACSR0A &= ~(1<<ACPMUX2);        // ACPMUX2 auf 0 auf AIN00
9
  // ACSR0A |= (1<<ACPMUX2);        // Interne Reference voltage -> AIN00 ACPMUX auf 1
10
  ACSR0B &= ~((1<<ACPMUX1)|(1<<ACPMUX0));  // Verbindung zu AIN00 zu Pin PA1
11
  ACSR0B |= ((1<<HSEL0)|(1<<HLEV0));    // Hysterese und 50mV einschalten im Register B  
12
  ACSR0B &= ~((1<<ACNMUX1)|(1<<ACNMUX0));  // Verbindung zu AIN01 zu Pin PA2
13
  ACSR0B |= (1<<ACOE1);          // Bit gesetzt für Ausgang auf PA5 im Register B
14
  }
15
16
int main(void)
17
  {
18
  init_AC0();
19
  while(1)          
20
    {
21
    if (ACSR0A & (1<<ACO0))    
22
      {
23
      PORTA &=~(1<<PINA5);        // LED schaltet
24
      }
25
    else
26
      {
27
      PORTA |=(1<<PINA5);          // LED schaltet
28
      }  
29
    }
30
  }
Da das erste Programm funktioniert kommen wir zum nächsten.
Wie kann ich am besten einen Interrupt auslösen?
Welches Bit ist am besten dazu um bei jeder Umschaltung z:B. eine LED 
anzuschalten?
LG Heiner

von Heiner (Gast)


Lesenswert?

Nach dem Datenblatt und der übersetzung hab ich das folgende gefunden:

Bit 3 ACIE0 Analog Comparator Interrupt Enable: Ist das Bit auf 1 
gesetzt, wird immer ein Interrupt ausgelöst, wenn das Ereignis das in 
Bit 1 und 0 definiert ist, eintritt.

Bits 1:0 - ACIS0[1:0]: Analog Comparator Interrupt Mode Select: Diese 
Bits bestimmen, welche Komparatorereignisse den 
Analogkomparator-Interrupt auslösen. Die verschiedenen Einstellungen 
sind in Tabelle 14-2 dargestellt.

In der Tabelle 14-2 steht das:

00 - Interrupt auslösen bei jedem Flankenwechsel
01 – Reserve
10 - Interrupt auslösen bei fallender Flanke
11 - Interrupt auslösen bei steigender Flanke

- Bit 3 ACIE0 einschalten - steht nach Reset oder Start auf 0
- Bit 1 und 0 kann ich den gewünschten Interrupt auswählen

Wie kann ich den Interrupt am besten nutzen um z.B. eine LED zu toggeln?

von c-hater (Gast)


Lesenswert?

Heiner schrieb:

> 00 - Interrupt auslösen bei jedem Flankenwechsel
> 01 – Reserve
> 10 - Interrupt auslösen bei fallender Flanke
> 11 - Interrupt auslösen bei steigender Flanke
>
> - Bit 3 ACIE0 einschalten - steht nach Reset oder Start auf 0
> - Bit 1 und 0 kann ich den gewünschten Interrupt auswählen
>
> Wie kann ich den Interrupt am besten nutzen um z.B. eine LED zu toggeln?

Das kannst nur du wissen. Das hängt nämlich einzig davon ab, wann genau 
die LED toggeln soll und das legst du fest.
Wenn sie (in etwa) dem Eingangssignal folgen soll, dann musst du 
natürlich das wählen:

> 00 - Interrupt auslösen bei jedem Flankenwechsel

von Heiner (Gast)


Lesenswert?

Das stimmt genau. Möchte als erstes bei steigender Flanke einen 
Interrupt auslösen. Damit muss die Einstellung sein:
1
ACSR0A |= (1<<ACIE0);  // Interrupt einschalten  
2
ACSR0A |= (1<<ACIS01);  // Interrupt Auslösung
3
ACSR0A |= (1<<ACIS00);  // bei steigender Flanke
bei jedem Wechsel
1
ACSR0A &= ~(1<<ACIS01);  // Interrupt Auslösung
2
ACSR0A &= ~(1<<ACIS00);  // bei jedem Wechsel
Welchen Interrupt muss ich verwenden?

von Heiner (Gast)


Lesenswert?

Nach dem Datenblatt Tabelle 9-1

Nr 13   ana_comp0-vect

stimmt das?

von Heiner (Gast)


Lesenswert?

Heiner schrieb:
> Nr 13   ana_comp0-vect

Muss natürlich ANA_COMP0_vect sein

von c-hater (Gast)


Lesenswert?

Heiner schrieb:
> Nach dem Datenblatt Tabelle 9-1
>
> Nr 13   ana_comp0-vect
>
> stimmt das?

Keine Ahnung. Du musst wissen, dass das Datenblatt hier nur Vorschläge 
macht. Ob die Hersteller der Compiler sich daran halten oder nicht, 
liegt in deren Ermessen.

Recht sicher sein kannst du nur in Assembler, wenn du das Include des 
richtigen Device benutzt. Dann wird der Assembler bei einer 
.org-Direktive mit dem entsprechenden symbolischen Vektornamen auch 
zielsicher den Code dorthin legen, wo er hingehört.

Allerdings muss man dazu erstmal wissen, wie er heißt. In Assembler ist 
das halt einfach zu erfahren, weil man hier NUR mit der einen 
Include-Datei hantiert. Da muss man einfach nur in diese eine rein 
schauen.

In C kann das hingegen beliebig kompliziert werden. Je nachdem, welcher 
Compiler und wie viele idiotische Abstraktionsschichten du über den 
simplen Sachverhalt gestapelt hast...

Da hilft nur: Beherrschung des selbst gewählten Werkzeugs. Das ist 
beherrschbar, aber es macht halt Arbeit, es zu beherrschen.

von Georg M. (g_m)


Lesenswert?

Heiner schrieb:
> Muss natürlich ANA_COMP0_vect sein

Ja, z.B.:
1
ISR(ANA_COMP0_vect)
2
{
3
  PORTB ^= (1 << PORTB2);  // toggle PB2
4
}

Global Interrupt Enable ist dabei auch erforderlich.

von Heiner (Gast)


Lesenswert?

Wenn ich das richtig verstanden habe muss es so aussehen:
1
ACSR0A |= (1<<ACIE0);  // Interrupt einschalten
2
  //ACSR0A |= (1<<ACIS01);  // Interrupt Auslösung
3
  //ACSR0A |= (1<<ACIS00);  // bei steigender Flanke
4
  ACSR0A &= ~(1<<ACIS01);  // Interrupt Auslösung
5
  ACSR0A &= ~(1<<ACIS00);  // bei jedem Wechsel
6
7
ISR (ANA_COMP0_vect)
8
  {
9
  PORTA ^=(1<<PINA0);
10
  }
11
12
  init_AC0();
13
  sei();
Damit geht es.

von Heiner (Gast)


Lesenswert?

Für die Funktion des Komparators beim Attiny 841 verwende ich bis jetzt 
die Register:
-ACSR0A
-ACSR0B
Werden noch weitere Einstellung bzw. Register benötigt?

von Georg M. (g_m)


Lesenswert?

Heiner schrieb:
> Werden noch weitere Einstellung bzw. Register benötigt?

Nur was im Datenblatt steht.
Der Komparator ist nun mal einer der einfachsten Bestandteile des 
Mikrocontrollers. Da gibt es nicht viele Konfigurationseinstellungen.

von Heiner (Gast)


Lesenswert?

Hallo
Der Komparator ist einfach, gebe ich sofort zu.
Wie nährt man sich am besten dem Innenleben des Attiny 841?
Welche Reihenfolge soll man nehmen oder was ist am besten nach dem 
Komparator machen?
LG Heiner

von Heiner (Gast)


Lesenswert?

Jemand eine Idee was man als nächstes machen sollte?

von c-hater (Gast)


Lesenswert?

Heiner schrieb:

> Wie nährt man sich am besten dem Innenleben des Attiny 841?

Der Tiny441/841 hat gegenüber den ganzen "klassischen" Tinys und Megas 
eigentlich nur zwei wirkliche Besonderheiten, der Rest ist praktisch der 
übliche Standardkram, den es mit leichten Variationen in unzähligen 
anderen AVR8 auch gibt.

Die zwei wirklichen Besonderheiten sind:

1) Port-Mapping
Das war nötig, weil das Ding so viel an klassischer AVR8-Peripherie 
beinhaltet, dass es vollkommen unmöglich wurde, alles über je einen 
dedizierten Pin herauszuführen.
Ein wesentliche Herausforderung zum erfolgreichen Einsatz eines 
Tiny441/841 ist also, erstmal herauszufinden, was von der vielen 
vorhandenen Peripherie eigentlich gleichzeitig eingesetzt werden kann 
und wie man die Kiste halt so hinbiegt, dass das möglich wird.

2) TWI-Slave
Das ist ein völlig ungewöhnlicher Geselle im AVR8-Universum, den gibt's 
nur hier. Nennenswerte Vorteile gegenüber dem sonst bei Tinys für diesen 
Zweck benutzten USI bringt er de facto leider nicht.
Man muss sich trotzdem damit auseinandersetzen, weil ausgerechnet das 
lächerliche USI beim Tiny441/841 komplett eingespart wurde...

von Heiner (Gast)


Lesenswert?

Danke für deine Antwort.
c-hater schrieb:
> 1) Port-Mapping
> Das war nötig, weil das Ding so viel an klassischer AVR8-Peripherie
> beinhaltet, dass es vollkommen unmöglich wurde, alles über je einen
> dedizierten Pin herauszuführen.
Damit hast du vollkommen recht. Viele Pins haben eine mehrfach Belegung. 
Die klassische Version ist ja den Pin ein- auszuschalten.
Hatte mir auch schon den ADC angesehen. Ist aber noch eine ganz andere 
Nummer für mich. Ansonsten habe ich für mich so einen kleinen Plan 
gemacht.
- Timer
- ADC
- Tasterentprellung
- Encoder
- Joystick
und als letztes noch den I2C Bus.
Da der Attiny841 was besonderes ist, ist der I2C Bus wohl auch was 
besonderes. Mal sehen wie das funktioniert.
Vielleicht fällt dir noch was besseres ein.
Mit USI konnte ich mich bisher garnicht anfreuden.
LG Heiner

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.