Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - Analog Read: what changed

Revision 2 to 3. 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-```
5+```text
66 UART UARTInit and UARTSendString (...
77```
88
99The ATmega328 can measure with 10-bit accuracy, so a value between 0..1023 is output.
1010
1111## Polling method
1212
1313### Initialize ADC
1414
1515Configure analog reading. AVcc is used as the reference voltage, this is the easiest way. This must be configured with **ADMUX**.
1616
1717The following reference voltages can be configured with ADMUX:
1818
1919| Bit 7 | Bit 6 | Description |
2020|-------|-------|-------------|
2121| 0 | 0 | Pin AREF |
2222| 0 | 1 | Use AVcc |
2323| 1 | 0 | \- |
2424| 1 | 1 | 2.56V |
2525
2626The converter is started with **ADCSRA**.
2727
2828``` pascal
2929procedure ADC_Init;
3030 begin
3131 ADMUX := (1 shl REFS); // Use AVcc for reference
3232 ADCSRA := (1 shl ADEN) or %111; // Switch on converter, divider 128
3333 end;
3434```
3535
3636### Measuring
3737
3838The procedure for measuring is as follows.
3939
4040- Specify the port.
4141- Wait until the measurement is complete.
4242- Read out the measured value.
4343
4444With 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 .
4545
4646``` pascal
4747function ADC_Read(Port : byte) : integer;
4848 begin
4949 ADMUX := (1 shl REFS) or (Port and $0F); // Specify port
5050 ADCSRA := ADCSRA or ( 1 shl ADSC ); // Start measuring
5151
5252 while (ADCSRA and (1 shl ADSC)) <> 0 do // Wait until measured
5353 begin
5454 end;
5555
5656 Result := ADC; // Read out the measured value
5757 end;
5858```
5959
6060If 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.
6161
6262### Output via UART
6363
6464Buffer variables for the measurement data.
6565
6666``` pascal
6767var
6868 Data : integer;
6969 s : string[10];
7070```
7171
7272The measurement data is then output in an endless loop.
7373
7474``` pascal
7575 begin
7676 // Initialize UART
7777 UARTInit;
7878
7979 // Initialize ADC
8080 ADC_Init;
8181
8282 // Allow interrupt
8383 asm Sei end;
8484
8585 // output measured values.
8686 repeat
8787 Data := ADC_Read(0);
8888 str(Data : 6, s);
8989 UARTSendString(s);
9090 until 1 = 2;
9191 end.
9292```
9393
9494## Interrupt method
9595
9696The 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.
9797
9898### Initialisation
9999
100100The difference:
101101
102102- With ADMUX you enter the input port at the beginning.
103103- At ADCSRA you have to start the first measurement with ADSC.
104104- With ADIE you communicate that the conversion interrupt is controlled.
105105
106106``` pascal
107107procedure ADC_Init;
108108 const
109109 Port = 0;
110110
111111 begin
112112 ADMUX := (1 shl REFS) or (Port and $0F);
113113 ADCSRA := %111 or (1 shl ADEN) or (1 shl ADSC) or (1 shl ADIE);
114114 end;
115115```
116116
117117### Output measured value in the interrupt
118118
119119``` pascal
120120procedure ADC_Ready public name 'ADC_ISR'; interrupt;
121121 var
122122 Data : integer;
123123 s : string[10];
124124
125125 begin
126126 Data := ADC;
127127 ADCSRA := ADCSRA or (1 shl ADSC);
128128 str(Data : 6, s);
129129 UARTSendString(s);
130130 end;
131131```
132132
133133> **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.
134134
135135### Main program
136136
137137Since the measurement is interrupt-controlled, the main loop remains empty. It is important to switch on the interrupts.
138138
139139``` pascal
140140begin
141141 // Initialize UART
142142 UARTInit;
143143
144144 // ADC
145145 ADC_Init;
146146
147147 // Allow interrupt
148148 asm Sei end;
149149
150150 // main loop
151151 repeat
152152 // Do something
153153 until 1 = 2;
154154end.
155155```
156156
157157# See also
158158
159159- [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview
160160
161161---
162162*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).*
163163Category: AVR
164164Category: Arduino
165165Category: Embedded
166166Category: Tutorials

Back to history