Forum: Mikrocontroller und Digitale Elektronik dsPIC33E - ADC und DMA


von Florian T. (florian_t91)


Angehängte Dateien:

Lesenswert?

Nachdem mein PIC jetzt läuft bin ich dabei den ADC in Gang zu setzen.
Ziel ist es 2 Eingänge auszulesen, per DMA in den Speicher zu schreiben 
und dann per UART an den PC zu senden.
Die ersten Versuche klappen schon ganz gut, als ich dann aber versucht 
hab die zwei Kanäle von einander zu trennen hat das nicht mehr ganz so 
geklappt.
Also habe ich mich näher damit beschäftigt und habe jetzt ein 
Verständnisproblem mit dem DMA.

Der angehängte C-Datei zeigt die relevanten Stellen.
Gedacht ist, dass ich den ADC aktiviere und sobald das erstemal der DMA 
Interrupt aufgerufen wird, wieder deaktiviert wird und die Daten 
gesendet.

Nachdem ich das Datasheet gelesen hab würde ich sagen, der Interrupt 
nach 256 (NUMSAMP) Messungen aufgerufen. Komischerweiße kommen am PC 
aber nur 8 Byte an (statt 512). Was ich allein schon durch meine 
sendADC() Routine seltsam finde.
1
void sendADC( __eds__ uint16_t* buff ) {
2
  uint16_t i;
3
4
  for( i = 0; i < NUMSAMP; ++i ) {
5
    uint8_t first = (uint8_t) (( buff[i] >> 8 ) & 0x03 );
6
    putcUART1( first );
7
8
    uint8_t second = (uint8_t) buff[i];
9
    putcUART1( second );
10
  }
11
}

In den Buffern sollten doch eigentlich abwechselnd die Werte von 
Channel0 und Channel1 liegen?

MfG
Florian

von Bronco (Gast)


Lesenswert?

Bist Du sicher, daß das richtig ist?
1
  DMA0STAL = (uint16_t) &buffA;
2
  DMA0STAH = (uint16_t) &buffA;
3
  DMA0STBL = (uint16_t) &buffB;
4
  DMA0STBH = (uint16_t) &buffB;


Bei mir sieht das in etwa so aus:
1
DMA0STA = __builtin_dmaoffset(&buffA);
2
DMA0STB = __builtin_dmaoffset(&buffB);

von Florian T. (florian_t91)


Lesenswert?

Im Beispiel von Microchip (an dem ich mich orientiert hab) steht 
folgendes:
1
  #ifdef _HAS_DMA_
2
  DMA0STAL = __builtin_dmaoffset(&BufferA);
3
  DMA0STAH = __builtin_dmapage(&BufferA);
4
5
  DMA0STBL = __builtin_dmaoffset(&BufferB);
6
  DMA0STBH = __builtin_dmapage(&BufferB);
7
  #else
8
  DMA0STAL = (unsigned int)&BufferA;
9
  DMA0STAH = (unsigned int)&BufferA;
10
11
  DMA0STBL = (unsigned int)&BufferB;
12
  DMA0STBH = (unsigned int)&BufferB;
13
  #endif

Da laut MPLAB X IDE bei mir kein HAS_DMA definiert ist, geh ich davon 
aus.
Auserdem sind ja meine empfangenen Werte kein völliger Mist.

Aber danke für die Anregung.

Habe es momentan ohne DMA per Interrupt gelöst. DMA wäre natürlich 
schöner.

MfG
Florian

PS:
Das nächste Problem ist, das in ADC1BUFF immer 0 drin steht, was aber 
nicht stimmt. Alle anderen ADC1BUFx sind (vermutlich) korrekt.
Nutze:
1
AD1CON2bits.SMPI = 15;
 Soll laut Datenblatt nach jedem 16 Sample/Conversion Vorgang einen 
Interrupt auslösen. In diesem send ich dann den kompletten Puffer.

von Bronco (Gast)


Lesenswert?

Ich weiß jetzt nicht wie es beim dsPIC33E ist, aber bei im Datenblatt 
vom dPIC33F steht, daß er entweder
- DMA und einen Puffer (ADC1BUF0)
oder
- kein DMA und 16 Puffer (ADC1BUF0..F)
hat.

Insofern bin ich doch etwas verwundert, daß Du 16 Puffer und DMA hast?
Ist das beim dsPIC33E wirklich anders als beim F?

von Koch (Gast)


Lesenswert?

1
   __builtin_dmaoffset(const int *)

Muss rein. Ausser Microchip hat den DMA kommplett neu gemacht, beim 
Wechsel von der F zur E-Serie, was ich nicht glaube.

von Florian T. (florian_t91)


Lesenswert?

Also so wie ich das Datenblatt verstanden habe, ist beides vorhanden. 
DMA und 16 Puffer. Wobei entweder DMA und ADC1BUF0 oder 1-16 Puffer 
verwendet werden können.

Was das
1
__builtin
 angeht. Wie gesagt der obige Ausschnitt stammt aus dem entsprechenden 
Codebeispiel von microchip. Und meine IDE sagt mir, dass es nicht 
verwendet wird.

von Florian K. (florian_k89)


Lesenswert?

Muss gestehen das ich die dsPIC E Serie nicht so gut kenne.
Aber wie ich das verstehe wird mit HAS_DMA geprüft ob überhaupt ein 
DMA_Controller auf dem Chip vorhanden ist. Der DMA Speicher liegt in 
einem gesondertem Bereich des RAMS.
Das System läuft so. Im Code deklarierst du eine Variable BufferA. Die 
liegt dann im RAM und die Adresse liegt im Adressraum des RAMS. Da aber 
der DMA wo anders liegt bzw. einen anderen Adressraum hat brauchst du 
noch den Offset und die Page. Offset und Page da der gesamte Adressraum 
beim dspIC 24Bit hat, aber die Grösse aller Register nur 16Bit ist.
Wie gesagt ich beziehe mich nur auf den dsPICF. Wie ich MICROCHIP kenne
haben die den DMA-Controller vom F zum E nicht grundlegend geändert.
Als Beispiel sind die ADCs beim dsPIC30 genauso wie beim dsPIC33F.
Sollten die es doch geändert haben, dann vergiss alles was ich gepostet 
habe.
Ach so, Koch ist auch mein Beitrag.

von Florian T. (florian_t91)


Lesenswert?

Aber ohne DMA Controller wären ja auch die ganzen DMA Register nicht 
vorhanden?

von Florian K. (florian_k89)


Lesenswert?

Guter Punkt.
Kannst bitte deinen genauen dsPIC33E Typen posten.
jetzt will ich es genau wissen. :)

von Bronco (Gast)


Lesenswert?

Vom dsPIC33F zum dsPIC33E hat sich doch einiges geändert:
http://ww1.microchip.com/downloads/en/DeviceDoc/70637D.pdf

- Es gibt kein dediziertes DMA-RAM mehr, sondern DMA kann ins ganze RAM 
erfolgen
- Es gibt mehr RAM, daher reicht ein 16Bit-Register für DMAxSTA/DMAxSTB 
nicht mehr aus
- Der ADC hat tatsächlich sowohl DMA als auch 16 Puffer

von Controllerbezeichnung (Gast)


Lesenswert?

Florian K. schrieb:
> Kannst bitte deinen genauen dsPIC33E Typen posten.

dsPIC33EP 512MU810

von Florian K. (florian_k89)


Lesenswert?

Ok Asche auf mein Haupt

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.