AVR Embedded Tutorial - Analog Read: what changed
Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | 1 | # Analog Read | |
| 2 | 2 | ||
| 3 | 3 | This code is for an Atmega328/Arduino runnning at 16MHz. How to control the UART can be found here: | |
| 4 | 4 | ||
| 5 | - | ||
| 5 | + | ```text | |
| 6 | 6 | UART UARTInit and UARTSendString (... | |
| 7 | 7 | ``` | |
| 8 | 8 | ||
| 9 | 9 | The ATmega328 can measure with 10-bit accuracy, so a value between 0..1023 is output. | |
| 10 | 10 | ||
| 11 | 11 | ## Polling method | |
| 12 | 12 | ||
| 13 | 13 | ### Initialize ADC | |
| 14 | 14 | ||
| 15 | 15 | Configure analog reading. AVcc is used as the reference voltage, this is the easiest way. This must be configured with **ADMUX**. | |
| 16 | 16 | ||
| 17 | 17 | The following reference voltages can be configured with ADMUX: | |
| 18 | 18 | ||
| 19 | 19 | | Bit 7 | Bit 6 | Description | | |
| 20 | 20 | |-------|-------|-------------| | |
| 21 | 21 | | 0 | 0 | Pin AREF | | |
| 22 | 22 | | 0 | 1 | Use AVcc | | |
| 23 | 23 | | 1 | 0 | \- | | |
| 24 | 24 | | 1 | 1 | 2.56V | | |
| 25 | 25 | ||
| 26 | 26 | The converter is started with **ADCSRA**. | |
| 27 | 27 | ||
| 28 | 28 | ``` pascal | |
| 29 | 29 | procedure ADC_Init; | |
| 30 | 30 | begin | |
| 31 | 31 | ADMUX := (1 shl REFS); // Use AVcc for reference | |
| 32 | 32 | ADCSRA := (1 shl ADEN) or %111; // Switch on converter, divider 128 | |
| 33 | 33 | end; | |
| 34 | 34 | ``` | |
| 35 | 35 | ||
| 36 | 36 | ### Measuring | |
| 37 | 37 | ||
| 38 | 38 | The procedure for measuring is as follows. | |
| 39 | 39 | ||
| 40 | 40 | - Specify the port. | |
| 41 | 41 | - Wait until the measurement is complete. | |
| 42 | 42 | - Read out the measured value. | |
| 43 | 43 | ||
| 44 | 44 | With 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 . | |
| 45 | 45 | ||
| 46 | 46 | ``` pascal | |
| 47 | 47 | function ADC_Read(Port : byte) : integer; | |
| 48 | 48 | begin | |
| 49 | 49 | ADMUX := (1 shl REFS) or (Port and $0F); // Specify port | |
| 50 | 50 | ADCSRA := ADCSRA or ( 1 shl ADSC ); // Start measuring | |
| 51 | 51 | ||
| 52 | 52 | while (ADCSRA and (1 shl ADSC)) <> 0 do // Wait until measured | |
| 53 | 53 | begin | |
| 54 | 54 | end; | |
| 55 | 55 | ||
| 56 | 56 | Result := ADC; // Read out the measured value | |
| 57 | 57 | end; | |
| 58 | 58 | ``` | |
| 59 | 59 | ||
| 60 | 60 | If 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. | |
| 61 | 61 | ||
| 62 | 62 | ### Output via UART | |
| 63 | 63 | ||
| 64 | 64 | Buffer variables for the measurement data. | |
| 65 | 65 | ||
| 66 | 66 | ``` pascal | |
| 67 | 67 | var | |
| 68 | 68 | Data : integer; | |
| 69 | 69 | s : string[10]; | |
| 70 | 70 | ``` | |
| 71 | 71 | ||
| 72 | 72 | The measurement data is then output in an endless loop. | |
| 73 | 73 | ||
| 74 | 74 | ``` pascal | |
| 75 | 75 | begin | |
| 76 | 76 | // Initialize UART | |
| 77 | 77 | UARTInit; | |
| 78 | 78 | ||
| 79 | 79 | // Initialize ADC | |
| 80 | 80 | ADC_Init; | |
| 81 | 81 | ||
| 82 | 82 | // Allow interrupt | |
| 83 | 83 | asm Sei end; | |
| 84 | 84 | ||
| 85 | 85 | // output measured values. | |
| 86 | 86 | repeat | |
| 87 | 87 | Data := ADC_Read(0); | |
| 88 | 88 | str(Data : 6, s); | |
| 89 | 89 | UARTSendString(s); | |
| 90 | 90 | until 1 = 2; | |
| 91 | 91 | end. | |
| 92 | 92 | ``` | |
| 93 | 93 | ||
| 94 | 94 | ## Interrupt method | |
| 95 | 95 | ||
| 96 | 96 | The 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. | |
| 97 | 97 | ||
| 98 | 98 | ### Initialisation | |
| 99 | 99 | ||
| 100 | 100 | The difference: | |
| 101 | 101 | ||
| 102 | 102 | - With ADMUX you enter the input port at the beginning. | |
| 103 | 103 | - At ADCSRA you have to start the first measurement with ADSC. | |
| 104 | 104 | - With ADIE you communicate that the conversion interrupt is controlled. | |
| 105 | 105 | ||
| 106 | 106 | ``` pascal | |
| 107 | 107 | procedure ADC_Init; | |
| 108 | 108 | const | |
| 109 | 109 | Port = 0; | |
| 110 | 110 | ||
| 111 | 111 | begin | |
| 112 | 112 | ADMUX := (1 shl REFS) or (Port and $0F); | |
| 113 | 113 | ADCSRA := %111 or (1 shl ADEN) or (1 shl ADSC) or (1 shl ADIE); | |
| 114 | 114 | end; | |
| 115 | 115 | ``` | |
| 116 | 116 | ||
| 117 | 117 | ### Output measured value in the interrupt | |
| 118 | 118 | ||
| 119 | 119 | ``` pascal | |
| 120 | 120 | procedure ADC_Ready public name 'ADC_ISR'; interrupt; | |
| 121 | 121 | var | |
| 122 | 122 | Data : integer; | |
| 123 | 123 | s : string[10]; | |
| 124 | 124 | ||
| 125 | 125 | begin | |
| 126 | 126 | Data := ADC; | |
| 127 | 127 | ADCSRA := ADCSRA or (1 shl ADSC); | |
| 128 | 128 | str(Data : 6, s); | |
| 129 | 129 | UARTSendString(s); | |
| 130 | 130 | end; | |
| 131 | 131 | ``` | |
| 132 | 132 | ||
| 133 | 133 | > **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. | |
| 134 | 134 | ||
| 135 | 135 | ### Main program | |
| 136 | 136 | ||
| 137 | 137 | Since the measurement is interrupt-controlled, the main loop remains empty. It is important to switch on the interrupts. | |
| 138 | 138 | ||
| 139 | 139 | ``` pascal | |
| 140 | 140 | begin | |
| 141 | 141 | // Initialize UART | |
| 142 | 142 | UARTInit; | |
| 143 | 143 | ||
| 144 | 144 | // ADC | |
| 145 | 145 | ADC_Init; | |
| 146 | 146 | ||
| 147 | 147 | // Allow interrupt | |
| 148 | 148 | asm Sei end; | |
| 149 | 149 | ||
| 150 | 150 | // main loop | |
| 151 | 151 | repeat | |
| 152 | 152 | // Do something | |
| 153 | 153 | until 1 = 2; | |
| 154 | 154 | end. | |
| 155 | 155 | ``` | |
| 156 | 156 | ||
| 157 | 157 | # See also | |
| 158 | 158 | ||
| 159 | 159 | - [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview | |
| 160 | 160 | ||
| 161 | 161 | --- | |
| 162 | 162 | *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).* | |
| 163 | 163 | Category: AVR | |
| 164 | 164 | Category: Arduino | |
| 165 | 165 | Category: Embedded | |
| 166 | 166 | Category: Tutorials |
