1 | /*==========================================================================================
|
2 | ADC Initialization for Channel Scan
|
3 | ===========================================================================================*/
|
4 | void adcInit(void){
|
5 | initDma0();
|
6 |
|
7 | AD1CON1bits.FORM = 0; // Data Output Format: Signed Fraction (Q15
|
8 | format)
|
9 | AD1CON1bits.SSRC = 2; // Sample Clock Source: GP Timer starts conversion
|
10 | AD1CON1bits.ASAM = 1; // ADC Sample Control: Sampling begins immediately
|
11 | after conversion
|
12 | AD1CON1bits.AD12B = 1; // 12-bit ADC operation
|
13 | AD1CON1bits.SIMSAM = 0; // Samples multiple channels individually in
|
14 | sequence
|
15 | AD1CON2bits.BUFM = 0;
|
16 | AD1CON2bits.CSCNA = 1; // Scan Input Selections for CH0+ during Sample A
|
17 | bit
|
18 | AD1CON2bits.CHPS = 0; // Converts CH0
|
19 | AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
|
20 | AD1CON3bits.ADCS = 63; // ADC Conversion Clock
|
21 | //AD1CHS0: A/D Input Select Register
|
22 | AD1CHS0bits.CH0SA = 0; // MUXA +ve input selection (AIN0) for CH0
|
23 | AD1CHS0bits.CH0NA = 0; // MUXA -ve input selection (Vref-) for CH0
|
24 |
|
25 | //AD1CHS123: A/D Input Select Register
|
26 | AD1CHS123bits.CH123SA = 0; // MUXA +ve input selection (AIN0) for CH1
|
27 | AD1CHS123bits.CH123NA = 0; // MUXA -ve input selection (Vref-) for CH1
|
28 | //AD1CSSL: A/D Input Scan Selection Register
|
29 | AD1CSSL = 0x001F; // Scan AIN0, AIN1, AIN2, AIN3, AIN4 inputs
|
30 | AD1CON1bits.ADDMABM = 0; // DMA buffers are built in scatter/gather mode
|
31 | AD1CON2bits.SMPI = 4; // 5 ADC buffers
|
32 | AD1CON4bits.DMABL = 3; // Each buffer contains 8 words
|
33 | IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
|
34 | IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
|
35 | AD1CON1bits.ADON = 1; // Turn on the A/D converter
|
36 | initTmr3();
|
37 | }
|
38 | /*======================================================================================
|
39 | Timer 3 is setup to time-out every 125 microseconds (8Khz Rate). As a
|
40 | result, the module
|
41 | will stop sampling and trigger a conversion on every Timer3 time-out,
|
42 | i.e., Ts=125us.
|
43 | =======================================================================================*/
|
44 | void initTmr3(void)
|
45 | {
|
46 | TMR3 = 0x0000;
|
47 | PR3 = 4999; // Trigger ADC1 every 125usec
|
48 | IFS0bits.T3IF = 0; // Clear Timer 3 interrupt
|
49 | IEC0bits.T3IE = 0; // Disable Timer 3 interrupt
|
50 | T3CONbits.TON = 1; //Start Timer 3
|
51 | }
|
52 |
|
53 | // Linker will allocate these buffers from the bottom of DMA RAM.
|
54 | struct
|
55 | {
|
56 | unsigned int Adc1Ch0[8];
|
57 | unsigned int Adc1Ch1[8];
|
58 | unsigned int Adc1Ch2[8];
|
59 | unsigned int Adc1Ch3[8];
|
60 | unsigned int Adc1Ch4[8];
|
61 | } BufferA __attribute__((space(dma)));
|
62 |
|
63 | struct
|
64 | {
|
65 | unsigned int Adc1Ch0[8];
|
66 | unsigned int Adc1Ch1[8];
|
67 | unsigned int Adc1Ch2[8];
|
68 | unsigned int Adc1Ch3[8];
|
69 | unsigned int Adc1Ch4[8];
|
70 | } BufferB __attribute__((space(dma)));
|
71 | // DMA0 configuration
|
72 | // Direction: Read from peripheral address 0-x300 (ADC1BUF0) and write
|
73 | to DMA RAM
|
74 | // AMODE: Peripheral Indirect Addressing Mode
|
75 | // MODE: Continuous, Ping-Pong Mode
|
76 | // IRQ: ADC Interrupt
|
77 |
|
78 | void initDma0(void)
|
79 | {
|
80 | DMA0CONbits.AMODE = 2; // Configure DMA for Peripheral indirect mode
|
81 | DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
|
82 | DMA0PAD = 0x0300; // Point DMA to ADC1BUF0
|
83 | DMA0CNT = 39; // 40 DMA request (4 buffers, each with 8 words)
|
84 | DMA0REQ = 13; // Select ADC1 as DMA Request source
|
85 | DMA0STA = __builtin_dmaoffset(&BufferA);
|
86 | DMA0STB = __builtin_dmaoffset(&BufferB);
|
87 | IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
|
88 | IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
|
89 | DMA0CONbits.CHEN=1; // Enable DMA
|
90 | }
|
91 |
|
92 | /*========================================================================================
|
93 | _DMA0Interrupt(): ISR name is chosen from the device linker script.
|
94 | ========================================================================================*/
|
95 | unsigned int DmaBuffer = 0;
|
96 | void __attribute__((_interrupt_)) _DMA0Interrupt(void)
|
97 | {
|
98 | if(DmaBuffer == 0){
|
99 | xMsb = (unsigned char)(BufferA.Adc1Ch0[1] >> 8);
|
100 | xLsb = (unsigned char)(BufferA.Adc1Ch0[1] & 0xFF);
|
101 | yMsb = (unsigned char)(BufferA.Adc1Ch1[1] >> 8);
|
102 | yLsb = (unsigned char)(BufferA.Adc1Ch1[1] & 0xFF);
|
103 | vrefMsb = (unsigned char)(BufferA.Adc1Ch2[1] >> 8);
|
104 | vrefMsb = (unsigned char)(BufferA.Adc1Ch2[1] & 0xFF);
|
105 | temperatureMsb = (unsigned char)(BufferA.Adc1Ch3[1] >> 8);
|
106 | temperatureLsb = (unsigned char)(BufferA.Adc1Ch3[1] & 0xFF);
|
107 | zMsb = (unsigned char)(BufferA.Adc1Ch4[1] >> 8);
|
108 | zLsb = (unsigned char)(BufferA.Adc1Ch4[1] & 0xFF);
|
109 |
|
110 | }
|
111 | else
|
112 | {
|
113 | xMsb = (unsigned char)(BufferB.Adc1Ch0[1] >> 8);
|
114 | xLsb = (unsigned char)(BufferB.Adc1Ch0[1] & 0xFF);
|
115 | yMsb = (unsigned char)(BufferB.Adc1Ch1[1] >> 8);
|
116 | yLsb = (unsigned char)(BufferB.Adc1Ch1[1] & 0xFF);
|
117 | vrefMsb = (unsigned char)(BufferB.Adc1Ch2[1] >> 8);
|
118 | vrefMsb = (unsigned char)(BufferB.Adc1Ch2[1] & 0xFF);
|
119 | temperatureMsb = (unsigned char)(BufferB.Adc1Ch3[1] >> 8);
|
120 | temperatureLsb = (unsigned char)(BufferB.Adc1Ch3[1] & 0xFF);
|
121 | zMsb = (unsigned char)(BufferB.Adc1Ch4[1] >> 8);
|
122 | zLsb = (unsigned char)(BufferB.Adc1Ch4[1] & 0xFF);
|
123 | }
|
124 |
|
125 | DmaBuffer ^= 1;
|
126 | IFS0bits.DMA0IF = 0; //Clear the DMA0 Interrupt Flag
|
127 | }
|