1 | // Testing interrupt-based analog reading
|
2 | // ATMega328p
|
3 |
|
4 | // Note, many macro values are defined in <avr/io.h> and
|
5 | // <avr/interrupts.h>, which are included automatically by
|
6 | // the Arduino interface
|
7 |
|
8 | // High when a value is ready to be read
|
9 | volatile int readFlag;
|
10 |
|
11 | // Value to store analog result
|
12 | volatile int analogVal;
|
13 |
|
14 |
|
15 | // Initialization
|
16 | void setup(){
|
17 |
|
18 | // clear ADLAR in ADMUX (0x7C) to right-adjust the result
|
19 | // ADCL will contain lower 8 bits, ADCH upper 2 (in last two bits)
|
20 | ADMUX &= B11011111;
|
21 |
|
22 | // Set REFS1..0 in ADMUX (0x7C) to change reference voltage to the
|
23 | // proper source (01)
|
24 | ADMUX |= B01000000;
|
25 |
|
26 | // Clear MUX3..0 in ADMUX (0x7C) in preparation for setting the analog
|
27 | // input
|
28 | ADMUX &= B11110000;
|
29 |
|
30 | // Set MUX3..0 in ADMUX (0x7C) to read from AD8 (Internal temp)
|
31 | // Do not set above 15! You will overrun other parts of ADMUX. A full
|
32 | // list of possible inputs is available in Table 24-4 of the ATMega328
|
33 | // datasheet
|
34 | ADMUX |= 8;
|
35 | // ADMUX |= B00001000; // Binary equivalent
|
36 |
|
37 | // Set ADEN in ADCSRA (0x7A) to enable the ADC.
|
38 | // Note, this instruction takes 12 ADC clocks to execute
|
39 | ADCSRA |= B10000000;
|
40 |
|
41 | // Set ADATE in ADCSRA (0x7A) to enable auto-triggering.
|
42 | ADCSRA |= B00100000;
|
43 |
|
44 | // Clear ADTS2..0 in ADCSRB (0x7B) to set trigger mode to free running.
|
45 | // This means that as soon as an ADC has finished, the next will be
|
46 | // immediately started.
|
47 | ADCSRB &= B11111000;
|
48 |
|
49 | // Set the Prescaler to 128 (16000KHz/128 = 125KHz)
|
50 | // Above 200KHz 10-bit results are not reliable.
|
51 | ADCSRA |= B00000111;
|
52 |
|
53 | // Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt.
|
54 | // Without this, the internal interrupt will not trigger.
|
55 | ADCSRA |= B00001000;
|
56 |
|
57 | // Enable global interrupts
|
58 | // AVR macro included in <avr/interrupts.h>, which the Arduino IDE
|
59 | // supplies by default.
|
60 | sei();
|
61 |
|
62 | // Kick off the first ADC
|
63 | readFlag = 0;
|
64 | // Set ADSC in ADCSRA (0x7A) to start the ADC conversion
|
65 | ADCSRA |=B01000000;
|
66 | }
|
67 |
|
68 |
|
69 | // Processor loop
|
70 | void loop(){
|
71 |
|
72 | // Check to see if the value has been updated
|
73 | if (readFlag == 1){
|
74 |
|
75 | // Perform whatever updating needed
|
76 |
|
77 | readFlag = 0;
|
78 | }
|
79 |
|
80 | // Whatever else you would normally have running in loop().
|
81 |
|
82 | }
|
83 |
|
84 |
|
85 | // Interrupt service routine for the ADC completion
|
86 | ISR(ADC_vect){
|
87 |
|
88 | // Done reading
|
89 | readFlag = 1;
|
90 |
|
91 | // Must read low first
|
92 | analogVal = ADCL | (ADCH << 8);
|
93 |
|
94 | // Not needed because free-running mode is enabled.
|
95 | // Set ADSC in ADCSRA (0x7A) to start another ADC conversion
|
96 | // ADCSRA |= B01000000;
|
97 | }
|