www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR32UC3A Port setzen


Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie definiert man beim AVR32 die Ports???

Beim Atmega
// Ports
#define LCD_CMD_PORT    PORTA    // Command Output Register
#define LCD_CMD_DIR      DDRA    // Data Direction Register for Command Port

#define LCD_DATA_IN      PINC    // Data Input Register
#define LCD_DATA_OUT    PORTC    // Data Output Register
#define LCD_DATA_DIR    DDRC    // Data Direction Register for Data Port

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

Gruß Michael

Autor: Marius Wensing (mw1987)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hans Wurst (hans_wurst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Zippi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zippi,

ok, das ist soweit klar.

Und mit gpio.h sollte es so aussehen oder?
#define EN_PIN   0
#define ENABLE_LOW     gpio_clr_gpio_pin(EN_PIN);
#define ENABLE_HIGH     gpio_set_gpio_pin(EN_PIN);

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?

Autor: Zippi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define EN_PIN   0
#define ENABLE_LOW     gpio_clr_gpio_pin(EN_PIN);
#define ENABLE_HIGH     gpio_set_gpio_pin(EN_PIN);

gpio_enable_gpio_pin(EN_PIN);

Wobei ich sagen muss das der GPIO mit jedem
gpio_set_gpio_pin(unsigned int pin);
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.
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| byte);
Damit würdest du das byte parralel an PA0 - PA7 legen.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank für die gute Erklärung

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe noch andere Unklarheiten:

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

Autor: Zippi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).
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.
void data_port_output_init()
{
AVR32_GPIO.port[0].gpers = 0x000000ff;     // Activiert PA0-PA7
AVR32_GPIO.port[0].oders = 0x000000ff;     // setzt PA0-PA7 als ausgang
}
/*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.*/

void data_port_input_init()
{
AVR32_GPIO.port[0].gpers = 0x000000ff;    // Activiert PA0-PA7
AVR32_GPIO.port[0].oderc = 0x000000ff;    // setzte PA0-PA7 als eingang
AVR32_GPIO.port[0].puers = 0x000000ff;    // Activiert Pull-up für PA0-PA7
}


void send_data(char byte)
{
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| byte);
}
/*Hier habe ich die s (set) function nicht genutzt, weil die bits welche 0 sind, im daten byte, auf 0 gesetzt werden sollen.*/

char read_data()
{
char rbyte;
rbyte = AVR32_GPIO.port[0].pvr;          // Lese PA0-PA7

return (rbyte);
}
/* 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 ;).

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
thanks,

ja WIKI wäre cool :-)

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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


Am Port B liegt dann 0x1f03ffff an.

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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 :(.

Autor: 2 Studenten (suchen eine Lösung) (Gast)
Datum:

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

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

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?

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
bestimmt.

Mit
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.

Autor: 2 studenten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: 2 studenten (Gast)
Datum:

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

Mfg

Autor: 2 Studenten (Andreas) (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
int main(void)
{
  U16 zahl=0; //Zähler
  U32 i; //you will find this definition of >U32< in driver "compiler.h"

  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
  while(1)
  {
    if(zahl>=63){
      zahl=0;
    }
    //AVR32_GPIO.port[0].gper = 0xFF;  // GPIO enable-Register
    //AVR32_GPIO.port[0].oder = 0xFF;  // GPIO als Ausgang.
    AVR32_GPIO.port[0].ovrc = 0xff;
    AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
    //AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
    zahl++;
    for(i=0; i<2000; i++); //wait loop

  }

}

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)

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Phil S. (zippi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
HI,

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

Das:
AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
ist natürlich besser als das:
AVR32_GPIO.port[0].ovrc = 0xff;
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.

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
int main(void)
{
  Bool test;  //Variable für einen Taster
  U16 zahl=0; //Zähler
  U32 i; //you will find this definition of >U32< in driver "compiler.h"
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
  while(1)
  {
    if(zahl>=63){
      zahl=0;
    }
    AVR32_GPIO.port[0].ovrc = 0xff;
    AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
    //AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
    zahl++;
    for(i=0; i<2000; i++); //wait loop
    gpio_enable_gpio_pin(10);
    gpio_enable_pin_pull_up(10);
    test = gpio_get_pin_value(10);
    if(!test){
      AVR32_GPIO.port[0].ovrc = 0xff;
      AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
      for(i=0; i<20000; i++);
    }
  }
}

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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:
      AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
macht, dann braucht ihr vorher nicht
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.
int main(void)
{
  Bool test;  //Variable für einen Taster
  U16 zahl=0; //Zähler
  U32 i; //you will find this definition of >U32< in driver "compiler.h"
  AVR32_GPIO.port[0].gpers = 0xFF;  // GPIO enable Register
  AVR32_GPIO.port[0].oders = 0xFF;  // GPIO als ausgang.
  gpio_enable_gpio_pin(10);
  gpio_enable_pin_pull_up(10);

  while(1)
  {
    if(zahl>=63){
      zahl=0;
    }
    //AVR32_GPIO.port[0].ovrc = 0xff;
    //AVR32_GPIO.port[0].ovrs  = zahl;  // GPIO-Zustand
    AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| zahl);
    zahl++;
    for(i=0; i<2000; i++) //wait loop
    {
      test = gpio_get_pin_value(10);
      if(!test){
        AVR32_GPIO.port[0].ovr = ((AVR32_GPIO.port[0].ovr & 0xffffff00)| 5);
        //for(i=0; i<20000; i++);
      }
    }
  }
}

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.

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
/* PWM */
#define AVR32_PWM_NUM                      1

/* PWM */ 
#define AVR32_PWM_ADDRESS                  0xFFFF3000
#define AVR32_PWM                          (*((volatile avr32_pwm_t*)AVR32_PWM_ADDRESS))
#define AVR32_PWM_CLK_PBA                  76
#define AVR32_PWM_IRQ                      384
#define AVR32_PWM_CHANNEL_LENGTH           0x7
#define AVR32_PWM_LINES_MSB                6
#define AVR32_PWM_0_PIN                    51
#define AVR32_PWM_0_FUNCTION               0
#define AVR32_PWM_1_PIN                    52
#define AVR32_PWM_1_FUNCTION               0
#define AVR32_PWM_2_PIN                    53
#define AVR32_PWM_2_FUNCTION               0
#define AVR32_PWM_3_PIN                    54
#define AVR32_PWM_3_FUNCTION               0
#define AVR32_PWM_4_0_PIN                  5
#define AVR32_PWM_4_0_FUNCTION             1
#define AVR32_PWM_5_0_PIN                  6
#define AVR32_PWM_5_0_FUNCTION             1
#define AVR32_PWM_4_1_PIN                  59
#define AVR32_PWM_4_1_FUNCTION             1
#define AVR32_PWM_5_1_PIN                  60
#define AVR32_PWM_5_1_FUNCTION             1
#define AVR32_PWM_6_PIN                    50
#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 :-(

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Mein erster Versuch des Anschaltens wird mit "Undeclared" 
kommentiert. Es hapert an DIVA und PREA.
int PWM(void){
  AVR32_PWM.MR = (1 << DIVA);
  AVR32_PWM.MR = (0000 << PREA);


}

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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)
AVR32_GPIO.port[0].gper;

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

PWM Mode Register: (seite 685)
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.

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
AVR32_PWM.MR = (1 << AVR32_PWM_DIVA_OFFSET);
AVR32_PWM.MR = (0000 << AVR32_PWM_PREA_OFFSET);
nun
AVR32_PWM.MR = (1 << 0);
AVR32_PWM.MR = (0000 << 8);
??

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

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
  AVR32_PWM.mr = (1 << 0); //DIVA set, clock selected by PREA
  AVR32_PWM.mr = (0000 << 8); //PREA set, divider  = 1
  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 = 2303; //visible blinking
  AVR32_PWM.channel[0].cdty = 500; //pulsewidth
  AVR32_PWM.channel[0].cmr = (1 << 9); //Polarity of output (cpol)
  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 :-/

Autor: Phil S. (zippi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
void PWM(void)
{
  U32 j, i;
  for(i=0; i<2; i++) //wait loop
  {
    AVR32_GPIO.port[1].ovrc = 0x0F;
    AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
    for(j=0; j<2000; j++); //wait loop
    AVR32_GPIO.port[1].ovrc = 0x0F;
    for(j=0; j<2000; j++); //wait loop
  }
  for(j=0; j<2000; j++); //wait loop
  //AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
  for(i=0; i<3; i++) //wait loop
    {
      AVR32_GPIO.port[1].ovrc = 0x0F;
      AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
      for(j=0; j<2000; j++); //wait loop
      AVR32_GPIO.port[1].ovrc = 0x0F;
      for(j=0; j<2000; j++); //wait loop
    }
  for(j=0; j<2000; j++); //wait loop
  AVR32_PWM.mr = (1 << 0); //DIVA set, clock selected by PREA
  AVR32_PWM.mr = (0000 << 8); //PREA set, divider  = 1
  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)
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
  AVR32_GPIO.port[1].gperc = 1 << 19; // Use PB19 as function, disable setting as a periphal pin
  AVR32_GPIO.port[1].pmr0c  = 1 << 19; //Function A (PWM) selected through setting
  AVR32_GPIO.port[1].pmr1c  = 1 << 19; //(pmr0c, pmr1c) = 00

}

>//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?

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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:
void PWM(void)
{
  U32 j, i;
  for(i=0; i<2; i++) //wait loop
  {
    AVR32_GPIO.port[1].ovrc = 0x0F;
    AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
    for(j=0; j<2000; j++); //wait loop
    AVR32_GPIO.port[1].ovrc = 0x0F;
    for(j=0; j<2000; j++); //wait loop
  }
  for(j=0; j<2000; j++); //wait loop
  //AVR32_PM.pbamask = (1 << 12); //Enable PWM clock
  for(i=0; i<3; i++) //wait loop
    {
      AVR32_GPIO.port[1].ovrc = 0x0F;
      AVR32_GPIO.port[1].ovrs  = 2;  // GPIO-Zustand
      for(j=0; j<2000; j++); //wait loop
      AVR32_GPIO.port[1].ovrc = 0x0F;
      for(j=0; j<2000; j++); //wait loop
    }
  for(j=0; j<2000; j++); //wait loop
  
  AVR32_PWM.mr = (0x0 << 8); //PREA set, divider  = 1
  
  
  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)
  AVR32_PWM.ena = (1 << 0); //PWM for channel 0 enabled
  AVR32_GPIO.port[1].gperc = 1 << 19; // Use PB19 as function, disable setting as a periphal pin
  AVR32_GPIO.port[1].pmr0c  = 1 << 19; //Function A (PWM) selected through setting
  AVR32_GPIO.port[1].pmr1c  = 1 << 19; //(pmr0c, pmr1c) = 00

}

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

Gruß Zippi

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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));

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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);
void ADC(void)
{
  int value = 0;
  volatile avr32_adc_t *adc = &AVR32_ADC;
  AVR32_GPIO.port[0].gperc = AVR32_GPIO.port[0].gperc | (1 << 21); // Use PA21 as function, disable setting as a periphal pin
  AVR32_GPIO.port[0].pmr0c  = AVR32_GPIO.port[0].pmr0c | (1 << 21); //Function A (ADC) selected through setting
  AVR32_GPIO.port[0].pmr1c  = AVR32_GPIO.port[0].pmr1c | (1 << 21); //(pmr0c, pmr1c) = 00
  AVR32_GPIO.port[0].puers |= (1 << 21); //enable pull up resistor
  /* enable channel for sensor */
  adc_enable( adc, 0 );
  // start conversion
  adc_start( adc );
  // get value for sensor
  value = adc_get_value( adc, 0 );
  /* Disable channel for sensor */
  adc_disable( adc, 0 );

}

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 "&"?

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Buddler B. (buddler) Benutzerseite
Datum:

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

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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.
AVR32_GPIO.port[0].gper = AVR32_GPIO.port[0].gper | (1 << 21);
Ist das gleiche wie:
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ß

Autor: Buddler B. (buddler) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Phil S. (zippi)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: adsd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.