diff --git a/hardware/sam/system/libsam/include/adc.h b/hardware/sam/system/libsam/include/adc.h index 2d189b7ee..31534753c 100644 --- a/hardware/sam/system/libsam/include/adc.h +++ b/hardware/sam/system/libsam/include/adc.h @@ -43,11 +43,14 @@ #include "../chip.h" -#define ADC_FREQ_MAX 20000000 -#define ADC_FREQ_MIN 1000000 +#define ADC_FREQ_MAX 5000000 +#define ADC_STARTUP 20 -#define ADC_STARTUP_NORM 40 -#define ADC_STARTUP_FAST 12 +#define ADC12_FREQ_MAX 20000000 +#define ADC12_FREQ_MIN 1000000 + +#define ADC12_STARTUP_NORM 40 +#define ADC12_STARTUP_FAST 12 /* Definitions for ADC resolution */ typedef enum _adc_resolution_t { diff --git a/hardware/sam/system/libsam/source/adc10_sam3u.c b/hardware/sam/system/libsam/source/adc10_sam3u.c index 1b73691d1..9531651df 100644 --- a/hardware/sam/system/libsam/source/adc10_sam3u.c +++ b/hardware/sam/system/libsam/source/adc10_sam3u.c @@ -64,7 +64,6 @@ extern "C" { */ uint32_t adc_init(Adc *p_adc, uint32_t ul_mck, uint32_t ul_adc_clock, uint32_t ul_startuptime) { - uint32_t ul_prescal,ul_startup; p_adc->ADC_CR = ADC_CR_SWRST; /* Reset Mode Register */ @@ -76,9 +75,14 @@ uint32_t adc_init(Adc *p_adc, uint32_t ul_mck, uint32_t ul_adc_clock, uint32_t u p_adc->ADC_RNCR = 0; p_adc->ADC_TCR = 0; p_adc->ADC_TNCR = 0; - ul_prescal = ul_mck/(2 * ul_adc_clock) - 1; - ul_startup = ((ul_adc_clock/1000000) * ul_startuptime / 8) - 1; - p_adc->ADC_MR |= ADC_MR_PRESCAL( ul_prescal ) | ( (ul_startup< ul_adc_clock ) { + prescal++; + ul_adc_clock = ul_mck/((prescal+1)*2); + } + uint32_t startup = ((ul_adc_clock/1000000) * ul_startuptime / 8) - 1; + p_adc->ADC_MR |= ADC_MR_PRESCAL(prescal) | ADC_MR_STARTUP(startup); return 0; } diff --git a/hardware/sam/system/libsam/source/adc12_sam3u.c b/hardware/sam/system/libsam/source/adc12_sam3u.c index 8da95532c..2ca25bf7d 100644 --- a/hardware/sam/system/libsam/source/adc12_sam3u.c +++ b/hardware/sam/system/libsam/source/adc12_sam3u.c @@ -64,7 +64,6 @@ extern "C" { */ uint32_t adc12_init(Adc12b *p_adc, uint32_t ul_mck, uint32_t ul_adc_clock, uint32_t ul_startuptime, uint32_t ul_offmode_startuptime) { - uint32_t ul_prescal,ul_startup,ul_offmode; p_adc->ADC12B_CR = ADC12B_CR_SWRST; /* Reset Mode Register */ @@ -76,11 +75,17 @@ uint32_t adc12_init(Adc12b *p_adc, uint32_t ul_mck, uint32_t ul_adc_clock, uint3 p_adc->ADC12B_RNCR = 0; p_adc->ADC12B_TCR = 0; p_adc->ADC12B_TNCR = 0; - ul_prescal = ul_mck/(2 * ul_adc_clock) - 1; - ul_startup = ((ul_adc_clock/1000000) * ul_startuptime / 8) - 1; - ul_offmode = ((ul_adc_clock/1000000) * ul_offmode_startuptime / 8) - 1; - p_adc->ADC12B_MR |= ADC12B_MR_PRESCAL( ul_prescal ) | ( (ul_startup<ADC12B_EMR |= (ul_offmode<<16) & (0xffu << 16); + uint32_t prescal = ul_mck/(2 * ul_adc_clock) - 1; + // check for rounding errors + if ( (ul_mck/((prescal+1)*2)) > ul_adc_clock ) { + prescal++; + ul_adc_clock = ul_mck/((prescal+1)*2); + } + uint32_t startup = ((ul_adc_clock/1000000) * ul_startuptime / 8) - 1; + p_adc->ADC12B_MR |= ADC12B_MR_PRESCAL(prescal) | ADC12B_MR_STARTUP(startup); + + uint32_t offmode = ((ul_adc_clock/1000000) * ul_offmode_startuptime / 8) - 1; + p_adc->ADC12B_EMR |= ADC12B_EMR_OFF_MODE_STARTUP_TIME(offmode); return 0; } /** diff --git a/hardware/sam/variants/arduino_due/variant.cpp b/hardware/sam/variants/arduino_due/variant.cpp index e1133db3e..2e4276e62 100644 --- a/hardware/sam/variants/arduino_due/variant.cpp +++ b/hardware/sam/variants/arduino_due/variant.cpp @@ -350,8 +350,8 @@ extern void init( void ) * prescal: ADCClock = MCK / ( (PRESCAL+1) * 2 ) => 64MHz / ((4+1)*2) = 6.4MHz * ADC clock = 6.4 MHz */ - adc_init( ADC, SystemCoreClock, 6400000, 10 ) ; - adc_configure_timing( ADC, 1200 ) ; + adc_init( ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP ) ; + adc_configure_timing( ADC, 15 ) ; adc_configure_trigger( ADC, ADC_TRIG_SW ) ; adc_disable_interrupt( ADC, 0xFFFFFFFF ) ; /* Disable all adc interrupt. */ adc_disable_channel( ADC, ADC_ALL_CHANNEL ) ; @@ -366,8 +366,8 @@ extern void init( void ) * prescal: ADCClock = MCK / ( (PRESCAL+1) * 2 ) => 64MHz / ((4+1)*2) = 6.4MHz * ADC clock = 6.4 MHz */ - adc12_init( ADC12B, SystemCoreClock, 6400000, 10, 1200 ) ; - adc12_configure_timing( ADC12B, 1200 ) ; + adc12_init( ADC12B, SystemCoreClock, ADC12_FREQ_MAX, ADC12_STARTUP_FAST, 1 ) ; + adc12_configure_timing( ADC12B, 15 ) ; adc12_configure_trigger( ADC12B, ADC_TRIG_SW ) ; adc12_disable_interrupt( ADC12B, 0xFFFFFFFF ) ; /* Disable all adc interrupt. */ adc12_disable_channel( ADC12B, ADC_ALL_CHANNEL ) ;