PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATxmega Einstieg will nicht so recht



Ceos
21.11.2009, 14:41
ich hab hier nen STK600 mit nem ATxmega129a1 drinne

ich hab mal folgendes programm geschrieben um die LEDS ans PORTA einfach mal so als lauflicht im 1sekunden takt laufen zu lassen


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

ISR(TCC0_OVF_vect)
{
PORTA.OUT <<= 1;
if(PORTA.OUT == 0) PORTA.OUT = 1;
}


int main(void)
{
CCP = CCP_IOREG_gc;
OSC.CTRL |= OSC_RC32MEN_bm;
while(!OSC.STATUS & OSC_RC32MRDY_bm);
CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
sei();
PORTA.DIR = 0xff;
PORTA.OUT = 1;
TCC0.PER = 31250;
TCC0.CTRLA = (TCC0.CTRLA & ~TC0_CLKSEL_gm) | TC_CLKSEL_DIV1024_gc;
TCC0.CTRLB = (TCC0.CTRLB & ~TC0_WGMODE_gm) | TC_WGMODE_SS_gc;
TCC0.INTCTRLA = (TCC0.INTCTRLA & ~TC0_OVFINTLVL_gm) | TC_OVFINTLVL_LO_gc;
PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;
while(1);
return 0;
}


theoretisch müsste ich auf internen 32MHz takt gestellt haben, den timer prescaler auf 1024 gestellt, als single slope konfiguriert und somit auf 1 überlauf pro sekunde gebracht haben ... das ergebnis sieht aber anders aus ... es sind 16 sekunden pro überlauf, er steht also noch immer bei 2Mhz intern ... auch das umstellen auf externen takt ist fehlgeschlagen und fuses für den takt gibt es nicht!

hat evtl. jemand schon erfahrung mit atxmega? ich find den zwerg ja mal endgeil ^^

auch wenn er ungleich komplizierter geworden ist ... liegt aber mehr daran, dass die registerbezeichnungen so vielfältig aber sinnheitlich verarmt sind

ich benutze mittlerweilen eclipse wegen der autovervollständigung um mich durch den registerjungel zu hangeln

askazo
21.11.2009, 15:04
Hi Ceos,

ich habe gestern auf der Arbeit auch angefangen, mich mit dem XMega zu beschäftigen. Ich habe praktischerweise die gleiche Hardware wie Du. Ich werde am Montag mal versuchen, ein wenig mit den Timern zu hantieren. Ich sag dann Bescheid, wie's gelaufen ist.

Gruß,
askazo

Ceos
21.11.2009, 15:09
hey hey ^^ ich hab leider nur zwischendurch zeit dafür, das macht es umso schwerer sich einzuarbeiten ^^

ich lege dir persönlich eclipse ans herz eclipse für c/c++ und dann nach dem avr eclipse plugin googeln ...

wie du den treiber erstellst kann ich dir später noch posten

in eclipse kannst du dann mit code-vervollständigung arbeiten und mit dem avr plugin haste auch gleich ne passende toolchain und ein modul für den avrdude zum automatischen hochladen ... die fuseeinstellung ist unter aller kanone, dafür würde ich doch eher auf das avrstudio zurückgreifen

Ceos
23.11.2009, 11:00
okay habs hinbekommen .... obwohl schon merkwürdig ... ist garnicht so anders geworden


ISR(TCC0_OVF_vect)
{
PORTA.OUT <<= 1;
if(PORTA.OUT == 0) PORTA.OUT = 1;
}

int main(void)
{
sei();
PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm;
PORTA.DIR = 0xff;
OSC.CTRL |= OSC_RC32MEN_bm;
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
CCP = CCP_IOREG_gc;
CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;
TCC0.CNT = 0;
TCC0.PER = 31250;
TCC0.CTRLA = (TCC0.CTRLA & ~(TC0_CLKSEL_gm)) | TC_CLKSEL_DIV1024_gc;
TCC0.CTRLB = (TCC0.CTRLB & ~(TC0_WGMODE_gm)) | TC_WGMODE_SS_gc;
TCC0.INTCTRLA = (TCC0.INTCTRLA & ~(TC0_OVFIF_bm)) | TC_OVFINTLVL_HI_gc;
while(1);
return 0;
}


ich hab eigentlich nur das CLK.CTRL vorher ausmaskiert oder hab ich tomaten auf den augen ?

askazo
23.11.2009, 13:12
Nein, Du hast noch was ganz entscheidendes anders gemacht.
Vorher:

while(!OSC.STATUS & OSC_RC32MRDY_bm);
Nachher:

while(!(OSC.STATUS & OSC_RC32MRDY_bm));

Ich versuche gerade, den Timer mit 32MHz laufen zu lassen. Irgendwo muss doch noch ein Register für den Common Prescaler der Timer sein...


Quatsch, hab mich verrechnet - der Timer läuft schon mit 32MHz. Aber der Common Prescaler (siehe Seite 153 im Manual) muss doch trotzdem irgendwo einzustellen sein, oder?


Gruß,
askazo

Ceos
23.11.2009, 15:22
also im manual A (NICHT DATASHEET!) auf seite 80 steht, dass man erst die quelle einstellt, dann prescaler A, B und C setzt

A: 1,2,4,8,16,32,64,128,256, 512 (5bit, offset 2, CLK.PSCTRL register)
B: 1,2,4
C: 1,2

B & C (2bit, offset 0 CLK.PSCTRL register)

theoretisch kann man auch den hochpräzisen timerquarz als source nehmen und über den PLL laufen lassen um die freuenz zu multiplizieren

EDIT:

quark ... hab nochmal nachgelesen, mit PS A kann man den takt teilen und mit PS B und C kann man zum abstimmen des taktverhältnis von CPU zu peripherie einzustellen ... geile idee, peripherie 4mal schneller als CPU ... das spart bestimmt ordentlich zeit beim benutzen der UART und man kann das zeitverhalten der CPU linearer berechnen ....

aber ich hab zu wenig weitblick als dass sich mir der sinn dieser funktion vollkommen erschliessen würde ^^

askazo
23.11.2009, 17:18
Hmm, so langsam blicke ich ein wenig durch.
Standartmässig sind die Teiler A,B und C auf 1, d.h.
clkper = clkper2 = clkper4 = clksys.
Mit den Teilern kann ich jetzt das ganze z.B. so einstellen, dass die "normale" Peripherie (also alles, was auf clkper läuft) und die CPU (clkcpu ist immer gleich clkper) auf 8MHz läuft, clkper2 auf 16MHz und clkper4 auf 32MHz (=clksys). Nur der Sinn des ganzen erschließt sich mir nicht ganz. Höchstens Stromersparniss...

Gruß,
askazo

Ceos
23.11.2009, 20:49
wie gesagt taktvorteile der hardware der CPU gegenüber seh ich da mehr im vorteil

maloj
25.11.2009, 14:49
leute ich verzweifele ich hab auch nen STK600 mit nem ATxmega128a1 drinne und jtag mk2.

Folgendes Problem: Wenn ich in Debugmodus gehe und im Quellcode nichts oder entweder was steht(PORTA und LEDPORT sind miteinander verbunden), fangen die LED0 und LED1 zu leuchten und die STATUSLED blinkt rot. Wenn man PORTB mit LEDPORT verbindet, fangen LED7 und LED4 zu blinken und LED5 und LED6 zu leuchten an und die STATUSLED blinkt weiterhin rot??


Woran kann es liegen!!???


Vielen Dank im Vorraus

askazo
26.11.2009, 08:17
Hi maloj,

willkommen im Club :)
PORTB funktioniert nicht, da auf PB4-PB7 das JTAG-Interface liegt.
Warum allerdings PORTA nicht geht, ist mir auch ein Rätsel. Aber zur Beruhigung - bei mir passiert das selbe.
PA0 und PA1 sind seltsamerweise nach dem Reset bei leerem Controller - im Gegensatz zu anderen Port-Pins - auf High. Da scheint also irgendeine Special Function drauf zu liegen, die standardmässig aktiviert ist. Allerdings liegt laut Datenblatt auf den beiden nur der ADC bzw. der analoge Komparator. Auf PA0 zusätzlich noch AREF, aber das erklärt das Phänomen auch nicht. Da bin ich ratlos...

Aber Du hast ja noch genug andere Ports, die Du auf die LEDs legen kannst :)

Gruß,
askazo

maloj
26.11.2009, 13:12
Hi du hast Recht mit dem PortB. Bin halt noch anfänger!!

Wegen dem PortA hat mir einer folgendes in dem Microcontroller.net geschrieben und das FUNKT:

Okay, jetzt kommen wir der ganzen Sache schon näher...

Im Datenblatt des XMegas steht, dass PA0 und PB0für die analogen
Referenzspannungen benutzt werden können (Alternate Pin Functions).
Außerdem liegt glaube ich an PA1 ebenfalls ein Analog-Kanal. Diese sind
dementsprechend auf jeden fall mit ARef0/1 vom STK600 verbunden.

Sobald du die auf Ausgang stellst treiben der Spannungsregler der
Analogversorgung und der Ausgangstreiber im XMega gegeneinander. Das
quittiert das STK mit einem kompletten Abschalten der
Versorgungsspannung aus Sicherheitsgründen.

Wenn du die beiden Pins nutzen möchtest, so entferne am besten die
Jumper für Aref0 und Aref1. Dann sollte es funktionieren.

MfG
Marius

askazo
26.11.2009, 15:09
Ah - die ARef-Jumper. Jetzt macht's Sinn... Und ein Blick in die Anleitung zum STK600 erklärt auch, wieso PA1 Ärger macht:

For xmega devices the AREF pins is also general purpose I/O pins. Hence, to use the pins as GPIO the Aref jumpers must be removed.

Note: For routingcard "STK600-RC100X-13" revision A and revision B the AREF1 is connected to PA1. These cards are marked "A0607.3.1213.A" and "A0607.3.1213.B"


Gruß,
askazo

maloj
26.11.2009, 15:36
Ja, weisst du vielleicht was mit den anderen beiden Jumpern ist?? Der Jumper VTARGET bleibt drin und der Resetjumper muss er raus?

askazo
26.11.2009, 16:03
VTARGET und RESET müssen drin bleiben.
Wenn Du VTARGET rausnimmst, bekommt der Controller keine Spannung mehr vom Board.
Den RESET-Jumper solltest Du nur rausnehmen, wenn Du einen externen Reset-Controller anschließt (was vermutlich nie passieren wird).

maloj
30.11.2009, 15:03
Hi,

ich bins noch mal. Habe da eine Frage und zwar zum LED Programm was oben steht.
Dieser Wert "TCC0.PER = 31250" repräsentiert in diesem Fall eine Sekunde. Für 8 Sekunden müsste dann 250000 anstatt 31250 stehen, warum klappt es aber nicht???

Vielen Dank im Vorraus

askazo
30.11.2009, 15:11
Ganz einfach:
Das PER-Register ist ein 16-bit Register. Mit 16 Bit kommst Du auf maximal 65535 (2^16)....

Gruß,
askazo

maloj
30.11.2009, 15:38
Ok natürlich!!!

Noch eine kleine Frage und zwar wenn ich TCC1 anstatt TCCO verwenden möchte, was muss ich alles in dem Led Programm ändern??


Vielen Dank im Vorraus!!!

askazo
30.11.2009, 16:03
Das ist das schöne bei den neuen Registerdefinitionen des XMega:
Du brauchst nur alle TCC0 mit TCC1 zu ersetzen - fertig.

maloj
30.11.2009, 16:12
Ich habe die Frage falsch gestellt! Wenn ich beide TCCn verwenden möchte, wie wird das ganze initialisiert!!??

maloj
01.12.2009, 09:39
ES FUNKT!!

Aber eine Frage habe ich noch, warum Funktioniert LEDProgramm nicht richtig(1 Sekunde wird nicht eingehalten), wenn man Optimierung abschaltet!?

Und was sollte man ändern damit es trotzdem ohne Optimierung funktioniert!????

Ceos
01.12.2009, 12:46
dass er ohne optimierung die zeit nicht einhält ist seltsam, hab ich noch nicht probiert

um wie viel weicht es denn ab ?

maloj
01.12.2009, 13:25
Bei: O0 --> 16sek
O1 --> 16sek
O2 --> 1sek
O3 --> 1sek
Os --> 1sek

Ceos
01.12.2009, 13:57
also 16 sekunden sagt mir, dass irgendwas mit der takteinstellung nicht hinhaut!

vermutlich vergehen zu viele takte zwischen


CCP = CCP_IOREG_gc;
CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;


versuchs mal mit ner zwischenvariable oder nem festwert, also


unsigned char temp = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC32M_gc;
CCP = CCP_IOREG_gc;
CLK.CTRL = temp;


alternativ kannste dir die bitmaske für das CLK.CTRL register direkt reinschreiben also 0bxxxxxxxx ... berichte mal über die ergebnisse

PS : laut datenblatt gibt es geschützte register wie z.B. das clocksource CLK.CTRL, die können nur beschrieben werden, wenn vorher das CCP register mit dem pasenden wert beschrieben wird und dann auch nur exakt 4 takte lang, also wenns zu lang dauert pustekuchen ^^

maloj
01.12.2009, 21:11
Also mit der zwischenvariable funkt!!!!!

Ceos
02.12.2009, 09:59
danke dir ^^ gleich mal im datenblatt vermerkt ^^

aber dass der beim optimieren sooo sehr schlampt und die formel aus festwerten nicht auflöst find ich schon ein wenig krass ....

ist vielleicht jemand der hier mitließt firm genug den zeitlichen unterschied zwischen der optimierten MIT formel variante und der OHNE formel variante zu vergleichen ?

ich dachte immer, dass macht kein unterschied ob ich bits schiebe oder gleich binär/hex schreibe O_o

askazo
02.12.2009, 10:43
Das Problem ist, dass hier zuerst der aktuelle Wert des CLK.CTRL-Registers ausgelesen werden muss. Somit besteht die Verknüpfung nicht nur aus Festwerten und kann daher auch nicht direkt aufgelöst werden.

Da aber nach dem Reset alle Bits des CLK.CTRL-Registers sowieso komplett auf 0 stehen, kann man sich das
(CLK.CTRL & ~CLK_SCLKSEL_gm) auch sparen und einfach nur
CCP = CCP_IOREG_gc;
CLK.CTRL = CLK_SCLKSEL_RC32M_gc; schreiben, das verkürzt die ganze Sache ungemein.

Gruß,
askazo

Ceos
02.12.2009, 11:41
ach stimmt ja ... arrrgh kein-kaffee-blind ... naja das register aber vorher mal auszulesen ist aber auch nicht unbedingt verkehrt!

nur in der situation ohne optimierung natürlich n killer ^^, es sei denn man machts mit ner variable vor dem freischalten