PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Erste Versuche mit einem XMega128



Kampi
22.03.2012, 22:12
Hallo Forum,

ich programmiere gerade etwas mit einem XMega128A1 und habe folgendes Programm:



/*
* XMega.c
*
* Created: 22.03.2012 19:42:07
* Author: Daniel
*/

#include <avr/io.h>

int main(void)
{
// Taktquelle konfigurieren
OSC.CTRL |= 0x02; // 32MHz-Enable Bit setzen
while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // Sobald der Takt stabil ist wird das RC32MRDY Bit gesetzt
CCP = 0xD8; // I/O Protektion aktivieren
CLK.CTRL = 0x01; // 32MHz als Taktquelle auswählen

// PLL konfigurieren
OSC_PLLCTRL = 0x82; // PLL Multiplikator auf x2 setzen und PLL Input Clock auf 32MHz setzen
OSC.CTRL |= 0x10; // PLL-Enable Bit setzen
while(!(OSC.STATUS & OSC_PLLRDY_bm)) // Warten bis PLL bereit ist

// I/O konfiguration
PORTB.DIR = 0xff; // Port B auf Ausgang stellen

while(1)
{
PORTB.OUT ^= (1<<PIN0);
}
}


Der Sinn des Programmes besteht darin, den Takt auf 32Mhz zu setzen und dann diesen Takt für die interne PLL zu nutzen.
Im Hauptprogramm wird dann ein Pin getoggled, damit ich am Oszi eine Veränderung sehen kann.
Allerdings zeigt das Oszi immer 2,35MHz an, egal auf was ich den PLL Multiplikator setze.
Wo steckt mein Fehler?

Danke für die Hilfe!

ePyx
23.03.2012, 07:52
Guten Morgen,

also bei mir funktioniert die folgende Variante (zum Vergleich) :



/*Oscillator auf 32Mhz einstellen*/
OSC.CTRL |= (1<<PIN1);
/*Wenn Oscillator stabil wird das Flag RC32MRDY
* gesetzt und 32Mhz können benutzt werden*/
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
/*I/O Protection*/
CCP = 0xD8;
/*Clock auf 32Mhz einstellen*/
CLK.CTRL = (1<<PIN0);

DFLLRC32M.CTRL = DFLL_ENABLE_bm;

Kampi
23.03.2012, 09:09
Guten Morgen,

also bei mir funktioniert die folgende Variante (zum Vergleich) :



/*Oscillator auf 32Mhz einstellen*/
OSC.CTRL |= (1<<PIN1);
/*Wenn Oscillator stabil wird das Flag RC32MRDY
* gesetzt und 32Mhz können benutzt werden*/
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
/*I/O Protection*/
CCP = 0xD8;
/*Clock auf 32Mhz einstellen*/
CLK.CTRL = (1<<PIN0);

DFLLRC32M.CTRL = DFLL_ENABLE_bm;


Ja aber das ist ja nur die Variante für den 32MHz Takt. Ich möchte ja noch die PLL dazu benutzen.
Aber mir ist heute morgen eingefallen....hat der XMega von Werk aus vielleicht noch ein Clock/8 Fusebit was gesetzt ist (so wie ein Mega168 ).
Weil 2,35MHz für ein einfaches Bit togglen ist etwas wenig....das wären Pi mal Daumen 16 Zyklen für den Befehl.....
Wenn der Takt aber durch dieses Bit erst durch 8 geteilt wird, würde es das erklären.
Weißt du da was drüber? Sonst muss ich nach der Arbeit mal reinschauen :)

ePyx
23.03.2012, 09:14
Der Oszillator verwendet doch die interne PLL um die Taktfrequenz überhaupt erreichen zu können. Ein CLKDIVIDER wie bei den neueren ATMegas ist mir nicht bekannt. Macht ja auch keinen Sinn, da man bei den Xmegas den CLock via Firmware setzen kann.

Eine gute Anlaufstelle ist folgende Seite : http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial

Ok hab gerade die AppNote zum Clocksystem gelesen. Dann ist meine Aussage natürlich falsch.

Kampi
23.03.2012, 09:25
Eine gute Anlaufstelle ist folgende Seite : http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial

Ok hab gerade die AppNote zum Clocksystem gelesen. Dann ist meine Aussage natürlich falsch.

Ja die Seite habe ich gestern auch gefunden. Leider steht da nichts zu der PLL ;)
Und ich meine mich erinnern zu können das die neueren Megas (168, 328....) alle so einen CLKDIVIDER haben, aber ich schaue nachher nochmal.
Und das Clocksystem beim XMega ist auch für mich Neuland. Nur ich wollte halt probieren den Takt mit Hilfe der PLL auf 64MHz zu erhöhen.

Kampi
23.03.2012, 14:00
Der Oszillator verwendet doch die interne PLL um die Taktfrequenz überhaupt erreichen zu können. Ein CLKDIVIDER wie bei den neueren ATMegas ist mir nicht bekannt. Macht ja auch keinen Sinn, da man bei den Xmegas den CLock via Firmware setzen kann.

Eine gute Anlaufstelle ist folgende Seite : http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial

Ok hab gerade die AppNote zum Clocksystem gelesen. Dann ist meine Aussage natürlich falsch.

Hat zwar nichts mit dem Problem zu tun, aber ich habe eben nochmal nachgeschaut. Der Mega328 auf meinem Arduino hat ein CLKDIV Fusebit.
Siehe Screen:
http://img827.imageshack.us/img827/5466/unbenanntazx.png (http://imageshack.us/photo/my-images/827/unbenanntazx.png/)

Leider ändert das wie gesagt nichts an meinem Problem das die PLL nicht arbeitet ;)

ePyx
23.03.2012, 14:51
Ja ein Fuse-Bit haben die neueren ATMegas. Aber Der Xmega hat keines und der Oszillator ist komplett per Software ansprechbar.

Kampi
23.03.2012, 14:56
Ja ein Fuse-Bit haben die neueren ATMegas. Aber Der Xmega hat keines und der Oszillator ist komplett per Software ansprechbar.

Jap nur ich dachte der hätte vielleicht auch noch so ein Fusebit. ;)
Ist aber doch schon was anderes wenn du den Oszillator komplett in der Software steuern kannst. Generell gefällt mir der Chip sowieso richtig gut :)
Nur der 3,3V Pegel ist doof :(

Torrentula
23.03.2012, 15:02
Nur der 3,3V Pegel ist doof

Haben aber mittlerweile alle neueren / größeren Chips :(

Welches Board verwendest du?

Kampi
23.03.2012, 15:13
Haben aber mittlerweile alle neueren / größeren Chips :(

Welches Board verwendest du?

Ja das stimmt. Ist doof aber gut dafür gibt es Work-Arounds.
Als Board verwende ich ein selbst gebautes. Ein XMega mit einer Adapterplatine auf einem Stück Lochraster und dann kommen da noch 11 Wannenstecker für die Ports dran. Spannungsversorgung befindet sich unterm Chip.
Bisher sieht das Board so aus:
http://img813.imageshack.us/img813/120/dscf0214d.jpg (http://imageshack.us/photo/my-images/813/dscf0214d.jpg/)

Ist nichts besonderes ;) aber später wollte ich das Board als Master in einem Controllernetzwerk verwenden.

ePyx
23.03.2012, 15:24
Jap hab auch zwei ATXmega-Boards. Beide mit 128A1. An den 3V3-Pegel muss man sich gewöhnen, aber so schlimm ist es auch nicht. L293D mit 3,3V (IO-Level) macht momentan noch nicht so den Spaß, aber wird schon.

ePyx
24.03.2012, 07:19
Für welche Applikation brauchst du die 64 MHz eigentlich? Wenn ich heute Nachmittag etwas Zeit habe, mach ich mal ein zwei Fotos von den Boards.

Kampi
24.03.2012, 10:29
Für welche Applikation brauchst du die 64 MHz eigentlich? Wenn ich heute Nachmittag etwas Zeit habe, mach ich mal ein zwei Fotos von den Boards.

Erstmal für gar nichts ;)
Wollte nur ein bischen mit dem Oszillator rumspielen :rolleyes:

Kampi
24.03.2012, 19:16
AVR Studio meckert bei diesem Programm rum:



/*
* XMega.c
*
* Timer C0 wird ist auf 1 Sekunde eingestellt.
*
* Created: 22.03.2012 19:42:07
* Author: Daniel
*/

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

void Clock_init(void);
void PLL_init(void);
void Int_init(void);
void Port_init(void);
void UART_init(void);
void DAC_init(void);
void ADCA_init(void);
void TimerC0_init(void);

void Send_UART(void);
void ADC_Cal(void);
void Start_Conversion(void);

int main(void)
{
// Variablen
volatile int ADC_Value = 0x00;
volatile int Calibration_Value_ADC; // Buffer für ADC Kalibrationswert

Clock_init(); // Konfiguriert die Clock
PLL_init(); // PLL konfigurieren
Int_init(); // Interrupts konfigurieren
DAC_init(); // DAC konfigurieren
ADCA_init(); // ADC konfigurieren
ADC_Cal(); // ADC kalibrieren
TimerC0_init(); // Timer C0 konfigurieren
Port_init(); // Ports konfigurieren
UART_init(); // UART konfigurieren

while(1)
{
}
}


void DAC_init()
{
DACA.CTRLC = ~(DAC_REFSEL_gm | DAC_LEFTADJ_bm); // Interne 1V Referenz, right adjust (12 Bit);
DACA.CTRLA = (DAC_CH0EN_bm | DAC_ENABLE_bm); // 1CLK Takt, Refresh 16CLKs
// DACA.TIMCTRL = 0x00;
// DAC aktivieren
}

void ADCA_init()
{
ADCA.CTRLA = 0x01; // ADC Enable
ADCA.CTRLB = 0x04; // Unsigned Mode / 8 Bit
ADCA.REFCTRL = 0x00; // Interne 1.0V Referenz
}

void Clock_init(void)
{
OSC.CTRL |= OSC_RC32MEN_bm; // Oszillator auf 32Mhz stellen
while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // Warten bis der Oszillator bereit ist
CCP = CCP_IOREG_gc;
CLK.CTRL = 0x01; // Clock auf 32MHz stellen
}

void PLL_init(void)
{

}

void Int_init(void)
{
PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; // Interrupts (Highlevel,Mediumlevel und Lowlevel freigeben)
sei(); // Globale Interruptfreigabe
}

void Port_init(void)
{
PORTB.DIR = 0xFF; // Kompletten PortB auf Ausgang stellen
}

void TimerC0_init(void)
{
TCC0.CTRLA = TC_CLKSEL_DIV1024_gc; // Vorteiler einstellen
TCC0.PER = 31249; // Timer-Topwert einstellen
TCC0.CTRLB = 0x00; // Timer in Normalmodus stellen
TCC0.INTCTRLA = 0x03; // Interrupt konfigurieren
}

void UART_init(void)
{

}

void Send_UART(void)
{

}

void Start_Conversion(void)
{
ADCA.CH0.CTRL = 0x81; // Messung starten und Input-Mode auf Singleended stellen
ADC_Value = ADCA_CH0RES;
}

void ADCA_Cal(void)
{
Calibration_Value_ADC = 0x00;
ADCA_CAL = Calibration_Value_ADC;
}

ISR(TCC0_OVF_vect)
{
PORTB.OUT ^= 0x01;
}


Als Fehler kommt das hier:

http://img850.imageshack.us/img850/897/unbenanntqgr.png (http://imageshack.us/photo/my-images/850/unbenanntqgr.png/)

Dabei habe ich die Variablen doch deklariert....
Hat jemand ne Lösung für das Problem?
Danke schonmal!

ePyx
24.03.2012, 19:19
Ja aber lokal in der main.

Kampi
24.03.2012, 19:48
Ja aber lokal in der main.

Danke.....dummer Fehler :/
Ne Frage zum Thema ADC....bei der Zeile "ADCA.CH0.CTRL = 0x81;" bezieht sich "CH=0" ja auf Channel 0.
Ist damit PinA.0 gemeint oder wie muss ich das verstehen?

ePyx
24.03.2012, 22:26
Na du hast zwei ADCs im XMega. Den ADCA und ADCB. Beide hängen auch an PortA und PortB. Wenn du jetzt ADCA.CH0 nimmst ist es also PortA.Pin0.

Kampi
24.03.2012, 22:36
Danke für die Antwort. Aber ich habe mir vorhin im Datenblatt die Stelle nochmal durchgelesen.
Wenn ich es richtig verstehe (und ich weiß nicht ob es so ist ;) ), hat der XMega 2 ADCs (wie du schon sagtest). Jeweils einen an PortB und A. Diese ADCs sind in 4 Kanäle unterteilt. Und dann kann man mittels des Mux Registers diesem Channel nochmal nen Pin zuweisen.
Das sieht man in dem Bild aus dem Datenblatt recht gut:

http://img221.imageshack.us/img221/1166/unbenanntwm.png (http://imageshack.us/photo/my-images/221/unbenanntwm.png/)

ePyx
25.03.2012, 07:50
Das mit den MUX-Registern gibt es auch bei den Megas und Tinys schon. Der ADC tastet ja nur immer einen Port-Pin ab. Damit er weiß welchen, musst du ihm das natürlich sagen. Frei wählen wie bei den externen Interrupts (was ich neben TWI, SPI und USART immer noch am Schärfsten finde ;) ). Dort kannst du explizit per Pin-Maske einen Pin auswählen. Was bei den ADCs nicht in der Funktionalität geht. Dort wird via Multiplexer zwischen den Quellen geschaltet. Daher auch der Name Mu(ltiple)x-Register.

Die Grafik ist für mich so zu deuten, dass man mit den MUX-Registern eine Kanalauswahl trifft. Entweder die differentiellen mit oder ohne Verstärkung oder aber die Single-Ended-Eingänge. Dann folgt die Konfiguration hinsichtlich Auflösung, Referenzspannung und Events. Da mit relativ hoher Wahrscheinlichkeit mehrere Kanäle zum Messen verwendet oder aber die Daten für den DMA gehalten werden müssen, gibt es dann pro Kanal ein Register wo man das Ergebnis abholen kann.

Man kann im Übrigen auch 4 virtuelle Kanäle deklarieren. Das geht über das MUXCTRL-Register.



ADCA.CH0.MUXCTRL

Kampi
25.03.2012, 10:06
Ich habe mir gerade mal eine Application Note von Atmel angesehen.
Dort habe ich diese Grafik gefunden:

http://img543.imageshack.us/img543/3708/unbenanntky.png (http://imageshack.us/photo/my-images/543/unbenanntky.png/)

Ich finde die erklärt das ein bischen besser als die im Datenblatt :)
Das mit den Virtuellen Kanälen habe ich noch gar nicht gesehen ^.^ und bisher hab ich nichtmal ne Ahnung wofür ich das brauchen könnte.

Kampi
25.03.2012, 13:15
Juhu nun scheint die PLL auch endlich zu arbeiten :)
Was ich nur noch nicht ganz verstehe ist folgendes:
Ich habe diese Zeile:

OSC.PLLCTRL = OSC_PLLSRC_RC32M_gc | 0x04;

Damit wird in das PLL Control-Register reingeschrieben das der interne 32MHz Takt verwendet wird und ein PLL Multiplikator von 4 verwendet wird. Damit komme ich auf meine Pin-Toggle Frequenz von 2,36MHz (die selbe Frequenz habe ich auch mit 32MHz und ohne PLL).
Aber warum ist das so? Müsste diese Frequenz nicht normalerweise rauskommen wenn ich 0x01 als Multiplikator vorgebe? Weil dann wird die Frequenz ja mit 1 multipliziert und das ergibt dann Ausgangsfrequenz = Eingangsfrequenz. Aber ich muss das mit 4 multiplizieren.
Bis 47MHz habe ich die CPU schon bekommen (und das hat sogar mein Oszi noch gemessen obwohl es nur ein 40MHz Gerät ist). Aber bei einem Multiplikator von 7 gibt das Oszi nur noch nen High-Pegel an.....ich glaube das geht schon an die Grenzen von dem Gerät :D
Beim internen 2MHz Takt scheint es so zu sein das man mit einem Multiplikator von 1 die Originalfrequenz hat. Beim 2MHz Takt toggled mein Pin mit 150kHz und mit PLL und Multiplikator 1 sind es 220kHz. Wobei das auch schon merkwürdig ist, dass man bei einem Multiplikator von 1 mehr bekommt und bei 32MHz wird es weniger.....
Kann sich da jemand einen Reim drauf machen?