00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "pic24_all.h"
00031 #include "stdio.h"
00032
00033 #ifndef _DMA0IF
00034 #error "This processor selection does not have a DMA module; this code example is incompatible with a PIC24 CPU that does not have DMA."
00035
00036 #endif
00037
00063 #define CONFIG_LED2() CONFIG_RB14_AS_DIG_OUTPUT()
00064 #define LED2 _LATB14
00065
00066
00067
00068
00069
00070 #ifdef USE_12BIT_ADC
00071 #define ADC_LEN 12
00072 #define ADC_NSTEPS 4096
00073 #define ADC_12BIT_FLAG 1
00074 #else
00075 #define ADC_LEN 10
00076 #define ADC_NSTEPS 1024
00077 #define ADC_12BIT_FLAG 0
00078 #endif
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #define CONVERSIONS_PER_INPUT 1
00090 #define MAX_CHANNELS 16
00091
00092 #define MAX_DMA_TRANSFER_SIZE (CONVERSIONS_PER_INPUT*MAX_CHANNELS) //make power of two for alignment to work
00093
00094
00095 uint16 au16_bufferA[MAX_DMA_TRANSFER_SIZE] __attribute__((space(dma),aligned(MAX_DMA_TRANSFER_SIZE*2)));
00096 uint8 u8_NumChannelsScanned;
00097
00098
00099
00100 uint8 configDMA_ADC(uint16 u16_ch0ScanMask, \
00101 uint8 u8_autoSampleTime, \
00102 uint8 u8_use12bit,
00103 uint8 u8_useScatterGather,
00104 uint8 u8_dmaLocsPerInput) {
00105 uint8 u8_i, u8_nChannels=0;
00106 uint16 u16_mask = 0x0001;
00107 uint16 u16_dmaMode;
00108
00109
00110
00111 for (u8_i=0; u8_i<16; u8_i++) {
00112 if (u16_ch0ScanMask & u16_mask)
00113 u8_nChannels++;
00114 u16_mask<<=1;
00115 }
00116
00117 if (u8_autoSampleTime > 31) u8_autoSampleTime=31;
00118
00119 AD1CON1bits.ADON = 0;
00121 AD1CON1 = ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON;
00122 #ifdef _AD12B
00123 if (u8_use12bit)
00124 AD1CON1bits.AD12B = 1;
00125 else
00126 AD1CON1bits.AD12B = 0;
00127 #endif
00128 if (u8_useScatterGather) {
00129 AD1CON1bits.ADDMABM = 0;
00130 u16_dmaMode = DMA_AMODE_PERIPHERAL_INDIRECT;
00131 }
00132 else {
00133
00134 AD1CON1bits.ADDMABM = 1;
00135 u16_dmaMode = DMA_AMODE_REGISTER_POSTINC;
00136 }
00137 AD1CON3 = ADC_CONV_CLK_INTERNAL_RC | (u8_autoSampleTime<<8);
00138
00139
00140
00141 AD1CON2 = ADC_VREF_AVDD_AVSS | ADC_CONVERT_CH0 | ADC_SCAN_ON | ((u8_nChannels-1)<<2);
00142
00143
00144
00145 #ifdef __PIC24H__
00146 AD1CHS0 = ADC_CH0_NEG_SAMPLEA_VREFN;
00147 #else
00148 AD1CHS = ADC_CH0_NEG_SAMPLEA_VREFN;
00149 #endif
00150 AD1CSSL = u16_ch0ScanMask;
00151
00152
00153 switch (u8_dmaLocsPerInput) {
00154 case 1 : AD1CON4 = ADC_1_WORD_PER_INPUT;break;
00155 case 2 : AD1CON4 = ADC_2_WORD_PER_INPUT;break;
00156 case 4 : AD1CON4 = ADC_4_WORD_PER_INPUT;break;
00157 case 8 : AD1CON4 = ADC_8_WORD_PER_INPUT;break;
00158 case 16 : AD1CON4 = ADC_16_WORD_PER_INPUT;break;
00159 case 32 : AD1CON4 = ADC_32_WORD_PER_INPUT;break;
00160 case 64 : AD1CON4 = ADC_64_WORD_PER_INPUT;break;
00161 case 128 : AD1CON4 = ADC_128_WORD_PER_INPUT;break;
00162 default: AD1CON4 = ADC_1_WORD_PER_INPUT;break;
00163 }
00164
00165
00166 DMA0PAD = (unsigned int) &ADC1BUF0;
00167 DMA0REQ = DMA_IRQ_ADC1;
00168 DMA0STA = __builtin_dmaoffset(au16_bufferA);
00169 DMA0CNT = (u8_nChannels * u8_dmaLocsPerInput)-1;
00170 DMA0CON =
00171 (DMA_MODULE_ON |
00172 DMA_SIZE_WORD |
00173 DMA_DIR_READ_PERIPHERAL |
00174 DMA_INTERRUPT_FULL |
00175 DMA_NULLW_OFF |
00176 u16_dmaMode |
00177 DMA_MODE_CONTINUOUS);
00178
00179 _DMA0IF = 0;
00180 _DMA0IP = 6;
00181 _DMA0IE = 1;
00182
00183 AD1CON1bits.ADON = 1;
00184 return(u8_nChannels);
00185 }
00186
00187
00188 volatile uint16 au16_buffer[MAX_DMA_TRANSFER_SIZE];
00189 volatile uint16 au16_bufferSum[MAX_CHANNELS];
00190 volatile uint8 u8_waiting;
00191
00192
00193 void _ISRFAST _DMA0Interrupt(void) {
00194 uint8 u8_i;
00195 uint16* au16_adcHWBuff = (uint16*) &au16_bufferA;
00196 _DMA0IF = 0;
00197 if (u8_waiting ) {
00198 for ( u8_i=0; u8_i<MAX_DMA_TRANSFER_SIZE; u8_i++) {
00199 au16_buffer[u8_i] = au16_adcHWBuff[u8_i];
00200 }
00201 u8_waiting = 0;
00202 }
00203
00204 LED2 = !LED2;
00205 }
00206
00207
00208
00209 int main (void) {
00210 uint8 u8_i, u8_j, u8_k;
00211 uint16 u16_pot;
00212 float f_pot;
00213
00214 configBasic(HELLO_MSG);
00215
00216
00217
00218 CONFIG_AN0_AS_ANALOG();
00219 CONFIG_AN1_AS_ANALOG();
00220 CONFIG_AN4_AS_ANALOG();
00221 CONFIG_AN5_AS_ANALOG();
00222 CONFIG_AN10_AS_ANALOG();
00223 CONFIG_AN11_AS_ANALOG();
00224 CONFIG_AN12_AS_ANALOG();
00225
00226 CONFIG_LED2();
00227
00228 u8_NumChannelsScanned = configDMA_ADC( ADC_SCAN_AN0 | ADC_SCAN_AN1 | ADC_SCAN_AN4 | \
00229 ADC_SCAN_AN5 | ADC_SCAN_AN10 | ADC_SCAN_AN11 | ADC_SCAN_AN12,
00230 31, ADC_12BIT_FLAG, 0, CONVERSIONS_PER_INPUT);
00231
00232
00233 while ( !AD1CON1bits.DONE) {};
00234 u8_waiting = 1;
00235 while (1) {
00236 while (u8_waiting){};
00237
00238
00239
00240 u8_k = 0;
00241 for (u8_j=0; u8_j<CONVERSIONS_PER_INPUT; u8_j++) {
00242 for ( u8_i=0; u8_i<u8_NumChannelsScanned; u8_i++) {
00243
00244 if (u8_j == 0) au16_bufferSum[u8_i] = au16_buffer[u8_k];
00245 else au16_bufferSum[u8_i] += au16_buffer[u8_k];
00246 u8_k++;
00247 }
00248 }
00249
00250 for (u8_i=u8_NumChannelsScanned; u8_i<MAX_CHANNELS ;u8_i++) {
00251 au16_bufferSum[u8_i] = 0;
00252 }
00253
00254 for ( u8_i=0; u8_i<MAX_CHANNELS ; u8_i++) {
00255 u16_pot = au16_bufferSum[u8_i]/CONVERSIONS_PER_INPUT;
00256 f_pot = 3.3 / ADC_NSTEPS * u16_pot;
00257 printf("r");
00258 if (u8_i < 10) outChar( '0'+u8_i );
00259 else outChar( 'A'-10+u8_i );
00260 printf(":0x%04X=%1.3fV ", u16_pot, (double) f_pot );
00261 if ((u8_i % 4) == 3) printf("\n");
00262 }
00263 printf("\n");
00264 u8_waiting = 1;
00265 doHeartbeat();
00266 DELAY_MS(1500);
00267 }
00268 }
00269