Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - Analog Read: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Analog Read
22
33This code is for an Atmega328/Arduino runnning at 16MHz. How to control the UART can be found here:
44
5-`   `[[AVR Embedded Tutorial - UART|UART UARTInit and UARTSendString (...]]
5+```
6+ UART UARTInit and UARTSendString (...
7+```
68
79The ATmega328 can measure with 10-bit accuracy, so a value between 0..1023 is output.
810
911## Polling method
1012
1113### Initialize ADC
1214
1315Configure analog reading. AVcc is used as the reference voltage, this is the easiest way. This must be configured with **ADMUX**.
1416
1517The following reference voltages can be configured with ADMUX:
1618
1719| Bit 7 | Bit 6 | Description |
1820|-------|-------|-------------|
1921| 0 | 0 | Pin AREF |
2022| 0 | 1 | Use AVcc |
2123| 1 | 0 | \- |
2224| 1 | 1 | 2.56V |
2325
2426The converter is started with **ADCSRA**.
2527
2628``` pascal
2729procedure ADC_Init;
2830 begin
2931 ADMUX := (1 shl REFS); // Use AVcc for reference
3032 ADCSRA := (1 shl ADEN) or %111; // Switch on converter, divider 128
3133 end;
3234```
3335
3436### Measuring
3537
3638The procedure for measuring is as follows.
3739
3840- Specify the port.
3941- Wait until the measurement is complete.
4042- Read out the measured value.
4143
4244With ADMUX you have to enter the reference voltage again because it shares the register with the reference. You could also do an OR operation with ADMUX .
4345
4446``` pascal
4547function ADC_Read(Port : byte) : integer;
4648 begin
4749 ADMUX := (1 shl REFS) or (Port and $0F); // Specify port
4850 ADCSRA := ADCSRA or ( 1 shl ADSC ); // Start measuring
4951
5052 while (ADCSRA and (1 shl ADSC)) <> 0 do // Wait until measured
5153 begin
5254 end;
5355
5456 Result := ADC; // Read out the measured value
5557 end;
5658```
5759
5860If you always read in from the same port, you only have to call up the ADMUX line once. You can also start measuring directly after the while loop which saves a few clock cycles.
5961
6062### Output via UART
6163
6264Buffer variables for the measurement data.
6365
6466``` pascal
6567var
6668 Data : integer;
6769 s : string[10];
6870```
6971
7072The measurement data is then output in an endless loop.
7173
7274``` pascal
7375 begin
7476 // Initialize UART
7577 UARTInit;
7678
7779 // Initialize ADC
7880 ADC_Init;
7981
8082 // Allow interrupt
8183 asm Sei end;
8284
8385 // output measured values.
8486 repeat
8587 Data := ADC_Read(0);
8688 str(Data : 6, s);
8789 UARTSendString(s);
8890 until 1 = 2;
8991 end.
9092```
9193
9294## Interrupt method
9395
9496The advantage of the interrupt-controlled method is that you do not have to wait until the measurement is finished, so you have time for other things.
9597
9698### Initialisation
9799
98100The difference:
99101
100102- With ADMUX you enter the input port at the beginning.
101103- At ADCSRA you have to start the first measurement with ADSC.
102104- With ADIE you communicate that the conversion interrupt is controlled.
103105
104106``` pascal
105107procedure ADC_Init;
106108 const
107109 Port = 0;
108110
109111 begin
110112 ADMUX := (1 shl REFS) or (Port and $0F);
111113 ADCSRA := %111 or (1 shl ADEN) or (1 shl ADSC) or (1 shl ADIE);
112114 end;
113115```
114116
115117### Output measured value in the interrupt
116118
117119``` pascal
118120procedure ADC_Ready public name 'ADC_ISR'; interrupt;
119121 var
120122 Data : integer;
121123 s : string[10];
122124
123125 begin
124126 Data := ADC;
125127 ADCSRA := ADCSRA or (1 shl ADSC);
126128 str(Data : 6, s);
127129 UARTSendString(s);
128130 end;
129131```
130132
131133> **Tip:** Interrupt routines should be kept short. This does not mean that you cannot do any processing in an interrupt routine, but you do need to ensure that when the next interrupt occurs, the last one is not still running.
132134
133135### Main program
134136
135137Since the measurement is interrupt-controlled, the main loop remains empty. It is important to switch on the interrupts.
136138
137139``` pascal
138140begin
139141 // Initialize UART
140142 UARTInit;
141143
142144 // ADC
143145 ADC_Init;
144146
145147 // Allow interrupt
146148 asm Sei end;
147149
148150 // main loop
149151 repeat
150152 // Do something
151153 until 1 = 2;
152154end.
153155```
154156
155157# See also
156158
157159- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
158160
159161---
160162*From the Free Pascal wiki, page "AVR Embedded Tutorial - Analog Read", as it stood on 2020-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
161163Category: AVR
162164Category: Arduino
163165Category: Embedded
164166Category: Tutorials

Back to history