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