Forum: Mikrocontroller und Digitale Elektronik dsPIC33E Probleme mit ADC/DMA


von Marc H. (hagy)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich möchte einen DSPIC33EP512MU810 nutzen, um mehrere analoge Eingänge 
einzulesen und schließlich PWM Signale zu erzeugen. Zur Entlastung des 
CPUs soll der ADC mittels DMA direkt in den SRAM schreiben.
Die PWM und der ADC funktioniert ohne DMA einwandfrei. Mit DMA werden 
die eingelesenen Werte zunächst ordnungsgemäß in den Buffer geschrieben 
und können ausgelesen werden. Allerdings erfolgt dann anscheinend kein 
Reset auf die Startadresse des Buffers, sodass sich die einmal 
gebufferten Werte nicht ändern. Dies kann ich nicht verstehen, da der 
DMA interrupt ständig ausgelöst wird.

Der Relevante Teil des Codes folgt hier. Der gesamte MAIN.c ist am 
Anhang.
Ich habe mich sehr eng an ein Beispiel von Microchip gehalten.

Ich hoffe jemand kann mir helfen.
Gruß
Marc
1
#include <xc.h>
2
#include "tglpin.h"
3
4
// User Defines
5
//#define FCY         70000000        // User must calculate and enter FCY here
6
#define NUMSAMP 16 // Number of Samples to Buffer until DMA Interrupt
7
8
// *****************************************************************************
9
// *****************************************************************************
10
// Section: File Scope or Global Constants
11
// *****************************************************************************
12
// *****************************************************************************
13
/* This section defines the input and the output buffers having an integer data type.
14
The input buffers are stored in either the extended data space or the x-memory area
15
depending on whether the extended data space (EDS) is available in the given dsPIC33E device.
16
 */
17
__eds__ int bufferA[NUMSAMP] __attribute__( (eds, space(dma)) );
18
__eds__ int bufferB[NUMSAMP] __attribute__( (eds, space(dma)) );
19
20
unsigned int adc_messwert = 0;
21
unsigned int PWM_PERIOD=2800;   //The PWM period can be computed: PWM_PERIOD = FOSC/(FPWM*PWMInputClockPrescaler)       
22
float DC =0.02;
23
float DC1=0.02;
24
float DC2=0.02;
25
float DC3=0.02;
26
float DC4=0.02;
27
float DC5=0.02;
28
unsigned int    dmaBuffer = 0;
29
30
/******************************************************************************
31
 * Function:        void InitAdc1(void)
32
 * Overview:        This function is used to configure A/D to convert channel 5 on Timer event.
33
 *                  It generates event to DMA on every sample/convert sequence. ADC clock is configured at 625Khz.
34
 *****************************************************************************/
35
void InitAdc1( void )
36
{
37
    AD1CON1bits.FORM = 0;       // Data Format: 0=Integer, 1=Signed Integer 3=Signed Fraction
38
    AD1CON1bits.SSRCG= 0;       // 
39
    AD1CON1bits.SSRC = 7;       // 7 Interan Counter (SAMC) ends sampling and starts convertion
40
    AD1CON1bits.ASAM = 1;       // ADC Sample Control: Sampling begins immediately after conversion
41
    AD1CON1bits.AD12B= 0;       // 10-bit ADC operation
42
    AD1CON2bits.CHPS = 1;       // 0: Converts CH0  //   1 for: CH0 and CH1
43
    AD1CON3bits.ADRC = 0;       // ADC Clock is derived from Systems Clock
44
    AD1CON3bits.SAMC = 0;       // Auto Sample Time = 0*Tad
45
    AD1CON3bits.ADCS = 6;       // ADC Conversion Clock Tad=Tcy*(ADCS+1)= (1/70M)*7 = 100ns (10.0Mhz)
46
      
47
    // ADC Conversion Time for 10-bit Tc=12*Tab =  900ns (1.1MHz)
48
    AD1CON1bits.ADDMABM = 1;    // 1: DMA buffers are built in conversion order mode ([0]1, [1]=2, [3]=1.. //0 Scatter gather mode
49
    AD1CON2bits.SMPI = 0;       // SMPI must be 0
50
    AD1CON4bits.ADDMAEN = 1;    // Converts in ADC1BUF0
51
52
    // AD1CHS0/AD1CHS123: A/D Input Select Register
53
    AD1CHS0bits.CH0SA = 0;      // MUXA +ve input selection (AIN0) for CH0
54
    AD1CHS0bits.CH0SA = 5;      // MUXA +ve input selection (AIN5) for CH0
55
    AD1CHS0bits.CH0NA = 0;      // MUXA -ve input selection (Vref-) for CH0
56
    AD1CHS123bits.CH123SA = 0;  // MUXA +ve input selection (AIN0) for CH1
57
    AD1CHS123bits.CH123NA = 0;  // MUXA -ve input selection (Vref-) for CH1
58
    IFS0bits.AD1IF = 0;         // Clear the A/D interrupt flag bit
59
    IEC0bits.AD1IE = 0;         // Do Not Enable A/D interrupt
60
    AD1CON1bits.ADON = 1;       // Turn on the A/D converter
61
    TglPinInit();
62
}
63
64
/******************************************************************************
65
 * Function:        void InitDma0(void)
66
 * Overview:        DMA0 configuration function.
67
                    Direction: Read from peripheral address 0-x300 (ADC1BUF0) and write to DMA RAM
68
                    AMODE: Register indirect with post increment
69
                    MODE: Continuous, Ping-Pong Mode
70
                    IRQ: ADC Interrupt
71
                    ADC stores results stored alternatively between DMA_BASE[0]/DMA_BASE[16] on every
72
                    16th DMA request
73
 *****************************************************************************/
74
void InitDma0( void )
75
{
76
    DMA0CONbits.AMODE = 0;  // Configure DMA for Register indirect with post increment
77
    DMA0CONbits.MODE = 2;   // 2 Configure DMA for Continuous Ping-Pong mode
78
        
79
    DMA0PAD = ( int ) &ADC1BUF0; // Point DMA to ADC1BUF
80
    DMA0CNT = ( NUMSAMP - 1 ); // Interrupt auf NUMSAMP Transfers
81
82
    DMA0REQ = 13; // ADC1 ? ADC1 Convert Done
83
84
    DMA0STAL = __builtin_dmaoffset( &bufferA );
85
    DMA0STAH = __builtin_dmapage( &bufferA );
86
87
    DMA0STBL = __builtin_dmaoffset( &bufferB );
88
    DMA0STBH = __builtin_dmapage( &bufferB );
89
90
91
    IFS0bits.DMA0IF = 0;    //Clear the DMA interrupt flag bit
92
    IEC0bits.DMA0IE = 1;    //Set the DMA interrupt enable bit
93
    DMA0CONbits.CHEN = 1;
94
}
95
96
97
98
/******************************************************************************
99
 * Function:        void ProcessADCSamples(__eds__ int16_t * adcBuffer)
100
 * Overview:        This function is just a prototype which can be used to perform
101
 *                  some activity on the samples taken by the ADC.
102
 *****************************************************************************/
103
void ProcessADCSamples( __eds__ int *adcBuffer )
104
{
105
    /* Do something with ADC Samples */
106
    int avg=0;
107
    avg=(adcBuffer[2]); //+adcBuffer[4]+adcBuffer[6])/3;
108
    adc_messwert= avg;
109
    IEC0bits.DMA0IE = 1;    //Set the DMA interrupt enable bit
110
 }
111
112
/******************************************************************************
113
 * Function:        void __attribute__((interrupt, auto_psv)) _DMA0Interrupt(void)
114
 * Overview:        Depending on the dmaBuffer value, the data in bufferA or bufferB is passed
115
 *****************************************************************************/
116
void __attribute__ ( (interrupt, auto_psv) ) _DMA0Interrupt( void )
117
{
118
    DMA0CONbits.CHEN=0; //Disable DMA
119
    
120
    if( dmaBuffer == 0 )
121
    {
122
        ProcessADCSamples( bufferA );
123
    }
124
    else
125
    {
126
        ProcessADCSamples( bufferB );
127
    }
128
   
129
    dmaBuffer ^= 1;
130
    TglPin();               // Toggle RA4 -> LED D7
131
    IFS0bits.DMA0IF = 0;    // Clear the DMA0 Interrupt Flag
132
    DMA0CONbits.CHEN=1; //Enable DMA
133
  }

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.