Forum: Mikrocontroller und Digitale Elektronik AVR32UC3A Port setzen


von Michael (Gast)


Lesenswert?

Hallo,

wie definiert man beim AVR32 die Ports???

Beim Atmega
1
// Ports
2
#define LCD_CMD_PORT    PORTA    // Command Output Register
3
#define LCD_CMD_DIR      DDRA    // Data Direction Register for Command Port
4
5
#define LCD_DATA_IN      PINC    // Data Input Register
6
#define LCD_DATA_OUT    PORTC    // Data Output Register
7
#define LCD_DATA_DIR    DDRC    // Data Direction Register for Data Port

kann mir jemand helfen wie das beim AVR32 aussehen muß?

Gruß Michael

von Marius W. (mw1987)


Lesenswert?

Du solltest dir das Datenblatt vom UC3 mal anschauen. Unter der Rubrik 
GPIO-Controller solltest du fündig werden. Da stehen alle wichtigen 
Register beschrieben.

Aber ich bin mir sicher, dass du nicht damit auskommen wirst, einfach 
die #defines zu ändern. Da wirst du sicherlich noch was im Code ändern 
müssen, vor allem da sich die Register vom AVR nicht 1:1 auf den AVR32 
übertragen lassen.

MfG
Marius

von Hans W. (hans_wurst)


Lesenswert?

Es gibt bereits header-Dateien, bei denen die Ports bereits alle 
definiert sind. Beim Einbinden der IO-Bibliotheken kannst du sie 
problemlos verwenden. Am besten du schaust dir einfach eines der 
Beispiele an, die im "AVR32 Studio" bereits integriert sind.

von Joschi (Gast)


Lesenswert?

Hi,

du musst glaube ich zuerst die avr/io.h einbinden und eine sogenannte 
gpio.h, evtl. funktioniert das bei dir, bei mir hats so nicht geklappt 
und ich bin noch am probieren.

Im Programm schreibst du dann einfach:
gpio_set(bzw. clear)_gpio_pin(AVR32_PIN_PA02);

Ob das funktioniert weiss ich noch nicht, da ich noch Probleme mit der 
HEADERDATEI gpio.h hab.
Eine Alternative ist eine einfache Zuweisung:
PORTB=0X0001, womit eigentlich das 1. Bit gesetzt werden müsste.

Evtl. einfach mal probieren mit einer LED an 5V und einem Vorwiderstand 
220 Ohm, Spannungsquelle anschließen an die LED und das 2. Ende in den 
Controller.
Wenn es klappt am besten mal posten.

Gruß JO

von Zippi (Gast)


Lesenswert?

Hi

Also ist ganz simpel
#include <avr32/io.h>
einbinden, mehr brauchst du nicht.

So es gibt 1 Register mehr bei AVR32 als bei den 8bit AVRs die du 
setzten musst und das ist der GPIO enable register. Außerdem musst du 
beachten das die port 32bit lang sind und nicht nur 8 bit. In dem 
Beispiel enable ich mal PA0 und PA4. Dabei setzte ich PA0 auf low und 
PA4 auf high.

AVR32_GPIO.port[0].gper = 0x00000011;  // GPIO enable Register

mit 1 machst du den GPIO active. Die 0 in den [] steht für den Port.
0 = A, 1 = B, 2 = C

AVR32_GPIO.port[0].oder = 0x00000011;        // GPIO als ausgang.
Die 0 wieder für den A PORT.
AVR32_GPIO.port[0].oder ist also DDRA

AVR32_GPIO.port[0].ovr  = 0x00000010;        // GPIO zustandt
So hier hab ich mit na 1 PA4 auf High gesetzt und PA0 auf low.


So ich hoffe es war gut verständlich. Fall noch fragen sind, dann 
einfach posten.

von Michael (Gast)


Lesenswert?

Hallo Zippi,

ok, das ist soweit klar.

Und mit gpio.h sollte es so aussehen oder?
1
#define EN_PIN   0
2
#define ENABLE_LOW     gpio_clr_gpio_pin(EN_PIN);
3
#define ENABLE_HIGH     gpio_set_gpio_pin(EN_PIN);
4
5
gpio_enable_module_pin(EN_PIN, 0);
wobei mir nicht klar ist für was der zweite Parameter 0(function a, b, 
c) steht.

Wenn ich jetzt PA0-PA7 definiert habe,wie sendet man ein Byte dort hin?

von Zippi (Gast)


Lesenswert?

Hi also der 2. Parameter 0 steht für das Modul.

Wenn du mal im Datenblatt(UC3A) auf seite 45 gehst dann siehst du unten 
eine Tabelle.
12.7 Peripheral Multiplexing on I/O lines

Da kannst du die Functionen durchschalten. 0 = Function A, 1 = Function 
B, 2 = Function C.

Aber so wie ich das Verstanden hab willst du die IOs schalten und keine 
Function.

Zurzeit würdest du Also PA0 Auf Function USART0 - RXD setzten.

Richtig wäre:
1
#define EN_PIN   0
2
#define ENABLE_LOW     gpio_clr_gpio_pin(EN_PIN);
3
#define ENABLE_HIGH     gpio_set_gpio_pin(EN_PIN);
4
5
gpio_enable_gpio_pin(EN_PIN);

Wobei ich sagen muss das der GPIO mit jedem
1
gpio_set_gpio_pin(unsigned int pin);
2
gpio_clr_gpio_pin(unsigned int pin);
neu enabled wird.

Wichtig ist das du in der Tabelle schaust welchen GPIO du setzten 
willst. Dort gibt es keinen definierten port. Also PORT A ist GPIO(0-31) 
wobei es 31 nicht giebt warum auch immer. Und PORT B ist GPIO(32-63).

So jetzt willst du ein Byte über nen ganzen port bringen. Naja du kannst 
mit der GPIO.h nur alle bits einzeln setzten. Da wäre natürlich ziemlich 
beschissen. Deswegen hab ich ja das oben mit den Registern direct 
erklärt.
1
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| byte);
Damit würdest du das byte parralel an PA0 - PA7 legen.

von Michael (Gast)


Lesenswert?

vielen Dank für die gute Erklärung

von Michael (Gast)


Lesenswert?

Hallo,

ich habe noch andere Unklarheiten:

Gibt es beim AVR32 auch ein pgm_read_byte?
1
unsigned short ReadData(const unsigned short* ptr)
2
{
3
  return pgm_read_byte(ptr);
4
}
ist es richtig den Port so einzulesen?
1
Port = AVR32_GPIO.port[1].ovr;
wie setzt man den 8Bit breiten Port komplett auf Ausgang bzw. Eingang?

von Zippi (Gast)


Lesenswert?

HI ich könnt ja mal ne Wiki schreiben :D.

Also pgm_read_byte scheint was aus der AVR Lib zu sein oder? Ob das bei 
AVR32 läuft weiß ich nicht musst du testen.
Das ovr (Output Value Register) wo der Name für die function steht ;). 
Also nen wert am Pin einlesen geht damit nicht.

Da brauchst du das pvr (PIN VALUE REGISTER).
1
Port = AVR32_GPIO.port[1].pvr;       // damit liest du komplett PORTB ein

So jetzt nochmal zu deinen 8bit daten. Die sollen auf PA0-PA7 oder?

Dazu will ich die jetzt noch eine zusatz Funktion erklären die ganz toll 
ist beim AVR32
Man kann bei den GPIOs hinter redem register noch ein s, c oder t 
schreiben.
s = setzen(set). Es setzt die pins auf 1 die du auf 1 gestellt hast.
C = löschen(clear). Es löscht die pins mit 0 die du auf 1 gestellt hast.
T = umschalten(toggle). Die pins die du auf 1 gestellt hast wechseln den 
zustandt. (das gilt nur fürs schreiben)

So jetzt mach ich dir mal Funktionen.
1
void data_port_output_init()
2
{
3
AVR32_GPIO.port[0].gpers = 0x000000ff;     // Activiert PA0-PA7
4
AVR32_GPIO.port[0].oders = 0x000000ff;     // setzt PA0-PA7 als ausgang
5
}
6
/*Hier wird wirklich nur Pa0-PA7 als ausgang gesetzt. Wenn PA8 schon ein ausgang war wird das bit nicht auf 0 gestellt das ich die function s (set) genutzt habe.*/
7
8
void data_port_input_init()
9
{
10
AVR32_GPIO.port[0].gpers = 0x000000ff;    // Activiert PA0-PA7
11
AVR32_GPIO.port[0].oderc = 0x000000ff;    // setzte PA0-PA7 als eingang
12
AVR32_GPIO.port[0].puers = 0x000000ff;    // Activiert Pull-up für PA0-PA7
13
}
14
15
16
void send_data(char byte)
17
{
18
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| byte);
19
}
20
/*Hier habe ich die s (set) function nicht genutzt, weil die bits welche 0 sind, im daten byte, auf 0 gesetzt werden sollen.*/
21
22
char read_data()
23
{
24
char rbyte;
25
rbyte = AVR32_GPIO.port[0].pvr;          // Lese PA0-PA7
26
27
return (rbyte);
28
}
29
/* das verunden hab ich weggelassen, weil das rbyte ja ein Char ist und so werden die restlichen bits (PA8-PA31) abgeschnitten.*/

Ich hoffe das konnte man gut verstehen ;).

von Michael (Gast)


Lesenswert?

thanks,

ja WIKI wäre cool :-)

von Michael (Gast)


Lesenswert?

Hallo,

ist das so korrekt?
1
DATA_OUT(x)  AVR32_GPIO.port[1].ovr = ((AVR32_GPIO.port[1].ovr & 0x0003ffff) | ((unsigned long)x << 24));
Aufruf:
1
DATA_OUT(0x1f);


Am Port B liegt dann 0x1f03ffff an.

von Phil S. (zippi)


Lesenswert?

Oh hab garnet gesehen das du geschrieben hast ;).

Aber das ist richtig so sollte an PORTB 0x1f03ffff anliegen.

Was hast du eigentlich für ein Projekt vor??? Wenn ich mal fragen darf.

Es gibt ja leider noch nicht sehr viele UC3 Progger :(.

von 2 Studenten (suchen eine Lösung) (Gast)


Lesenswert?

Wie kann man eigentlich bei einem UC3 von einem PIN lesen (wenn man die 
vordefinierten Funktionen nutzt)?

Es gibt beispielsweise folgendes:
1
test = gpio_get_pin_value(2);
Hinterlegt ist dabei:
1
int gpio_get_pin_value(unsigned int pin)
2
{
3
  volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
4
  return (gpio_port->pvr >> (pin & 0x1F)) & 1;
5
}

Als absoluten µC-Newbies mit rudimentären C-Kenntnissen sagt uns das 
leider gar nichts. Wir munkeln nur, dass dem übergebenen Pin (2) eine 5 
zugeordnet wird (??)

Was wird also genau zugeordnet und ist das die richtige Funktion, um auf 
einem Pin ein anliegendes Stromsignal zu erkennen?

von Michael (Gast)


Lesenswert?

Hi Zippi,

hab jetzt ein LCD angebunden mit 240 x 160.
Freund mich immer mehr mit dem Controller an.
Läuft schon ganz gut.

von Phil S. (zippi)


Lesenswert?

echt cool. Ja wenn man einmal richt drin ist, macht es immer mehr spaß 
;).

Finde den AVR32 echt super. Was für ein board hast du genommen? Kannst 
du mal Bilder von deinem Projekt zeigen und schreiben was noch so genau 
damit vor hast.

mfg

von Phil S. (zippi)


Lesenswert?

Achja zu den beiden Studenten (oder heist du so ;)). Ich kann nur sagen, 
dass das nutzen der vorgefertugten funktionen nicht umbedingt einfacher 
ist und vorallem nicht schneller ;). Aber jeden das seine.

Also das mit den 5 bestimmt nur den port. Der Prozessor(welchen hab ihr 
überhaupt???) hat mehrere PORTs A,B,C,X. Da das framework(also eure 
fertige funktion) so aufgebaut ist das ihr nur den GPIO pin angeben 
müsst, wird der port duch
1
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
bestimmt.

Mit
1
return (gpio_port->pvr >> (pin & 0x1F)) & 1;
wird dann der pin bestimmt. das & 0x1f sorgt dafür das ihr nur maximal 
eine 31 habt, da jeder port nur 31 pins nutzt.

mit gpio_get_pin_value(2); bekommt ihr also den wert von PA2.
Als bespiel fur PB2 müsste man gpio_get_pin_value(34); eingeben ;).

Nach als zusatz info: Ihr musst vorher noch den Pin als eingang setzten 
damit das auch funktioniert.

von 2 studenten (Gast)


Lesenswert?

hab dank zippi!
sind wirklich 2 studenten und haben zu testzwecken n fertiges eval board
uc3a von in-circuit  mit dem uc3a1215-u geholt.
gut zu wissen, dass man vorgefertigte methoden nicht nutzen muss.
dachten, die gehören zur standardbiblo.
weißt du zufällig ob/wo wir vorgefertigte methoden (pvr,ovr,etc.) incl. 
doku als pdf finden können?

mfg

von Phil S. (zippi)


Lesenswert?

Ne leider hab ich auch noch nirgends so eine art doku direct gefunden.

Aber wenn man mal das Kapitel von GPIO im datenblatt durchliest, sollte 
man nach und nach auch die vorgefertigte gpio.c aus dem Framework 
verstehen.

Sonst könnt ihr auch fragen. Weiter oben im thread steht ja auch wie man 
es ohne fertige funktionen macht. Probiert einfach mal rum. Wenn man es 
1x verstanden hat ist es total einfach ;).

Ich werde die tage auch mal mit einer art wiki anfangen und alles 
nochmal genau erklären. Link stell ich dann hier rein.

LG

von 2 studenten (Gast)


Lesenswert?

Na gut,
vielen Dank für die Bemühungen.
Werden uns da schon irgendwie durchwurschteln.

Mfg

von 2 Studenten (Andreas) (Gast)


Lesenswert?

Und natürlich sind wir auf eine Wiki gespannt.
Am liebsten wäre mir wirklich, komplett ohne GPIO auszukommen und eher 
so vorzugehen, wie es im AVR-GCC-Tutorial für die 8Bit-Avrs beschrieben 
ist. Das erscheint mir logischer und universeller.

PS: Unsere geplanten Projekte:
Christian:
- mehrere Spannungen mittels Multiplexer messen (in Brennstoffzellen)

Andreas:
- Temperatur messen, auf Grundlage dessen Lüfter regeln
- über Leistungskurve (Spannung * Strom) einer Brennstoffzelle deren 
Reaktionsluftzufuhr regeln (also Steuersignal für Kompressor ausgeben, 
entweder 1-10V/1-5V oder Servosignal)

Zeitraum zur Bewerkstelligung: 2 Monate ... ihr werdet also öfter von 
uns hören ;-)

Gruß
Andreas

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Ich (Andreas von 2 Studenten) bin jetzt mittlerweile im 
Leuchtdiodenstadium bei den AVR32 angekommen und habe folgendes Problem:
Ich gebe eine hochzählende Zahl zu Testzwecken binär auf Dioden aus, 
allerdings habe ich das Problem, dass bei 1 die Dioden aus sind und bei 
0 an.
Sprich eine 5 wird bei 6 Dioden verkehrt dargestellt, anstatt 000101 
bekomme ich 111010.
Was habe ich im Quelltext falsch gemacht?
Ich habe immer noch ein bißchen Probleme mit den Zuordnungen von Bytes 
und den vorgefertigten GPIO-Befehlen.

Die Zahl läuft nur bis 63 hoch, wegen der 6 Dioden.
1
int main(void)
2
{
3
  U16 zahl=0; //Zähler
4
  U32 i; //you will find this definition of >U32< in driver "compiler.h"
5
6
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
7
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
8
  while(1)
9
  {
10
    if(zahl>=63){
11
      zahl=0;
12
    }
13
    //AVR32_GPIO.port[0].gper = 0xFF;  // GPIO enable-Register
14
    //AVR32_GPIO.port[0].oder = 0xFF;  // GPIO als Ausgang.
15
    AVR32_GPIO.port[0].ovrc = 0xff;
16
    AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
17
    //AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
18
    zahl++;
19
    for(i=0; i<2000; i++); //wait loop
20
21
  }
22
23
}

Mit den durch "//" maskierten Befehlen komme ich auch leider zu keinem 
anderen Ergebnis.

Weitere Frage:
Wie kann ich z.B. folgendes erreichen: 19 ms an Pin 10 kein Signal und 1 
ms Signal (für ein Servosignal)? Irgendwie habe ich in der Doku was von 
den Timern gelesen, scheitere aber schon an der Auswahl der richtigen 
Uhr und bin bei den entsprechenden An- und Ausschaltbits überfragt. 
(Zippi... wir wollen deine WIKI! :D)

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Problem 1 gelöst (invertiertes Blinken):
Es lag an einem Sachverhalt names Sourcing & Sinking, bzw. dem 
Vertauschen.
Ich hatte aus Versehen bei allen Dioden den Widerstand zw. GND und Diode 
anstatt zwischen Pin und Diode. Dadurch floss irgendwie der Strom 
anders.

von Phil S. (zippi)


Angehängte Dateien:

Lesenswert?

HI,

Ja der code an sich sieht schonmal ganz gut aus. Sollte gehen.

Das:
1
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
ist natürlich besser als das:
1
AVR32_GPIO.port[0].ovrc = 0xff;
2
AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand

Einer servo über GPIO mit warte schleifen zu schreiben ist natürlich 
mehr als fusch^^. Und befor ihr zu den Timern bzw ne servo macht man mit 
PWM. Geht solltet ihr anfang die CPU zu initialisieren. Sonst arbeitet 
ihr nur mit dem ungenauen internen tackt. Infos stehen im aktuellem 
Datenblatt auf seite 68. Im kapitel 13.6.1 Mein Clock Control.

Naja aber weil ich mal nicht so bin gibt es von mir auch einen source.
In dem Soucre könnt ihr theoretisch jeden clock einstellen von 6-66Mhz
Praktisch aber nicht weil alles unter 42 nicht mehr ganz spezifisch ist.
Warum das so ist steh im datenblatt (falls ihr lust habt könnt ihr das 
auch anpassen). Gehen tut es aber trozdem. Zusätzlich gehen nur takte 
die durch 6 teilbar sind.
Von mir getestete Clocks:
12/18/24/30/36/42/48/54/60/66/72/78/84/90 Mhz. Haben alle funktioniert. 
Natürlich ist alles über 66 Mhz übertaktung.
Der Source geht nicht mit UES prozessoren. Und ich hab ihn nur auf einem 
UC3A getestet.

PS: Die Wiki muss leider erstmal noch etwas warten da ich noch ein 
vernünftiges Wiki skript suche.

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Hi Phil,

vielen Dank für deine Hilfe!
Mit den Timern werde ich mich wohl erst nächste Woche ausführlicher 
beschäftigen. (Erstmal das entsprechende Kapitel dazu recherchieren und 
deinen Quelltext ansehen.)

Mittlerweile schaffe ich es zumindest auch Signale zu geben. Wie kann 
ich aber erwirken, dass nicht erst nach dem Schleifendurchlauf "test" 
geprüft wird, sondern bei jeder Betätigung sofort eine andere Funktion 
aufgerufen wird?

bisheriger Stand:
1
int main(void)
2
{
3
  Bool test;  //Variable für einen Taster
4
  U16 zahl=0; //Zähler
5
  U32 i; //you will find this definition of >U32< in driver "compiler.h"
6
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
7
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
8
  while(1)
9
  {
10
    if(zahl>=63){
11
      zahl=0;
12
    }
13
    AVR32_GPIO.port[0].ovrc = 0xff;
14
    AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
15
    //AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
16
    zahl++;
17
    for(i=0; i<2000; i++); //wait loop
18
    gpio_enable_gpio_pin(10);
19
    gpio_enable_pin_pull_up(10);
20
    test = gpio_get_pin_value(10);
21
    if(!test){
22
      AVR32_GPIO.port[0].ovrc = 0xff;
23
      AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
24
      for(i=0; i<20000; i++);
25
    }
26
  }
27
}

von Phil S. (zippi)


Lesenswert?

Hehe genau das ist das Problem.
Normal macht man nicht einfach in einem Code eine Schleife die so lange 
dauert und dann noch genau sein soll, deswegen timer ;). Achja mein 
Code(clock.c) hat nichts mit dem Timer zu tun. Da geht es nur um den CPU 
main clock.

Für Timer information im datenblatt ab S. 639 bis S. 672. Ich würde euch 
raten den ganzen Teil auszudrucken und zu lesen. Wenn ihr fragen habt 
einfach Posten.
Doch wenn ihr für den Anfang nur einen Servo Motor ansteuern wollt wäre 
ab S. 673(PWM) besser(viel besser ;)).

Zu euerm Code nochmal

Wenn ihr:
1
      AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
macht, dann braucht ihr vorher nicht
1
AVR32_GPIO.port[0].ovrc = 0xff;
zu machen.

So also um es in der schleife abzufragen muss es einfach in die schleife 
rein. Dann ist die Zeit aber natürlich länger.
1
int main(void)
2
{
3
  Bool test;  //Variable für einen Taster
4
  U16 zahl=0; //Zähler
5
  U32 i; //you will find this definition of >U32< in driver "compiler.h"
6
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
7
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
8
  gpio_enable_gpio_pin(10);
9
  gpio_enable_pin_pull_up(10);
10
11
  while(1)
12
  {
13
    if(zahl>=63){
14
      zahl=0;
15
    }
16
    //AVR32_GPIO.port[0].ovrc = 0xff;
17
    //AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
18
    AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
19
    zahl++;
20
    for(i=0; i<2000; i++) //wait loop
21
    {
22
      test = gpio_get_pin_value(10);
23
      if(!test){
24
        AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
25
        //for(i=0; i<20000; i++);
26
      }
27
    }
28
  }
29
}

Ich hoffe ihr versteht was ich geändert habt.
Achja einen pin kann man auch direct abfragen ohne die GPIO.h.
Geht aber natürlich auch so.

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Hallo Phil,

danke für die Vereinfachung des Quellcodes. Somit springt sozusagen 
früher das "Interrupt" ein (obwohl dafür ja meist eine extra-Routine 
genutzt wird, oder?).

Ich versuche jetzt exemplarisch den PWM.Controller zum laufen zu 
bekommen und testhalber immer von 0 bis Maximum ansteigen zu lassen.

Wollen wir bezüglich der ganzen Thematik ein neues Thema namens first 
steps und try outs auf AVR32 eröffnen? Wäre sicher interessant für 
andere Einsteiger die grundlegenden Sachen auf einem Haufen zu finden 
(wird vielleicht die Beta-Variante der Wiki ;-)).

Gruß
Andreas

von Buddler B. (buddler) Benutzerseite


Lesenswert?

So.. da eben die Bearbeite-Funktion meinen ganzen Text gelöscht hat, 
nochmal in kurzer Form:

Arbeitsschritte PWM:
- im Powermanager die PWM-Clock anschalten (wie geht das?)
Es gibt 13 Uhren, 11 Modulo-Uhren und 2 Linearteiler. Basis ist die 
PWM-Master-Clock (MCK).

In den Header-Files habe ich aber nur folgendes gefunden:
1
/* PWM */
2
#define AVR32_PWM_NUM                      1
3
4
/* PWM */ 
5
#define AVR32_PWM_ADDRESS                  0xFFFF3000
6
#define AVR32_PWM                          (*((volatile avr32_pwm_t*)AVR32_PWM_ADDRESS))
7
#define AVR32_PWM_CLK_PBA                  76
8
#define AVR32_PWM_IRQ                      384
9
#define AVR32_PWM_CHANNEL_LENGTH           0x7
10
#define AVR32_PWM_LINES_MSB                6
11
#define AVR32_PWM_0_PIN                    51
12
#define AVR32_PWM_0_FUNCTION               0
13
#define AVR32_PWM_1_PIN                    52
14
#define AVR32_PWM_1_FUNCTION               0
15
#define AVR32_PWM_2_PIN                    53
16
#define AVR32_PWM_2_FUNCTION               0
17
#define AVR32_PWM_3_PIN                    54
18
#define AVR32_PWM_3_FUNCTION               0
19
#define AVR32_PWM_4_0_PIN                  5
20
#define AVR32_PWM_4_0_FUNCTION             1
21
#define AVR32_PWM_5_0_PIN                  6
22
#define AVR32_PWM_5_0_FUNCTION             1
23
#define AVR32_PWM_4_1_PIN                  59
24
#define AVR32_PWM_4_1_FUNCTION             1
25
#define AVR32_PWM_5_1_PIN                  60
26
#define AVR32_PWM_5_1_FUNCTION             1
27
#define AVR32_PWM_6_PIN                    50
28
#define AVR32_PWM_6_FUNCTION               2

Allerdings nichts, was die Uhr betrifft.

Was bedeutet eigentlich ein Konstrukt vom Typ "(*((volatile 
avr32_pwm_t*)AVR32_PWM_ADDRESS))"? War das etwas mit Pointern? Also an 
Adresse X wird Platz für Datentyp soundso frei gehalten?

So etwas wie avr32_pwm_t oder avr32_gpio_t (also mit t am Ende) liest 
man ja öfter.

Das PWM Enable-Register scheint zum einschalten zusein. Die Struktur ist 
auch im Datenblatt unter 32.7.2 zu sehen, allerdings bewirkt ein
AVR32_PWM.MR...irgendwas gar nichts :-(

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Ok. Mein erster Versuch des Anschaltens wird mit "Undeclared" 
kommentiert. Es hapert an DIVA und PREA.
1
int PWM(void){
2
  AVR32_PWM.MR = (1 << DIVA);
3
  AVR32_PWM.MR = (0000 << PREA);
4
5
6
}

von Phil S. (zippi)


Lesenswert?

OK,

Wegen dem Volatile das steht hier gut beschrieben:
http://www.imb-jena.de/~gmueller/kurse/c_c++/c_volat.html

So nun zu deinen Uhren.
Erstmal sind das keine 13 Uhren die der AVR32 hat sonden Takte bzw 
taktleitungen.

Auf Seite 70 Stehen die einstellungen für die einzelnen Taktleitungen.
Der PWM takt steht im PBAMASK an bit 12. Wichtig zu wissen wäre noch das 
alle Taktleitungen im Reset aktive sind, dass heist dort brauchst du 
erstmal nichts verändern.
Interessant ist aber, dass das abstellen von nicht benötigten Takten bis 
zu 25% Stom sparen kann. Das heist also bei 66Mhz nur 30mA bei einer 
Spannung von 3,3V. Nur so nebenbei ;).

Was du dir noch anschauen solltest ist wie man Register direct 
anspricht. Du benutzt ja meistens immer die GPIO.h oder jetzt die PWM.h. 
Wenn du richtig verstehen wills was du da eigentlich Programmierst oder 
einstellst rate ich dir von dem Framework ab. Hier mal ein paar 
Beispiele wie man direct registern snspricht (der grund aufbau ist immer 
gleich):

GPIO Enable Register: (seite 178)
1
AVR32_GPIO.port[0].gper;

ADC Control Register: (seite 708)
1
AVR32_ADC.cr;

PWM Mode Register: (seite 685)
1
AVR32_PWM.mr

Und so ist es mit jedem Register möglich, dafür brauchst du auch kein 
Header außer der AVR32/io.h. Wenn das zu schnell war wird das nochmal in 
meiner Wiki beschrieben. Die erste Version gibt es dann auch bald.

Ich werde ein neues Thema machen und dann die WIKI erst einmal als PDF 
verfassen und sie dann an ausgewählte Tester schicken. Dann hab ich nen 
Feedback ob das soweit gut zu verstehen war oder nicht. Und kann sie 
verbessern.

So hatte noch vergessen das du es ja schon versucht hast direct 
anzusteuern.
Zur info die Bits haben auch spezielle namen:
DIVA = AVR32_PWM_DIVA_OFFSET;
und
PREA = AVR32_PWM_PREA_OFFSET;.
ps: Das MR bei dem PWM register wird kleingeschrieben.

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Hi Zippi,
vielen Dank mal wieder für deine kompetente Hilfe!
Ich verabschiede mich dann ab heute vom Framework und machs dann auch 
lieber von Grund auf. Genau bei dieser Herangehensweise stellt sich aber 
folgendes Problem:

Phil S. schrieb:
> > Zur info die Bits haben auch spezielle namen:
> DIVA = AVR32_PWM_DIVA_OFFSET;
> und
> PREA = AVR32_PWM_PREA_OFFSET;.
> ps: Das MR bei dem PWM register wird kleingeschrieben.

Woher bekomme ich genau solche Namen? Im Datenblatt steht z.B. beim 
MR-Register (Mode Register) nur DIVA, DIVB usw., sowie darüber Nummern.
Leider aber nichts von AVR32_PWM_DIVA_OFFSET.
Kann ich diese Bits auch einfach über Nummern ansprechen, die evtl. aus 
dem Datenblatt ersichtlich sind? So z.B. bei dem DIVA-Bit wie folgt:

anstelle von
1
AVR32_PWM.MR = (1 << AVR32_PWM_DIVA_OFFSET);
2
AVR32_PWM.MR = (0000 << AVR32_PWM_PREA_OFFSET);
nun
1
AVR32_PWM.MR = (1 << 0);
2
AVR32_PWM.MR = (0000 << 8);
??

Meine ganze Initialisierung sehe dann wie folgt aus:
1
  AVR32_PM.pbamask = (1 << 12); //Enable PWM clock... although it should already be running
2
  AVR32_PWM.mr = (1 << 0); //DIVA set, clock selected by PREA
3
  AVR32_PWM.mr = (0000 << 8); //PREA set, divider  = 1
4
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled

von Buddler B. (buddler) Benutzerseite


Lesenswert?

1
  AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
2
  AVR32_PWM.mr = (1 << 0); //DIVA set, clock selected by PREA
3
  AVR32_PWM.mr = (0000 << 8); //PREA set, divider  = 1
4
  AVR32_PWM.channel[0].cmr = (0101 << 0); //Pre-scaler 1024
5
  AVR32_PWM.channel[0].cmr = (1 << 8); //period center-aligned (calg)
6
  AVR32_PWM.channel[0].cprd = 2303; //visible blinking
7
  AVR32_PWM.channel[0].cdty = 500; //pulsewidth
8
  AVR32_PWM.channel[0].cmr = (1 << 9); //Polarity of output (cpol)
9
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
Ich könnte mir so die Initialisierung vorstellen, kann ich allerdings 
den PWM-Ausgang auf jeden Pin legen? Oder gehen nur bestimmte Pins dafür 
und wie schalte ich die an?
In einem anderen Quellcodebeispiel habe ich folgendes gefunden:
>  AVR32_GPIO.port[0].pmr0c  = Bit(8) | Bit(7); //Function
>  AVR32_GPIO.port[0].pmr1c  = Bit(8) | Bit(7); //0 = PWM.

Im Datenblatt zum Eval-Board steht an Pin 19: 
PB19/PWM_PWM[0]/PM_GCLK[0]/EIM_SCAN[4]... allerdings passiert an diesem 
Pin nichts :-/

von Phil S. (zippi)


Angehängte Dateien:

Lesenswert?

HI,

Also die Namen wie man sie beschreibt stehen nicht direct im datenblatt. 
Habe mir das anfangs im Framework angeschaut und kenne den Aufbau jetzt 
auswendig.
Du kannst natürlich anstatt den namen AVR32_PWM_PREA_OFFSET Auch ne 8 
nehmen. Wenn du mit der Maus über das register gehst siehst du auch, 
dass er es als 8 definiert hat. Als Hilfe kannst du aber auch z.b. 
AVR32_ eingeben und dann Strg + leertaste drücken dann erscheinen alle 
register. Hab hier mal nen bild als beispiel.
Hab grad eben auch nen Servo gesucht, angeschlossen, programmiert und er 
läuft schon ;).

Wo die PWM pins sind, steht auf Seite 45. Da steht z.b. PB19 hat als 
Function A PWM0.
Die Funktionen Wählt man dann mit dem Peripheral Mux Register 1 u 2 aus. 
Da hattest du ja schon den ansatz gezeigt. Wie das genau geht steht auf 
Seite 179
Für PB19 auf Funktion A:
> AVR32_GPIO.port[1].pmr0c  = 1 << 19; //Function
AVR32_GPIO.port[1].pmr1c  = 1 << 19;
Für PB19 auf Funktion D:
> AVR32_GPIO.port[1].pmr0s  = 1 << 19; //Function
> AVR32_GPIO.port[1].pmr1s  = 1 << 19;

Zusätzlich musst du noch den GPIO deaktivieren.
> AVR32_GPIO.port[1].gperc  = 1 << 19;

lg Zippi

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Wieder einen Schritt weiter und die Mux-Register verstanden!

Damit habe ich es geschafft, den PWM-Ausgang anzuschalten und auch eine 
Diode entsprechend blinken zu lassen. Jetzt heißt es nur noch die 
Parameter richtig zu verstehen.

Die Funktion sieht wie folgt aus:
1
void PWM(void)
2
{
3
  U32 j, i;
4
  for(i=0; i<2; i++) //wait loop
5
  {
6
    AVR32_GPIO.port[1].ovrc = 0x0F;
7
    AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
8
    for(j=0; j<2000; j++); //wait loop
9
    AVR32_GPIO.port[1].ovrc = 0x0F;
10
    for(j=0; j<2000; j++); //wait loop
11
  }
12
  for(j=0; j<2000; j++); //wait loop
13
  //AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
14
  for(i=0; i<3; i++) //wait loop
15
    {
16
      AVR32_GPIO.port[1].ovrc = 0x0F;
17
      AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
18
      for(j=0; j<2000; j++); //wait loop
19
      AVR32_GPIO.port[1].ovrc = 0x0F;
20
      for(j=0; j<2000; j++); //wait loop
21
    }
22
  for(j=0; j<2000; j++); //wait loop
23
  AVR32_PWM.mr = (1 << 0); //DIVA set, clock selected by PREA
24
  AVR32_PWM.mr = (0000 << 8); //PREA set, divider  = 1
25
  AVR32_PWM.channel[0].cmr = (0101 << 0); //Pre-scaler 1024
26
  AVR32_PWM.channel[0].cmr = (1 << 8); //period center-aligned (calg)
27
  AVR32_PWM.channel[0].cprd = 23030; //visible blinking
28
  AVR32_PWM.channel[0].cdty = 5000; //Pulsewidth
29
  AVR32_PWM.channel[0].cmr = (1 << 9); //Polarity of output (cpol)
30
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
31
  AVR32_GPIO.port[1].gperc = 1 << 19; // Use PB19 as function, disable setting as a periphal pin
32
  AVR32_GPIO.port[1].pmr0c  = 1 << 19; //Function A (PWM) selected through setting
33
  AVR32_GPIO.port[1].pmr1c  = 1 << 19; //(pmr0c, pmr1c) = 00
34
35
}

>//AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
Musste deaktiviert werden, da danach merkwürdigerweise nichts mehr 
passierte (anhand der Blinkschleife ersichtlich gewesen). Irgendwo 
weiter oben im Thema wurde erwähnt, das die Masterclock bereits läuft, 
doch dann hätte ein weiteres setzen des entsprechenden Registers doch 
nichts bewirken dürfen, oder?

von Phil S. (zippi)


Lesenswert?

Hi,
Ok schon super, dass du verstanden hast wie die PWM funktioniert ;).
Da sind aber noch entscheidende Fehler bei deiner Register Ansteuerung.

Achtung Ganz wichtig:
1. So was wie binäres schreiben in Register geht nicht. z.b.
>>AVR32_PWM.mr = (0000 << 8);
>>AVR32_PWM.channel[0].cmr = (0101 << 0);
Das ist für ihn alles Dezimal, das es bei dir grad passt ist Zufall. 
Also er schreibt dann in cmr 101 rein. Das ist dann in Hex 0x65
Und würde im Register den Teiler auf 0101 stellen aber das macht nur die 
0x5. Die 0x60 schreibt in die oberen Register noch 1010 rein. Was 
zurzeit nicht schlimm ist weil dort keine Funktion steckt.
Besser ist da mit hex zu arbeiten:
>>AVR32_PWM.mr = (0x0 << 8);
>>AVR32_PWM.channel[0].cmr = (0x5 << 0);

2. Das 2. Problem ist, welches auch verursacht, dass bei dem diesem 
Befehl nix mehr geht:
>AVR32_PM.pbamask = (1 << 12);

Du schreibst so quasi 0b00000000000000000001000000000000.
Das Aktiviert den Takt für PWM schon, trozdem(da ja alle taktleitungen 
aktive sind) deaktivierst du alle andern in diesem Register wie z.b. 
GPIO. Also werden deine LEDs auch nicht mehr gehen ;).
Richtig wäre, das man den alten wert mit übernimmt. Beispiel:

>AVR32_PM.pbamask = AVR32_PM.pbamask  | (1 << 12);
Somit wird der alte Wert mit dem neuen verodert.

Das gleiche gilt auch für:
>AVR32_PWM.channel[0].cmr = (0101 << 0); //Pre-scaler 1024
>AVR32_PWM.channel[0].cmr = (1 << 8); //period center-aligned (calg)
>>>AVR32_PWM.channel[0].cprd = 23030; //visible blinking
>>>AVR32_PWM.channel[0].cdty = 5000; //Pulsewidth
>AVR32_PWM.channel[0].cmr = (1 << 9); //Polarity of output (cpol)

Als erstes setzt du den Pre-scaler und im 2. Moment wird der Pre-scaler 
wirder gelöscht und nur setzt du das CALG bit. Als 3.(an 5. stelle) 
löscht du wieder das ganze register und setzt nur das CPOL bit.

Quasi macht dein ganzes Programm in echt:
1
void PWM(void)
2
{
3
  U32 j, i;
4
  for(i=0; i<2; i++) //wait loop
5
  {
6
    AVR32_GPIO.port[1].ovrc = 0x0F;
7
    AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
8
    for(j=0; j<2000; j++); //wait loop
9
    AVR32_GPIO.port[1].ovrc = 0x0F;
10
    for(j=0; j<2000; j++); //wait loop
11
  }
12
  for(j=0; j<2000; j++); //wait loop
13
  //AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
14
  for(i=0; i<3; i++) //wait loop
15
    {
16
      AVR32_GPIO.port[1].ovrc = 0x0F;
17
      AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
18
      for(j=0; j<2000; j++); //wait loop
19
      AVR32_GPIO.port[1].ovrc = 0x0F;
20
      for(j=0; j<2000; j++); //wait loop
21
    }
22
  for(j=0; j<2000; j++); //wait loop
23
  
24
  AVR32_PWM.mr = (0x0 << 8); //PREA set, divider  = 1
25
  
26
  
27
  AVR32_PWM.channel[0].cprd = 23030; //visible blinking
28
  AVR32_PWM.channel[0].cdty = 5000; //Pulsewidth
29
  AVR32_PWM.channel[0].cmr = (1 << 9); //Polarity of output (cpol)
30
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
31
  AVR32_GPIO.port[1].gperc = 1 << 19; // Use PB19 as function, disable setting as a periphal pin
32
  AVR32_GPIO.port[1].pmr0c  = 1 << 19; //Function A (PWM) selected through setting
33
  AVR32_GPIO.port[1].pmr1c  = 1 << 19; //(pmr0c, pmr1c) = 00
34
35
}

Versuch es also mal richtig einzustellen. Du kannst auch mehrere Bits 
verodern, so setzt du alle Bits gleichzeitig.
1
AVR32_PWM.channel[0].cmr = (0x5 << 0) | (1 << 8) | (1 << 9); //Polarity of output (cpol)

Gruß Zippi

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Oh weh. Danke für die Korrektur solcher grundsätzlicher Fehler!

Wenn mich meine Informatikkenntnisse nicht täuschen, kann ich ja keine 0 
verodern. Sprich: Wie ordne ich dann eigentlich eine 0 sauber zu?
>AVR32_PWM.channel[0].cmr = AVR32_PWM.channel[0].cmr | (0 << 8); //period 
left-aligned (calg)
dürfte ja eigentlich nicht funktionieren?

Des Weiteren: Ich habe jetzt ein Servosignal mit den richtigen "Abmaßen" 
erzeugt. Die typischen Servoanschlüsse sind meist 3-polig und haben 
plus, minus und Servosignal. Ich habe Minus mit Mirkocontroller-, bzw. 
Boardmasse verbunden und Signal mit dem PWM-Ausgang. Es liegen aber 
bereits 5 Volt am Stecker bei plus (des Servoanschlusses)an?!
Daher habe ich mir nicht getraut, diese Leitung mit irgendwas (z.B. bei 
Vin des µC-Boards (wenn der über USB versorgt wird, liegen dort 4,8 V)) 
zu verbinden. Wird ein Servotester angeschlossen, funktionierts (der 
wird dann anscheinend über die +-Leitung versorgt), mit dem UC3 aber 
nicht.
:-/

Kann ich gefahrlos die 5V des Servoanschlusses auf die 4,8 V von Vin 
legen?
Ist das Servosignal vielleicht mit 3,3V zu schwach?

PS: @Zippi: Hurra! Morgen wird die Baustelle ADC aufgerissen. Wir warten 
sehnlichst auf deine Wiki :D

von Phil S. (zippi)


Lesenswert?

HI,

Ja du kannst den Servo auf deine 4,8V legen. Und die Spannung ist die 
USB Spannung. Also mein Servo funktioniert. Und ich hab das Kabel an VCC 
gemacht, also 3,3V.

Wegen dem verodern. Beim start sind die meisten Register auf 0 gesetzt, 
und so musst du eigentlich nur die 1 setzen welche du brauchst.

Wenn du doch ein Register hast welches du auf 0 setzen willst kannst du 
es mit einer oder und Invertierung machen.
In dem Beispiel wird das 8bit auf 0 gesetzt.

>AVR32_PWM.channel[0].cmr = AVR32_PWM.channel[0].cmr &(~(1 << 8));

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Ich habe eben folgendes ausprobiert:
Vom Servokabel mit Minus auf GND des Mikrocontrollers, mit Plus auf Vin 
und mit Signal auf den PWM-Pin. Bei hoch und runter laufendem Signal 
(1-2 ms) passiert nichts. Dann habe ich das Signal fest auf 1,53 ms 
eingestellt, mit dem Effekt, dass der Motor für ca. 10 s lief, danach 
Abschaltung. Tests mit anderen Signalbreiten (1,3 ms; 1,8 ms) ergaben 
KEIN Anlaufen.

Weiterer Nebeneffekt: Ich habe einen funktionierenden PWM-Pin weniger 
:'-(
Einen Widerstand vergessen? Oder woran könnte es gelegen haben? Wie hast 
du deinen Servo richtig angeschlossen?
Ich habe nochmal nachgemessen: auf plus vom Servo liegen 5,8 V an, d.h. 
auch am UC3 zwischen Vin und GND 5,8 V.

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Retourkutsche: Der PWM-Pin ist nicht hinüber, aber der Motor nun, da ich 
durch mein "Vollgas-Signal" das Steuerteil vom Motor in den 
Programmiermodus gebracht habe und anscheinend auch etwas umprogrammiert 
(YGE 40 von YGE, Motor: 1010er Serie von Lehner-Motoren-Technik, bis 
100000 1/min). Der Motor reagiert nur noch mit Zucken.

Trotzdem ist die PWM-Programmiererei dank Zippi erstmal erfolgreich und 
zumindest ein PWM-Lüfter lässt sich nun anstandslos regeln.

Damit geht das sorglose Gefrage eines Anfängers aber weiter, denn es 
soll ein Temperatursignal eingelesen werden. Daher ist das An- und 
Ausschalten und richtige Auslesen des ADC wichtig.

Aus dem Framework lässt leider wieder nicht genau erkennen, wie sich 
analog zur PWM auch der ADC bedienen lässt.
Mein ansatzweiser Quellcode sieht daher wie folgt aus:
Ist eigentlich
>AVR32_GPIO.port[0].puers |= (1 << 21);
dasselbe wie
>AVR32_GPIO.port[0].puers =  AVR32_GPIO.port[0].puers | (1 << 21);
1
void ADC(void)
2
{
3
  int value = 0;
4
  volatile avr32_adc_t *adc = &AVR32_ADC;
5
  AVR32_GPIO.port[0].gperc = AVR32_GPIO.port[0].gperc | (1 << 21); // Use PA21 as function, disable setting as a periphal pin
6
  AVR32_GPIO.port[0].pmr0c  = AVR32_GPIO.port[0].pmr0c | (1 << 21); //Function A (ADC) selected through setting
7
  AVR32_GPIO.port[0].pmr1c  = AVR32_GPIO.port[0].pmr1c | (1 << 21); //(pmr0c, pmr1c) = 00
8
  AVR32_GPIO.port[0].puers |= (1 << 21); //enable pull up resistor
9
  /* enable channel for sensor */
10
  adc_enable( adc, 0 );
11
  // start conversion
12
  adc_start( adc );
13
  // get value for sensor
14
  value = adc_get_value( adc, 0 );
15
  /* Disable channel for sensor */
16
  adc_disable( adc, 0 );
17
18
}

von Phil S. (zippi)


Lesenswert?

Hi,

Ja das ist genau das selbe, nur in kurz vorm geschrieben.
>AVR32_GPIO.port[0].puers |= (1 << 21);
=
>AVR32_GPIO.port[0].puers = AVR32_GPIO.port[0].puers | (1 << 21);

Für ADC gilt dasselbe wie für PWM und alle anderen Peripherien.
Erst Datenblatt teil lesen, dann die Register versuchen zu verstehen und 
wenn man nicht weiter kommt kann man mal ins Framework schauen ;).

Ich würde dir aber erstmal Raten die an Die Main clock zu setzen, damit 
du mal eine vernünftige CPU clock hast. Dann lässt sich auch PWM genauer 
einstellen.

Wegen dem Servo noch mal... Hoch und runter = 1-2ms?
Eine Periode muss immer 20ms haben.
Ich hoffe du weist wie ein Servo richtig funktioniert?
http://www.flugleiter.de/rc/servo

Gruß

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Servo wurde soweit verstanden: 20 ms, 1-2 ms davon das Servosignal. Das 
Problem war wie gesagt, dass der Motorregler aus dem Modellbau kommt und 
so eingestellt ist, dass Vollgas bei Start (2 ms Signal) den 
Programmiermodus öffnen.

Wegen der Main Clock: Ich arbeite zur Zeit mit 115kHz. Sind die anderen 
Varianten günstiger?
MCSEL: Main Clock Select
0: The slow clock is the source for the main clock
1: Oscillator 0 is source for the main clock
2: PLL0 is source for the main clock

(PS: Bald ist Wochenende, da verschone ich dich mal mit 
Löcher-in-den-Bauch-fragen ;-) )

Nur eine letzte Frage noch:
Was bedeutet dieser Befehl:
>volatile avr32_adc_t *adc = &AVR32_ADC;
Es wird ein Objekt der Klasse avr32_adc_t erzeugt, und zwar an der 
Adresse von AVR32_ADC? Oder Was bedeuten dort "*" und "&"?

von Phil S. (zippi)


Lesenswert?

OK,

Ja du arbeitest zurzeit mit 115khz und das sogar sehr ungenaue 115khz.
Dazu kann der AVR32 mehr als 500x so schnell laufen wenn du ihn 
einstellst und das auch noch sehr genau.
Wenn du MCSEL auf 1 stellst Hast du den Oszillator. Also dein Quarz auf 
dem Board. Der liegt bei 12Mhz wenn ich mich nicht täusche. Das wäre 
schon mal ein Anfang.

Beim dem ADC Pointer bin ich mir nicht ganz sicher, da ich wie gesagt 
nicht mit dem Framework arbeite. Aber ich denke das er sich da nur die 
Adresse von den ADC Register holt.

Gruß

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Ich habe jetzt probiert den ADC-Pin zum laufen zu bekommen, habe jetzt 
aber das Problem, dass sich der µC anscheinend aufhängt.
1
int main(void)
2
{
3
  Bool test, direction = TRUE;  //Variable für einen Taster
4
  unsigned long zahl=252; //ADC-Value
5
  U32 i, pulsewidth = 0, pulsewidth2 = 0, pulsewidthstep = 1; //you will find this definition of >U32< in driver "compiler.h"
6
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
7
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
8
  AVR32_GPIO.port[1].gpers = 0x0F;  // GPIO enable Register
9
  AVR32_GPIO.port[1].oders = 0x0F;  // GPIO als ausgang.
10
  AVR32_GPIO.port[0].ovrc = 0xff;
11
  AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
12
  for(i=0; i<15000; i++);
13
  ADC_INIT();
14
...
An dieser Stelle wird ADC_INIT() aufgerufen. Die for-Schleife ist nur 
für ein paar Dioden zur Ausgabe der "zahl".
Wird die Funktion ADC_INIT aufgerufen, steigt der µC aus.
1
void ADC_INIT(void)
2
{
3
  AVR32_GPIO.port[0].gperc = AVR32_GPIO.port[0].gperc | (1 << 21); // Use PA21 as function, disable setting as a periphal pin
4
  AVR32_GPIO.port[0].pmr0c  = AVR32_GPIO.port[0].pmr0c | (1 << 21); //Function A (ADC) selected through setting
5
  AVR32_GPIO.port[0].pmr1c  = AVR32_GPIO.port[0].pmr1c | (1 << 21); //(pmr0c, pmr1c) = 00
6
  AVR32_GPIO.port[0].puers |= (1 << 21); //enable pull up resistor
7
  AVR32_ADC.mr |= (1 << 4); //LOWRES bit set, 8 bit resolution
8
  int zahl = 111, i=0;
9
  AVR32_GPIO.port[0].ovrc = 0xff;
10
  AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
11
  for(i=0; i<15000; i++);
12
}
Anhand der Dioden ist sichtbar, dass die for-Schleife nicht erreicht 
wird. :-/
Wer sieht den Fehler?

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Der Aussteig geschieht schon an der ersten Zeile der Funktion ADC_INIT:
>AVR32_GPIO.port[0].gperc = AVR32_GPIO.port[0].gperc | (1 << 21); // Use PA21 as 
function, disable setting as a periphal pin

Habe ich etwas vergessen?

von Phil S. (zippi)


Lesenswert?

HI,

Also du hast da noch ein Verständnis Problem.
Das
>AVR32_GPIO.port[0].gper
ist das Register an sich.
Mit dem c oder s dahinter macht er quasi die Veroderung automatisch.
1
AVR32_GPIO.port[0].gper = AVR32_GPIO.port[0].gper | (1 << 21);
Ist das gleiche wie:
1
AVR32_GPIO.port[0].gpers = (1 << 21);
Dieses s oder c oder t sind Zusatz Funktionen welche nur die GPIO 
bieten, deswegen musst du die Veroderung bei andern Registern machen, 
bei den GPIO aber nicht. So steht auch im Datenblatt auf Seite 175, dass 
das AVR32_GPIO.port[0].gper ein read/write Register ist.
Aber das AVR32_GPIO.port[0].gperc ein write only Register.
Da du es aber liest stürzt er wohl ab.

Gruß

von Buddler B. (buddler) Benutzerseite


Lesenswert?

Erübrigt sich eine Veroderung bei Write-only-Registern generell, d.h. 
beispielsweise immer
>AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
anstatt
>AVR32_PWM.ena |= (1 << 0); //PWM for channel 0 enabled?

Ersteres bewirkt auch nicht, dass aus ena: 1101000 danach 0000001 wird?

von Phil S. (zippi)


Lesenswert?

Jop genau da hast du recht.
Das 2. wird auch nicht funktionieren da beim lesen eines Write-only 
Registers die MCU meistens abstürzt.

gruß

von Markus (Gast)


Lesenswert?

Hallo,

ich arbeite mich auch gerade in die Welt der 32 Bit Controller. Für den 
Anfang war das hier schon einmal gut aber gibt es mittlerweile ein Wiki? 
Ich habe nichts gefunden wo drin steht, was z.B. die ganzen Abkürzungen 
wie gpers bzw oders bedeuten. Von daher ist die ganze Sache nicht ganz 
so trivial und die Beispiele im AVRStudio 5 helfen nur bedingt 
weiter....

von adsd (Gast)


Lesenswert?

Markus schrieb:
> Ich habe nichts gefunden wo drin steht, was z.B. die ganzen Abkürzungen
> wie gpers bzw oders bedeuten.

Na, das sind Abkürzungen für Bits/Register usw. aus den Datenblättern. 
Eine kurze Suche im Datenblatt ergab z.B. für ODERS:

 0x44 Output Driver Enable Register Set

von Markus (Gast)


Lesenswert?

Ja war mein Fehler. Hatte das falsche Datenblatt....
Hab das soweit auch alles geschafft was ich wollte und nun gehts an SPI. 
Hab da auch schon einige Besipiele gefunden aber das ist mir auch wieder 
recht unklar. Bei den 8 Bit Controllern fand ich das alles 
übersichtlicher....

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.