1 | #include "p33fxxxx.h"
|
2 | void InitADC_DMA();
|
3 | void __attribute__((__interrupt__,no_auto_psv)) _DMA5Interrupt(void);
|
4 | void RunADC_DMA();
|
5 | void ProcessADCSamples(unsigned int * AdcBuffer);
|
6 | int main (void);
|
7 |
|
8 | //int BufferA[6][8] __attribute__((space(dma),aligned(64)));
|
9 | //int BufferB[6][8] __attribute__((space(dma),aligned(64)));
|
10 |
|
11 | struct
|
12 | {
|
13 | unsigned int Adc1Ch0[8];
|
14 | unsigned int Adc1Ch1[8];
|
15 | unsigned int Adc1Ch2[8];
|
16 | unsigned int Adc1Ch3[8];
|
17 | unsigned int Adc1Ch4[8];
|
18 | unsigned int Adc1Ch5[8];
|
19 | unsigned int Adc1Ch6[8];
|
20 | unsigned int Adc1Ch7[8];
|
21 | unsigned int Adc1Ch8[8];
|
22 | unsigned int Adc1Ch9[8];
|
23 | unsigned int Adc1Ch10[8];
|
24 | unsigned int Adc1Ch11[8];
|
25 | unsigned int Adc1Ch12[8];
|
26 | unsigned int Adc1Ch13[8];
|
27 | //unsigned int Adc1Ch14[8];
|
28 | //unsigned int Adc1Ch15[8];
|
29 |
|
30 | } BufferA __attribute__((space(dma)));
|
31 | struct
|
32 | {
|
33 | unsigned int Adc1Ch0[8];
|
34 | unsigned int Adc1Ch1[8];
|
35 | unsigned int Adc1Ch2[8];
|
36 | unsigned int Adc1Ch3[8];
|
37 | unsigned int Adc1Ch4[8];
|
38 | unsigned int Adc1Ch5[8];
|
39 | unsigned int Adc1Ch6[8];
|
40 | unsigned int Adc1Ch7[8];
|
41 | unsigned int Adc1Ch8[8];
|
42 | unsigned int Adc1Ch9[8];
|
43 | unsigned int Adc1Ch10[8];
|
44 | unsigned int Adc1Ch11[8];
|
45 | unsigned int Adc1Ch12[8];
|
46 | unsigned int Adc1Ch13[8];
|
47 | //unsigned int Adc1Ch14[8];
|
48 | //unsigned int Adc1Ch15[8];
|
49 | } BufferB __attribute__((space(dma)));
|
50 |
|
51 |
|
52 | void InitADC_DMA()
|
53 | {
|
54 | AD1CON1bits.ADON = 0; //ADC is Off, set it off bevor configuration
|
55 | AD1CON1bits.FORM = 0; // Data Output Format: Signed Fraction (Q15 format)
|
56 | AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
|
57 | AD1CON1bits.ASAM = 1; // Sampling begins immediately after conversion
|
58 | AD1CON1bits.AD12B = 1; // 12-bit ADC operation
|
59 | AD1CON1bits.SIMSAM = 1; // Samples multiple channels sequentially
|
60 |
|
61 | AD1CON2bits.BUFM = 0;
|
62 | AD1CON2bits.CSCNA = 1; // Scan CH0+ Input Selections during Sample A bit
|
63 | AD1CON2bits.CHPS = 0; // Converts CH0
|
64 |
|
65 | AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
|
66 | AD1CON3bits.ADCS = 63; // ADC Conversion Clock
|
67 |
|
68 | //AD1CHS0: A/D Input Select Register
|
69 | AD1CHS0bits.CH0SA = 0; // MUXA +ve input selection (AIN0) for CH0
|
70 | AD1CHS0bits.CH0NA = 0; // MUXA -ve input selection (Vref-) for CH0
|
71 |
|
72 | //AD1CHS123: A/D Input Select Register
|
73 | AD1CHS123bits.CH123SA = 0; // MUXA +ve input selection (AIN0) for CH1
|
74 | AD1CHS123bits.CH123NA = 0; // MUXA -ve input selection (Vref-) for CH1
|
75 |
|
76 | //AD1CSSH/AD1CSSL: A/D Input Scan Selection Register
|
77 | AD1CSSH = 0x0000;
|
78 | AD1CSSL = 0x3F00; // Scan AIN8, AIN9, AIN10, AIN11, AIN12, AIN13 inputs
|
79 |
|
80 | //Set up Timer3 to trigger ADC1 conversions:
|
81 |
|
82 | TMR3 = 0x0000;
|
83 | PR3 = 4999; // Trigger ADC1 every 125usec
|
84 | IFS0bits.T3IF = 0; // Clear Timer 3 interrupt
|
85 | IEC0bits.T3IE = 0; // Disable Timer 3 interrupt
|
86 | T3CONbits.TON = 1; //Start Timer 3
|
87 |
|
88 | //Set up DMA Channel 5 for Peripheral Indirect Addressing:
|
89 |
|
90 | DMA5CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode
|
91 | DMA5CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
|
92 | DMA5PAD = (volatile unsigned int)&ADC1BUF0;// Point DMA to ADC1BUF0
|
93 | DMA5CNT = 47; // 48 DMA request (6 buffers, each with 8 words)
|
94 | DMA5REQ = 13; // Select ADC1 as DMA Request source
|
95 | DMA5STA = __builtin_dmaoffset(&BufferA);
|
96 | DMA5STB = __builtin_dmaoffset(&BufferB);
|
97 | IFS3bits.DMA5IF = 0; //Clear the DMA interrupt flag bit
|
98 | IEC3bits.DMA5IE = 1; //Set the DMA interrupt enable bit
|
99 |
|
100 |
|
101 | }
|
102 | void __attribute__((__interrupt__,no_auto_psv)) _DMA5Interrupt(void)
|
103 | {
|
104 | IFS3bits.DMA5IF = 0; //Clear the DMA5 Interrupt Flag
|
105 | unsigned int DmaBuffer = 0;
|
106 | // Switch between Primary and Secondary Ping-Pong buffers
|
107 | if(DmaBuffer == 0)
|
108 | {
|
109 | /*
|
110 | ProcessADCSamples(BufferA.Adc1Ch0);
|
111 | ProcessADCSamples(BufferA.Adc1Ch1);
|
112 | ProcessADCSamples(BufferA.Adc1Ch2);
|
113 | ProcessADCSamples(BufferA.Adc1Ch3);
|
114 | */
|
115 | }
|
116 | else
|
117 | {
|
118 | /*
|
119 | ProcessADCSamples(BufferB.Adc1Ch0);
|
120 | ProcessADCSamples(BufferB.Adc1Ch1);
|
121 | ProcessADCSamples(BufferB.Adc1Ch2);
|
122 | ProcessADCSamples(BufferB.Adc1Ch3);
|
123 | */
|
124 | }
|
125 |
|
126 | DmaBuffer ^= 1;
|
127 |
|
128 | }
|
129 | //Set up ADC1 for DMA operation:
|
130 | void RunADC_DMA()
|
131 | {
|
132 | AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode
|
133 | AD1CON2bits.SMPI = 5; // 6 ADC buffers
|
134 | AD1CON4bits.DMABL = 3; // Each buffer contains 8 words
|
135 |
|
136 | IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
|
137 | IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
|
138 | DMA5CONbits.CHEN = 1; //Enable DMA0 channel
|
139 | AD1CON1bits.ADON = 1; // Turn on the A/D converter
|
140 | }
|
141 |
|
142 |
|
143 | void ProcessADCSamples(unsigned int * AdcBuffer)
|
144 | {
|
145 | char AdcBuffer_string[32];
|
146 | // itoa_o(*AdcBuffer, AdcBuffer_string, 10);
|
147 | }
|
148 |
|
149 |
|
150 | int main (void)
|
151 | {
|
152 | InitADC_DMA();
|
153 | RunADC_DMA();
|
154 | while (1){}
|
155 | }
|