1 | void ADC_Init(char mode)
|
2 | {
|
3 | //ADCON1 Register
|
4 | //Set up A/D for Automatic Sampling
|
5 | //Use Timer3 to provide sampling time
|
6 | //Set up A/D conversrion results to be read in 1.15 fractional
|
7 | //number format.
|
8 | //All other bits to their default state
|
9 | ADCON1bits.FORM = 3;
|
10 | ADCON1bits.SSRC = 2;
|
11 | ADCON1bits.ASAM = 1;
|
12 |
|
13 | //ADCON2 Register
|
14 | ADCON2bits.VCFG = 3; //External Vref+, External Vref-
|
15 | ADCON2bits.SMPI = 0; //Set up A/D for interrupting after 1 samples get filled in the buffer
|
16 |
|
17 | //ADCON3 Register
|
18 | //We would like to set up a sampling rate of 7998.6981Hz or 87252.071 Hz
|
19 | //Total Conversion Time= 1/Sampling Rate = 125.02 microseconds or 11.461 microseconds
|
20 | //For fosc=117.968MHz, Tcy = 33.91 ns = Instruction Cycle Time
|
21 | //We will set up Sampling Time using Timer3 & Tad using ADCS<5:0> bits
|
22 | //All other bits to their default state
|
23 | //Let's set up ADCS arbitrarily to 38
|
24 | //So Tad = Tcy*(ADCS+1)/2 = 661.2 nanoseconds
|
25 | //So, the A/D converter will take 14*Tad periods to convert each sample
|
26 | ADCON3bits.ADCS = 63;
|
27 |
|
28 | //Next, we will to set up Timer 3 to time-out every X=125.02 microseconds (for mode 1) or X=11.461 microseconds (for mode 2)
|
29 | //As a result, the module will stop sampling and trigger a conversion
|
30 | //on every Timer3 time-out, i.e., 125.02 microseconds or 11.461 microseconds. At that time,
|
31 | //the conversion process starts and completes 14*Tad periods later.
|
32 | TMR3 = 0x0000;
|
33 | IFS0bits.T3IF = 0;
|
34 | IEC0bits.T3IE = 0;
|
35 | T3CONbits.TCS = 0;
|
36 | T3CONbits.TCKPS=0;
|
37 |
|
38 | //ADCHS Register
|
39 | //Set up A/D Channel Select Register to convert AN0
|
40 | ADCHS = 0x0000;
|
41 |
|
42 |
|
43 | //ADCSSL Register
|
44 | //Channel Scanning is disabled. All bits left to their default state
|
45 | ADCSSL = 0x0000;
|
46 |
|
47 | //ADPCFG Register
|
48 | //Set up channels AN0 as analog input and configure rest as digital
|
49 | //Recall that we configured all A/D pins as digital when code execution
|
50 | //entered main() out of reset
|
51 | ADPCFG = 0xFFFF;
|
52 | ADPCFGbits.PCFG0 = 0;
|
53 |
|
54 | //Clear the A/D interrupt flag bit
|
55 | IFS0bits.ADIF = 0;
|
56 |
|
57 | //Set the A/D interrupt enable bit
|
58 | IEC0bits.ADIE = 1;
|
59 |
|
60 | //Turn on the A/D converter
|
61 | //This is typically done after configuring other registers
|
62 | ADCON1bits.ADON = 1;
|
63 |
|
64 | //Start Timer 3
|
65 | T3CONbits.TON = 1;
|
66 | }
|
67 |
|
68 | //_ADCInterrupt() is the A/D interrupt service routine (ISR).
|
69 | //The routine must have global scope in order to be an ISR.
|
70 | //The ISR name is chosen from the device linker script.
|
71 | void __attribute__((__interrupt__)) _ADCInterrupt(void)
|
72 | {
|
73 | //Clear the Timer3 Interrupt Flag
|
74 | IFS0bits.T3IF = 0;
|
75 |
|
76 | int i = 0;
|
77 |
|
78 | //Clear the A/D Interrupt flag bit or else the CPU will
|
79 | //keep vectoring back to the ISR
|
80 | IFS0bits.ADIF = 0;
|
81 |
|
82 | //Put the A/D conversion results to inputSignal.real
|
83 | adcPtr = &ADCBUF0 ;
|
84 |
|
85 | for (i=0;i<1;i++)
|
86 | {
|
87 | (*p_inputSignal++).real = *adcPtr++;
|
88 | }
|
89 |
|
90 | if (p_inputSignal > &inputSignal[NUMSAMP-1])
|
91 | {
|
92 | SamplesReadyFlag++ ; // Sampling completed
|
93 | IEC0bits.ADIE = 0; // Disable ADC interrupt
|
94 | }
|