Forum: Mikrocontroller und Digitale Elektronik Avr Xmega-A1 Explained


von Peter Parker (Gast)


Lesenswert?

Habe einen AVR XMEGA-A1 Xplained von Atmel vor mir liegen.

Ich programmiere in C auf meinem Linux System und flashe meinen Code 
mittels der PDI Schnittstelle und avrdude auf den xmega.

Ich habe innerhalb meines Codes das USART so konfiguriert, dass der 
xmega über usb die serielle Schnittstelle emuliert, so dass ich mit 
putty/plink eine "Debug Ausgabe" in meinem Terminal auf Linux haben 
kann:
1
plink -sercfg 9600,8,n,1 -serial /dev/ttyACM0

Der C Code den ich hier zeige schaltet durch die LEDS und druckt den 
aktuellen Wert der LED-Bits im Terminal aus:
1
#include <stdio.h>
2
#include "lib/usart_driver.c"
3
4
// Forward Declarations
5
void setup(void);
6
void loop(void);
7
8
#define USART USARTC0
9
10
static int uart_putchar (char c, FILE *stream)
11
{
12
    if (c == '\n')
13
    uart_putchar('\r', stream);
14
15
    // Wait for the transmit buffer to be empty
16
    while (  !(USARTC0_STATUS & USART_DREIF_bm) );
17
18
    // Put our character into the transmit buffer
19
    USARTC0_DATA = c;
20
21
    return 0;
22
}
23
FILE usart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
24
25
26
void setupLeds() {
27
  // Set whole PORTE to output
28
  PORTE.DIRSET = 0xff;
29
30
  // Per default all LEDs are active low, so set all LEDs to active high
31
  PORTE.PIN0CTRL = PORT_INVEN_bm;
32
  PORTE.PIN1CTRL = PORT_INVEN_bm;
33
  PORTE.PIN2CTRL = PORT_INVEN_bm;
34
  PORTE.PIN3CTRL = PORT_INVEN_bm;
35
  PORTE.PIN4CTRL = PORT_INVEN_bm;
36
  PORTE.PIN5CTRL = PORT_INVEN_bm;
37
  PORTE.PIN6CTRL = PORT_INVEN_bm;
38
  PORTE.PIN7CTRL = PORT_INVEN_bm;
39
}
40
41
void setUpSerial() {
42
  // These pins are connected to USARTC0
43
  // Set PINC3 (TXD0) as output
44
  PORTC.DIRSET = PIN3_bm;
45
46
  // Set PINC2 (RXD0) as input
47
  PORTC.DIRCLR = PIN2_bm;
48
49
  // USARTC0, 8 Data bits, No Parity, 1 Stop bit
50
  USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
51
52
  /* Set Baudrate to 9600 bps:
53
   * Use the default I/O clock frequency that is 2 MHz.
54
   * Do not use the baudrate scale factor
55
   *
56
   * Baudrate select = (1 / (16 * (((I/O clock frequency) / Baudrate) - 1) = 12
57
   */
58
  USART_Baudrate_Set(&USART, 12 , 0);
59
60
  // Open both RX and TX
61
  USART_Rx_Enable(&USART);
62
  USART_Tx_Enable(&USART);
63
64
  // enable debug logging to console with printf()
65
  stdout = stdin = &usart_str;
66
}
67
68
int main(void) {
69
  setupLeds();
70
  setUpSerial();
71
72
  while(1){
73
74
    uint8_t ledPattern = 0b11111111;
75
    PORTE.OUT = ledPattern;
76
    _delay_ms(150);
77
78
    int a;
79
    for(a = 0; a <= 7; a = a + 1){
80
      ledPattern ^= 1 << a;
81
      PORTE.OUT = ledPattern;
82
      printf("set led pattern to: %u\n",ledPattern);
83
      _delay_ms(150);
84
    }
85
  }
86
87
  USART_Rx_Disable(&USART);
88
  USART_Tx_Disable(&USART);
89
}

Den Code habe ich aus diesen Quellen zusammengebastelt und teilweise von 
einem Kollegen übernommen:

- https://morf.lv/guide-to-xmega-usart-aka-serial-communication
- 
http://www.jtronics.de/avr-projekte/xmega-tutorial/xmega-tutorial-usart.html

Nun zu meinen Fragen:

Als nächstes möchte ich mit dem integrierten Lautsprecher des Xmega 
experimentieren. Leider habe ich nichts brauchbares für mich im 
Datenblatt ( http://www.atmel.com/images/doc8077.pdf ) gefunden.

1.) Kann mir eine Code Beispiele geben, die Sounds aus den integrierten 
Lautsprecher erzeugen? (Zum Beispiel: generiere ein einfaches Piepen.)

2.) Kann mir einer im Datenblatt zeigen, wo entsprechende Infos sind?

3.) Danach wollte ich mit dem Lichtsensor experimentieren. Wo finde ich 
Code Beispiele die dieses machen? (Zum Beispiel: lies den aktuellen 
Lichtwert in eine Variable und drucke es in das Terminal. Den Teil mit 
drucke es in das Terminal aus habe ich ja schon, nur kann ich im 
Datenblatt nicht rauslesen, wie man den Lichtsensor abfragen kann.)


Vielen Dank für das Lesen und eine Antwort.

von myasuro (Gast)


Lesenswert?

Hmm, löse ich deine Hausaufgabe:


















Nein!!
Gebe ich tipps:














Ja:
Suche dir erst mal raus wie du den Sensor anschließen willst.
Hier sind die Stichworte:
AD-Wandler
SPI
I2C
UART

Viel Spaß

Mit freundlichen Gruß
Kerler Marian

von Peter Parker (Gast)


Lesenswert?

Hallo,

Ähm, bitte lies doch mal den ganzen Artikel durch. Der Sensor ist schon 
auf dem Board verbaut. Hättest du dir mal das Board angeguckt. Google 
und so.


Es ist keine Hausaufgabe.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter Parker schrieb:
> 2.) Kann mir einer im Datenblatt zeigen, wo entsprechende Infos sind?

Du brauchst in diesem Fall das Schaltbild des Boards.
Wenn du dir das anschaust, siehst du, das der Lichtsensor an Port PB1 
angeschlossen ist, der Temperaturfühler sitzt an PB0 und wird über Port 
PB3 angeschaltet.
Du solltest jetzt also den AD Wandler B aktivieren (wieder mit Hilfe des 
Datenblattes) und dann den Kanal B1 auswählen, um den Lichtsensor 
abzufragen. Das Resultat der AD Wandlung sendest du z.B. wieder an die 
serielle.

> 1.) Kann mir eine Code Beispiele geben, die Sounds aus den integrierten
> Lautsprecher erzeugen? (Zum Beispiel: generiere ein einfaches Piepen.)
Der Lautsprecher hängt am DACB0 (Pin B2) und wird also mit dem DA 
Wandler B angesprochen. Dazu schickst du ihm Wellenformen, die mit z.B. 
einem Timer getriggert werden. Denke dran, vor Benutzung des 
Lautsprechers die Endstufe über Port PQ3 (Audio Shutdown) anzuschalten. 
An ist Pin low.

: Bearbeitet durch User
von Peter Parker (Gast)


Lesenswert?

Matthias S. schrieb:
> Du brauchst in diesem Fall das Schaltbild des Boards.

OK habe nun das "datasheet" geöffnet ( Seite 3/4 und 6 , 
http://www.atmel.com/images/atmel-8067-8-and-16-bit-avr-microcontrollers-atxmega64a1-atxmega128a1_datasheet.pdf 
). Eines der beiden Bilder sollte ein Schaltbild darstellen, bitte 
korrigiere mich wenn das nicht der Fall sein sollte.

Matthias S. schrieb:
> Wenn du dir das anschaust, siehst du, das der Lichtsensor an Port PB1
> angeschlossen ist, der Temperaturfühler sitzt an PB0 und wird über Port
> PB3 angeschaltet.

Also, an den Rändern der Skizze mit der Überschrift "Block diagram and 
pinout" sehe ich in der Tat deine Bezeichnungen "PB0" und "PB1" und auch 
"PB3". Aber ich verstehe nicht, woher du daraus lesen kannst, dass es 
sich hier um den Lichtsensor/Temperaturfühler handelt.

Matthias S. schrieb:
> Du solltest jetzt also den AD Wandler B aktivieren (wieder mit Hilfe des
> Datenblattes) und dann den Kanal B1 auswählen, um den Lichtsensor
> abzufragen. Das Resultat der AD Wandlung sendest du z.B. wieder an die
> serielle.

Ok, Wenn ich dein "AD Wandler B" in das Englische übersetze, dann müsste 
ich wohl irgendwas im Datasheet suchen wie "Analog-Digital-Converter-B" 
oder abgekürzt "ADCB". Das finde ich auch auf Seite 62 in der Tabelle 
"Peripheral Module Address Map", die aber für nähere Informationen bzlg. 
"ADCB" auf dieses Dokument verweist: 
http://www.atmel.com/images/doc8077.pdf . Auf Seite 284 des letzteren 
Dokuments meine ich den schematischen Aufbau einer "ADC" (hier ohne B) 
zu sehen. (Bitte korrigiere mich wenn es nicht stimmt.)

Des Weiteren kann ich in der source Datei von AVR "iox128a1.h" einige 
Konstanten finden, die mit dem "ADCB" in Verbindung stehen:
1
...
2
/* ADCB - Analog to Digital Converter B */
3
...
4
#define ADCB_CTRLB  _SFR_MEM8(0x0241)
5
...
6
#define ADCB_CH1_CTRL  _SFR_MEM8(0x0268)
7
#define ADCB_CH1_MUXCTRL  _SFR_MEM8(0x0269)
8
#define ADCB_CH1_INTCTRL  _SFR_MEM8(0x026A)
9
#define ADCB_CH1_INTFLAGS  _SFR_MEM8(0x026B)
10
#define ADCB_CH1_RES  _SFR_MEM16(0x026C)
11
...

Wenn ich nun tiefer in dem Text ( 
http://www.atmel.com/images/doc8077.pdf , Seite 297, "CTRLB – ADC 
Control register B") stöbere, finde ich heraus, dass ich eine bestimmte 
Bitfolge setzen muss, um den "AD Wandler B zu aktivieren". Stimmt das?
Falls es stimmt, würde ich diesen Code vorschlagen:
1
void main(){
2
  while(1){
3
    /*aktiviere den ADCB mit "unsigned, Freerun und 8-bit Genaugkeit"*/
4
    ADCB_CTRLB = 0b00001100;
5
    /*
6
    -nun müsste ich den "Kanal B1" (also die Temperatur) ausdrucken können
7
    */
8
    printf("Die Temperatur ist: %u\n",ADCB_CH1_RES);
9
  }
10
}

Bestimmt denke ich viel zu einfach. Was fehlt hier noch?

(Ich lasse das Gedöns mit dem Lautsprecher erstmal weg...)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter Parker schrieb:
> OK habe nun das "datasheet" geöffnet ( Seite 3/4 und 6 ,
> 
http://www.atmel.com/images/atmel-8067-8-and-16-bit-avr-microcontrollers-atxmega64a1-atxmega128a1_datasheet.pdf
> ). Eines der beiden Bilder sollte ein Schaltbild darstellen, bitte
> korrigiere mich wenn das nicht der Fall sein sollte.

Nee, du brauchst das AVR1924.zip von hier:
http://www.atmel.com/tools/XMEGA-A1XPLAINED.aspx?tab=documents
Direkter Link:
http://www.atmel.com/images/AVR1924.zip

Im Zip ist der Schaltplan für das Board als PDF. Ein wenig 
unübersichtlich, aber vollständig.

Um den ADCB zu aktivieren, kannst du z.B. folgendes machen. Leider habe 
ich kein Programmstück für eine einzigen Kanal, sondern immer nur sweeps 
für mehrere:
1
#define ADC ADCB   // using ADC B
2
3
// Setup the ADC for 3-Channel sampling
4
// runs free with 3 channels , zero effort
5
static void ADCInit(void)
6
{
7
  ADC.CTRLA = 0x01;
8
  ADC.CTRLB = ADC_RESOLUTION_12BIT_gc | (ADC_MODE << 4) ;  // 12 bit right adjusted
9
  ADC.PRESCALER = ADC_PRESCALER_DIV256_gc;
10
  ADC.REFCTRL = ADC_REFSEL_VCC_gc;    // using (VCC/1.6) als AREF
11
  ADC.EVCTRL = ADC_SWEEP_012_gc ;     // sweep channels 0 to 3
12
/**
13
 * \brief Get calibration data
14
 *
15
 */
16
  ADC.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL0) );
17
  ADC.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL1) );
18
  // configure channels 0 to 2 input modes
19
  ADC.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
20
  ADC.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
21
  ADC.CH1.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
22
  ADC.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
23
  ADC.CH2.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
24
  ADC.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc;
25
  ADC.CTRLB = ADC_RESOLUTION_12BIT_gc | (ADC_MODE << 4) | (1 << 3);  // enable freerun
26
}
Der ADC läuft nun von alleine im Hintergrund und liefert in seinen 
Ergebnisregistern die Werte für Kanal 0 bis Kanal 2. Nummer 3 lassen wir 
aus, weil da der Portpin PB3 zur Aktivierung des NTC ist, den du auf Low 
setzen musst, damit der NTC vernünftige Werte liefert. Lesen des ADC ist 
einfach:
1
Temperature = ADC.CH0RES;   // temp. sensor
2
Lightstrength = ADC.CH1RES;   // lightsensor
3
AudioIn = ADC.CH2RES;   // from audio out

: Bearbeitet durch User
von Peter Parker (Gast)


Lesenswert?

Vielen Dank für deine Antwort erstmal Matthias.

Matthias S. schrieb:
> Im Zip ist der Schaltplan für das Board als PDF. Ein wenig
> unübersichtlich, aber vollständig.

Ok, auf der Schaltskizze sehe ich die englische Bezeichnung:
-"Phototransistor, Lightsensor": Das Board hat also einen Lichtsensor.
-"NTC TEMP": Das soll "Temperatursensor" bedeuten? Warum heisst es nicht 
"Temperature sensor"?

Wenn ich nun die Linie verfolge steht am Ende "Lightsensor - 6" --> 
"PB1(ACB1/ADCB1)".
Kannst du mir erklären, welche Schlussfolgerungen ich aus dieser 
Feststellung ziehen kann?

Ich probiere nun erstmal selbst zu Schlussfolgerungen zu kommen, in dem 
ich die AVR-Header-Datei für den Chip durchsuche:

-Wenn ich nach "PB1" in der AVR-Header Datei "iox128a1.h" suche, finde 
ich nichts.
-Wenn ich nach "ACB1" in der AVR-Header Datei suche, finde ich wieder 
nichts.
-Wenn ich nach "ADCB1" in der AVR-Header Datei suche, finde ich wieder 
nichts.

Ok jetzt kann ich aber vielleicht von "ADCB1" auf "ADCB" kommen und nach 
"ADCB" in der Header-Datei suchen (analog für "ACB1" -> "ACB"):

-Suche nach "ADCB":
Habe ich ja Dank deiner Ausführungen im vorherigen Post schon eine 
Stelle in der AVR-Header-Datei gefunden, die meines Erachtens nach 
wichtig sein könnte bei der Programmierung mit C. Dann habe ich aber 
auch noch diese Zeile gefunden:
1
#define ADCB    (*(ADC_t *) 0x0240)  /* Analog to Digital Converter B */
2
/*
3
Hieraus schliesse ich, dass es eine Konstante mit dem Namen "ADCB" gibt vom Typ "ADC_t", der Typ "ADC_t" wiederum ist ein gewöhnliches C-Struct namens "ADC_struct".
4
*/

Wenn ich mir jetzt das gewöhnliche C-Struct "ADC_struct" anschaue sehe 
ich folgenden Code:
1
/* Analog-to-Digital Converter */
2
typedef struct ADC_struct
3
{
4
    register8_t CTRLA;  /* Control Register A */
5
    register8_t CTRLB;  /* Control Register B */
6
    register8_t REFCTRL;  /* Reference Control */
7
    register8_t EVCTRL;  /* Event Control */
8
    register8_t PRESCALER;  /* Clock Prescaler */
9
    register8_t reserved_0x05;
10
    register8_t INTFLAGS;  /* Interrupt Flags */
11
    register8_t reserved_0x07;
12
    register8_t reserved_0x08;
13
    register8_t reserved_0x09;
14
    register8_t reserved_0x0A;
15
    register8_t reserved_0x0B;
16
    _WORDREGISTER(CAL);  /* Calibration Value */
17
    register8_t reserved_0x0E;
18
    register8_t reserved_0x0F;
19
    _WORDREGISTER(CH0RES);  /* Channel 0 Result */
20
    _WORDREGISTER(CH1RES);  /* Channel 1 Result */
21
    _WORDREGISTER(CH2RES);  /* Channel 2 Result */
22
    _WORDREGISTER(CH3RES);  /* Channel 3 Result */
23
    _WORDREGISTER(CMP);  /* Compare Value */
24
    register8_t reserved_0x1A;
25
    register8_t reserved_0x1B;
26
    register8_t reserved_0x1C;
27
    register8_t reserved_0x1D;
28
    register8_t reserved_0x1E;
29
    register8_t reserved_0x1F;
30
    ADC_CH_t CH0;  /* ADC Channel 0 */
31
    ADC_CH_t CH1;  /* ADC Channel 1 */
32
    ADC_CH_t CH2;  /* ADC Channel 2 */
33
    ADC_CH_t CH3;  /* ADC Channel 3 */
34
} ADC_t;


-Suche nach "ACB":
1
#define ACB    (*(AC_t *) 0x0390)  /* Analog Comparator B */
2
/*
3
Hieraus schliesse ich, dass es eine Konstante mit dem Namen "ACB" gibt vom Typ "AC_t", der Typ "AC_t" wiederum ist ein gewöhnliches C-Struct namens "AC_struct".
4
*/

Wenn ich mir jetzt das gewöhnliche C-Struct "AC_struct" anschaue sehe 
ich folgenden Code:
1
/* Analog Comparator */
2
typedef struct AC_struct
3
{
4
    register8_t AC0CTRL;  /* Comparator 0 Control */
5
    register8_t AC1CTRL;  /* Comparator 1 Control */
6
    register8_t AC0MUXCTRL;  /* Comparator 0 MUX Control */
7
    register8_t AC1MUXCTRL;  /* Comparator 1 MUX Control */
8
    register8_t CTRLA;  /* Control Register A */
9
    register8_t CTRLB;  /* Control Register B */
10
    register8_t WINCTRL;  /* Window Mode Control */
11
    register8_t STATUS;  /* Status */
12
} AC_t;


Matthias S. schrieb:
> Leider habe
> ich kein Programmstück für eine einzigen Kanal, sondern immer nur sweeps
> für mehrere:

Meinst du damit, dass der Chip es einfach nicht unterstüzt oder, dass du 
einfach keinen anderen Code hast im Moment?

Habe nun mit deinen Tipps (etwas abgeänderter Code, finde die Konstanten 
Definition "ADC" nicht so toll) den Lichtsensor mit folgendem Code zum 
Ausgabe mit printf gebracht:
1
#include <stdio.h>
2
#include "lib/usart_driver.c"
3
#include <avr/pgmspace.h>
4
#include <stddef.h>
5
6
// Forward Declarations
7
void setup(void);
8
void loop(void);
9
10
#define USART USARTC0
11
12
static int uart_putchar (char c, FILE *stream)
13
{
14
    if (c == '\n')
15
    uart_putchar('\r', stream);
16
17
    // Wait for the transmit buffer to be empty
18
    while (  !(USARTC0_STATUS & USART_DREIF_bm) );
19
20
    // Put our character into the transmit buffer
21
    USARTC0_DATA = c;
22
23
    return 0;
24
}
25
FILE usart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
26
27
uint8_t ReadCalibrationByte(uint8_t index) {
28
29
  uint8_t result;
30
  NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
31
  result = pgm_read_byte(index);
32
  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
33
34
  return(result);
35
}
36
37
void setUpSerial() {
38
  // These pins are connected to USARTC0
39
  // Set PINC3 (TXD0) as output
40
  PORTC.DIRSET = PIN3_bm;
41
42
  // Set PINC2 (RXD0) as input
43
  PORTC.DIRCLR = PIN2_bm;
44
45
  // USARTC0, 8 Data bits, No Parity, 1 Stop bit
46
  USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
47
48
  /* Set Baudrate to 9600 bps:
49
   * Use the default I/O clock frequency that is 2 MHz.
50
   * Do not use the baudrate scale factor
51
   *
52
   * Baudrate select = (1 / (16 * (((I/O clock frequency) / Baudrate) - 1) = 12
53
   */
54
  USART_Baudrate_Set(&USART, 12 , 0);
55
56
  // Open both RX and TX
57
  USART_Rx_Enable(&USART);
58
  USART_Tx_Enable(&USART);
59
60
  // enable debug logging to console with printf()
61
  stdout = stdin = &usart_str;
62
}
63
64
void setupLightSensor(){
65
  ADCB.CTRLA = 0x01;  /* ==> Einschalten des ADCB.*/
66
  ADCB.CTRLB = 0b00001100; /* ==> CONVMODE FREERUN RESOLUTION des ADCB einstellen.*/
67
  ADCB.PRESCALER = ADC_PRESCALER_DIV8_gc; /* ==> Frage: Was bringt diese Zeile?*/
68
  ADCB.REFCTRL = (0x01<<4); /* ==> Frage: Was bringt diese Zeile?*/
69
  ADCB.EVCTRL = ADC_SWEEP_012_gc; /* ==> Frage: Was bedeutet "Channel Sweep" überhaupt?*/
70
  ADCB.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL0) ); /* Hier holt man irgendwelche Kalibrationswerte... */
71
  ADCB.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCBCAL1) ); /* Hier holt man irgendwelche Kalibrationswerte... */
72
  ADCB.CH1.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc; /* Was bedeutet "Single-ended input, no gain" ? */
73
  ADCB.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc; /* Wählt den Pin nummer 1 aus. Ist hier die Bezeichnung "PB1" gemeint?*/
74
}
75
76
int main(void) {
77
  setUpSerial();
78
  setupLightSensor();
79
80
  while(1){
81
    printf("ADCB.CH1RES: %u\n",ADCB.CH1RES);
82
    _delay_ms(500);
83
  }
84
85
  USART_Rx_Disable(&USART);
86
  USART_Tx_Disable(&USART);
87
}


Habe nun, aber weitere Fragen und zwar zu den Dingen, die in der Methode 
"setupLightSensor()" passieren:
- Was bringt diese Zeile?:
1
ADCB.PRESCALER = ADC_PRESCALER_DIV8_gc;
Eigene Recherche:
    - Im Dokument ( http://www.atmel.com/images/doc8077.pdf , Seite 290 
) ist eine Skizze aufgemalt und Text bezüglich des "ADC" und seines 
"Prescalers". Habe auch auf Wikipedia gelesen wozu ein Prescaler gut 
sein soll, aber der Text setzt doch auch viel Vorwissen voraus. Kann man 
Prescaler auch für Idioten erklären oder ist das zu komplex?

- Was bringt diese Zeile?:
1
ADCB.REFCTRL = (0x01<<4)
    - Im vorher genannten Dokument auf Seite 298 steht, dass dadurch 
"VCC/1.6" asugewählt wird. Was bedeutet das (bitte eine Erklärung für 
Idioten)?

- Was bedeutet "Channel Sweep" überhaupt?

- Was bedeutet "Single-ended input, no gain" ?

- Wie kann ich diesen Code schreiben, so dass er "Interrupt gesteuert" 
ausgeführt wird?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter Parker schrieb:
> Wenn ich mir jetzt das gewöhnliche C-Struct "AC_struct" anschaue

Das ist der Analog Comparator, eine andere Peripherie als der ADC. Der 
XMega hat viel Peripherie.

>> Leider habe
>> ich kein Programmstück für eine einzigen Kanal, sondern immer nur sweeps
>> für mehrere:
>
> Meinst du damit, dass der Chip es einfach nicht unterstüzt oder, dass du
> einfach keinen anderen Code hast im Moment?

Ich habe nie Verwendung für nur einen Kanal gehabt und deswegen das 
praktische Feature des ADC genutzt, mehrere Kanäle selbstständig zu 
wandeln.

> - Was bringt diese Zeile?:ADCB.PRESCALER = ADC_PRESCALER_DIV8_gc;

Der Prescaler erzeugt den Arbeitstakt für den ADC und sollte so gewählt 
werden, das die maximale Taktfrequenz des ADC nicht überschritten wird. 
Wie hoch er ist, hängt davon ab, wie hoch der CPU Takt ist. Der ADC Takt 
sollte für gute 12-bit Ergebnisse nicht höher als (1/3,5 µs) = 285 kHz 
sein.


Peter Parker schrieb:
> - Wie kann ich diesen Code schreiben, so dass er "Interrupt gesteuert"
> ausgeführt wird?

Was meinst du mit Interrupt gesteuert? Wenn du den ADC zu bestimmten 
Zeiten auslösen willst, kannst du ihn z.B. vom Timer triggern. Du kannst 
auch Interrupts erzeugen, wenn der ADC mit einer Wandlung fertig ist.
Im Moment läuft er, ohne Rechenzeit zu brauchen, im Hintergrund.

Peter Parker schrieb:
> - Was bringt diese Zeile?:ADCB.REFCTRL = (0x01<<4)    - Im vorher
> genannten Dokument auf Seite 298 steht, dass dadurch
> "VCC/1.6" asugewählt wird. Was bedeutet das (bitte eine Erklärung für
> Idioten)?

Hmm, wie kann man das idiotisch erklären? Die Referenz bestimmt die 
obere Grenze des ADC Messbereiches. Die interne Struktur des XMega 
leitet bei der o.a. Einstellung eine Spannung von (3,3/1,6)=2,06 V als 
Referenz an den ADC. Somit misst der ADC zwischen 0 und 2,06 V.

Lies dir bitte im Family Manual (doc8077) den Abschnitt über den ADC 
durch. Das musste ich auch, bevor ich die Dinge wie Channel Sweep usw. 
kapiert habe.

Peter Parker schrieb:
> finde die Konstanten
> Definition "ADC" nicht so toll

Geschmackssache. Mein Code war nämlich für ADCA und ich habe ihn ganz 
simpel auf ADCB mit dieser Definition umgestellt. Das würde bei dir nur 
mit vielfachem Umtippen gehen :-P

: Bearbeitet durch User
von Peter Parker (Gast)


Lesenswert?

Matthias erstmal Danke für die Zeit, die du dir nimmst.

Matthias S. schrieb:
> Lies dir bitte im Family Manual (doc8077) den Abschnitt über den ADC
> durch. Das musste ich auch, bevor ich die Dinge wie Channel Sweep usw.
> kapiert habe.

Habe ich das richtig verstanden?
Also ein ADC wandelt ein analoges Signal (hier eine bestimmte Spannung) 
in eine Bitfolge (Digitales Signal).

Der vorliegende Mikrocontroller kann sogar den Input des analogen 
Signals wählen. Was ist aber nun der Unterschied zwischen:

- /* Single-ended input, no gain */
- /* Differential input, no gain */

Was kann ich von meinem Ergebnis im Register
1
ADCB.CH1RES
 Lichtsensor erwarten?

Wird die Messung dadurch besser/schlechter? Sind besser/schlechter die 
falschen Begriffe?

von Dieter F. (Gast)


Lesenswert?

Peter Parker schrieb:
> Kann man
> Prescaler auch für Idioten erklären oder ist das zu komplex?

https://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC

von Dieter F. (Gast)


Lesenswert?

Peter Parker schrieb:
> Was ist aber nun der Unterschied zwischen:
>
> - /* Single-ended input, no gain */
> - /* Differential input, no gain */

Wie wäre es denn damit, mal die Foren-Suche zu bemühen?

Beitrag "AD-Wandler, Differentialeingänge und single-ended?"

von Peter Parker (Gast)


Lesenswert?

Ok, danke an alle für die sehr hilfreichen Antworten. Habe mein Problem 
lösen können mit den Tipps!

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.