adc_avr.c
Go to the documentation of this file.
00001 00043 #include "adc_avr.h" 00044 00045 #include "cfg/cfg_adc.h" 00046 #include "cfg/cfg_proc.h" 00047 #include "cfg/cfg_signal.h" 00048 #include <cfg/macros.h> 00049 #include <cfg/compiler.h> 00050 00051 #include <cpu/irq.h> // IRQ_ASSERT_ENABLED() 00052 00053 #include <drv/adc.h> 00054 00055 #include <avr/io.h> 00056 #include <avr/interrupt.h> 00057 00064 #define ADC_AVR_AREF 0 00065 #define ADC_AVR_AVCC 1 00066 #define ADC_AVR_INT256 2 00067 /* \} */ 00068 00069 #if CONFIG_KERN 00070 #include <cfg/module.h> 00071 #include <kern/proc.h> 00072 #include <kern/signal.h> 00073 00074 00075 #if !CONFIG_KERN_SIGNALS 00076 #error Signals must be active to use the ADC with kernel 00077 #endif 00078 00079 /* Signal adc convertion end */ 00080 #define SIG_ADC_COMPLETE SIG_SINGLE 00081 00082 /* ADC waiting process */ 00083 static struct Process *adc_process; 00084 00089 ISR(ADC_vect) 00090 { 00091 sig_post(adc_process, SIG_ADC_COMPLETE); 00092 } 00093 #endif /* CONFIG_KERN */ 00094 00099 void adc_hw_select_ch(uint8_t ch) 00100 { 00101 /* Set to 0 all mux registers */ 00102 #if CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA328P || CPU_AVR_ATMEGA168 00103 ADMUX &= ~(BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0)); 00104 #elif CPU_AVR_ATMEGA32 || CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 \ 00105 || CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 || CPU_AVR_ATMEGA324P \ 00106 || CPU_AVR_ATMEGA644P 00107 ADMUX &= ~(BV(MUX4) | BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0)); 00108 #if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 00109 ADCSRB &= ~(BV(MUX5)); 00110 #endif 00111 #else 00112 #error Unknown CPU 00113 #endif 00114 00115 /* Select channel, only first 8 channel modes are supported */ 00116 ADMUX |= (ch & 0x07); 00117 00118 #if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 00119 /* Select channel, all 16 channels are supported */ 00120 if (ch > 0x07) 00121 ADCSRB |= BV(MUX5); 00122 00123 #endif 00124 00125 } 00126 00127 00133 uint16_t adc_hw_read(void) 00134 { 00135 // Ensure another convertion is not running. 00136 ASSERT(!(ADCSRA & BV(ADSC))); 00137 00138 // Start convertion 00139 ADCSRA |= BV(ADSC); 00140 00141 #if CONFIG_KERN 00142 // Ensure IRQs enabled. 00143 IRQ_ASSERT_ENABLED(); 00144 adc_process = proc_current(); 00145 sig_wait(SIG_ADC_COMPLETE); 00146 #else 00147 //Wait in polling until is done 00148 while (ADCSRA & BV(ADSC)) ; 00149 #endif 00150 00151 return(ADC); 00152 } 00153 00157 void adc_hw_init(void) 00158 { 00159 /* 00160 * Select channel 0 as default, 00161 * result right adjusted. 00162 */ 00163 ADMUX = 0; 00164 00165 #if CONFIG_ADC_AVR_REF == ADC_AVR_AREF 00166 /* External voltage at AREF as analog ref source */ 00167 /* None */ 00168 #elif CONFIG_ADC_AVR_REF == ADC_AVR_AVCC 00169 /* AVCC as analog ref source */ 00170 ADMUX |= BV(REFS0); 00171 #elif CONFIG_ADC_AVR_REF == ADC_AVR_INT256 00172 /* Internal 2.56V as ref source */ 00173 ADMUX |= BV(REFS1) | BV(REFS0); 00174 #else 00175 #error Unsupported ADC ref value. 00176 #endif 00177 00178 #if defined(ADCSRB) 00179 /* Disable Auto trigger source: ADC in Free running mode. */ 00180 ADCSRB = 0; 00181 #endif 00182 00183 /* Enable ADC, disable autotrigger mode. */ 00184 ADCSRA = BV(ADEN); 00185 00186 #if CONFIG_KERN 00187 MOD_CHECK(proc); 00188 ADCSRA |= BV(ADIE); 00189 #endif 00190 00191 /* Set convertion frequency */ 00192 #if CONFIG_ADC_AVR_DIVISOR == 2 00193 ADCSRA |= BV(ADPS0); 00194 #elif CONFIG_ADC_AVR_DIVISOR == 4 00195 ADCSRA |= BV(ADPS1); 00196 #elif CONFIG_ADC_AVR_DIVISOR == 8 00197 ADCSRA |= BV(ADPS1) | BV(ADPS0); 00198 #elif CONFIG_ADC_AVR_DIVISOR == 16 00199 ADCSRA |= BV(ADPS2); 00200 #elif CONFIG_ADC_AVR_DIVISOR == 32 00201 ADCSRA |= BV(ADPS2) | BV(ADPS0); 00202 #elif CONFIG_ADC_AVR_DIVISOR == 64 00203 ADCSRA |= BV(ADPS2) | BV(ADPS1); 00204 #elif CONFIG_ADC_AVR_DIVISOR == 128 00205 ADCSRA |= BV(ADPS2) | BV(ADPS1) | BV(ADPS0); 00206 #else 00207 #error Unsupported ADC prescaler value. 00208 #endif 00209 00210 /* Start a convertion to init ADC hw */ 00211 adc_hw_read(); 00212 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)