void ADC_Handler(void) { uint32_t i; uint32_t ul_temp; /* With PDC transfer */ if (g_adc_test_mode.uc_pdc_en) { if ((adc_get_status(ADC) & ADC_SR_RXBUFF) == ADC_SR_RXBUFF) { g_adc_sample_data.us_done = ADC_DONE_MASK; adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE); /* Only keep sample value, and discard channel number. */ for (i = 0; i < NUM_CHANNELS; i++) { g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk; } } } else { if ((adc_get_status(ADC) & ADC_SR_DRDY) == ADC_SR_DRDY) { ul_temp = adc_get_latest_value(ADC); for (i = 0; i < NUM_CHANNELS; i++) { g_adc_sample_data.us_value[i] = ul_temp & ADC_LCDR_LDATA_Msk; g_adc_sample_data.us_done |= 1 << i; } } } }
/** * \brief ADC interrupt handler. */ void ADC_Handler(void) { uint32_t tmp; uint32_t status ; status = adc_get_status(ADC); /* Checa se a interrupção é devido ao canal 5 */ static float rad_antes = 0; if ((status & ADC_ISR_EOC5)) { tmp = adc_get_channel_value(ADC, ADC_POT_CHANNEL); ili93xx_set_foreground_color(COLOR_WHITE); ili93xx_draw_filled_rectangle(9, 39, ILI93XX_LCD_WIDTH,55); v=3.3*((float)tmp)/4095.0; rad=2*pi*((float)tmp)/4095.0; ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad_antes),160+54*arm_sin_f32(rad_antes)); ili93xx_set_foreground_color(COLOR_BLACK); sprintf(vet, "Tensao: %f", v); ili93xx_draw_string(10, 40, vet); ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad),160+54*arm_sin_f32(rad)); rad_antes = rad; } }
/** * \brief Interrupt handler for the ADC. */ static void adc_irq_handler(void) { uint32_t status; uint8_t i, j; uint32_t value; /* Get Interrupt Status (ISR) */ status = adc_get_status(); /* check at least one EOCn flag set */ if( status & 0x00000FFF ) { for (i=0; i < NUMBER_OF_ADC_CHANNELS; i++) { value = adc_get_converted_data(i); /* Check ISR "End of Conversion" corresponding bit */ if ((status & (1u<<i))) { for (j = 0; j < NUM_CHANNELS; j++) { if ( _data.channel[j] == i) { _data.value[j] = value; _data.done |= 1 << i; break; } } } } } }
// Start converting the enabled channels void AnalogInStartConversion(uint32_t channels) { #if SAM3XA || SAM4S // Clear out any existing conversion complete bits in the status register for (uint32_t chan = 0; chan < 16; ++chan) { if ((adc_get_status(ADC) & (1 << chan)) != 0) { (void)adc_get_channel_value(ADC, static_cast<adc_channel_num_t>(chan)); } } adc_start(ADC); #elif SAM4E channels &= activeChannels; if ((channels & 0x0000FFFF) != 0) { StartConversion(AFEC0); } if ((channels & 0xFFFF0000) != 0) { StartConversion(AFEC1); } #elif SAME70 channels &= activeChannels; if ((channels & 0x000003FF) != 0) { StartConversion(AFEC0); } if ((channels & 0x003FF800) != 0) { StartConversion(AFEC1); } #endif }
/** * \brief ADC interrupt handler. * Entramos aqui quando a conversao for concluida. */ void ADC_Handler(void) { uint32_t tempValue; uint32_t status ; status = adc_get_status(ADC); /* Checa se a interrupção é devido ao canal 5 */ if ((status & ADC_ISR_EOC5)) { tempValue = adc_get_channel_value(ADC, ADC_POT_CHANNEL); if ((tempValue > adc_value_old + 2) || (tempValue < adc_value_old - 2)) { if (isAmp){ amplitude = tempValue; atualiza_amp(amplitude); } else { frequencia = tempValue; tc_stop(TC0,0); configure_tc((frequencia*32768/2000)/4095); atualiza_freq(frequencia); } } adc_value_old = tempValue; } }
/** * Interrupt handler for TC0 interrupt. */ void ADC_Handler(void) { uint32_t tmp; uint32_t status ; status = adc_get_status(ADC); max_digital = adc_get_channel_value(ADC, ADC_POT_CHANNEL); }
/** * \brief Callback function for ADCIFE interrupt. */ static void adcife_read_conv_result(void) { if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) == ADCIFE_SR_SEOC) { g_adc_sample_data[0] = adc_get_last_conv_value(&g_adc_inst); g_uc_condone_flag = 1; adc_clear_status(&g_adc_inst, ADCIFE_SCR_SEOC); } }
/** * \brief Callback function for ADCIFE interrupt. */ static void adcife_set_conv_flag(void) { if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) == ADCIFE_SR_SEOC) { g_uc_condone_flag = 1; adc_clear_status(&g_adc_inst, ADCIFE_SCR_SEOC); adc_disable_interrupt(&g_adc_inst, ADC_SEQ_SEOC); } }
/** * \brief ADC interrupt handler. * Entramos aqui quando a conversao for concluida. */ void ADC_Handler(void) { uint32_t resistencia; if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) { resistencia = adc_get_channel_value(ADC, ADC_POT_CHANNEL); } }
/** \brief Disable channel * * \param *adc Base address of the ADC * \param channel channel to disable (0 to 7) */ void adc_disable(volatile avr32_adc_t *adc, uint16_t channel) { Assert( adc != NULL ); Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist **/ if (adc_get_status(adc, channel) == true) { /* disable channel */ adc->chdr |= (1 << channel); } }
uint16_t getLightSens() { uint16_t result = 0; adc_start_conversion(&adc1); while(adc_get_status(&adc1) != ADC_STATUS_RESULT_READY); adc_read(&adc1, &result); result = result * 16; adc_clear_status(&adc1, ADC_STATUS_RESULT_READY); return result; }
void adc_disable(volatile avr32_adc_t * adc, unsigned short channel) { Assert( adc!=NULL ); Assert( channel <= AVR32_ADC_CHANNELS_MSB ); // check if channel exist if (adc_get_status(adc, channel) == ENABLED) { // disable channel adc->chdr |= (1 << channel); } }
/** * \brief Timmer handler (100ms) starts a new conversion. */ void TC0_Handler(void) { volatile uint32_t ul_dummy; /* Clear status bit to acknowledge interrupt */ ul_dummy = tc_get_status(TC0,0); /* Avoid compiler warning */ UNUSED(ul_dummy); if (adc_get_status(ADC) & (1 << ADC_POT_CHANNEL)) { adc_start(ADC); } }
/** * \brief Handler for ADC interrupt. */ void ADC_Handler(void) { uint32_t low_threshold; uint32_t high_threshold; uint32_t status = adc_get_status(ADC); /* Read the status to ack the IT */ if ((status & ADC_ISR_COMPE) == ADC_ISR_COMPE) { /* Get the potentiometer initial value */ pontentiometer_value = adc_get_channel_value( ADC, ADC_CHANNEL_POTENTIOMETER ); /* Set Window threshold according to the initial values */ low_threshold = pontentiometer_value - (NB_INTERVALS * (0x1000 / 256)); if (low_threshold > 0xf0000000) { low_threshold = 0; } high_threshold = pontentiometer_value + (NB_INTERVALS * (0x1000 / 256)); if (high_threshold >= 0x1000) { high_threshold = 0x1000 - 1; } /* Normalize the value 0 -> 255 */ pontentiometer_value = pontentiometer_value*100 + 1; ppt_delay_clapse_counter = 0; /* Setup Threshold*/ adc_set_comparison_window( ADC, low_threshold, high_threshold); /* Compare mode, in the window. */ adc_enable_interrupt(ADC, ADC_IER_COMPE); } if (status & ADC_ISR_ENDRX) { /* Start next buffer */ ADC->ADC_RNPR = (uint32_t) frame_buffer[(adc_buf_ndx + 2) % AUDIO_NB_BUFFER]; ADC->ADC_RNCR = AUDIO_FRAME_SIZE; adc_buf_ndx = (adc_buf_ndx + 1) % AUDIO_NB_BUFFER; adc_nb_samples += AUDIO_FRAME_SIZE; } }
/** * \brief Enter sleep mode using WFI instruction. * Enable interrupt first and then disable it after wake up. */ static void enter_asleep(void) { while (1) { puts("Now switching the device into sleep mode...\r"); /* Clear status register. */ adc_get_status(ADC); /* Enable Compare Interrupt. */ adc_enable_interrupt(ADC, ADC_IER_COMPE); __WFI(); /* Every time waked up, break out of the loop. */ break; } }
/** * \brief ADC interrupt handler. */ void ADC_Handler(void) { uint32_t tmp; uint32_t status ; status = adc_get_status(ADC); /* Checa se a interrupção é devido ao canal 5 */ if ((status & ADC_ISR_EOC5)) { tmp = adc_get_channel_value(ADC, ADC_POT_CHANNEL); if(tmp != adc_value_old) { adc_value_old = tmp; adc_value_new = 1; } } }
/** * \brief Callback function for ADCIFE interrupt. */ static void adcife_wm_handler(void) { uint32_t ul_mode; uint16_t us_adc; /* Disable Window Monitor Interrupt. */ adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_WM) == ADCIFE_SR_WM) { ul_mode = adc_get_wm_mode(&g_adc_inst); us_adc = adc_get_last_conv_value(&g_adc_inst); switch (ul_mode) { case 1: printf("-ISR-:DAC output voltage %d mv is above the low threshold:%d mv!\n\r", (int)(us_adc * VOLT_REF / MAX_DIGITAL), (int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL)); break; case 2: printf("-ISR-:DAC output voltage %d mv is below the high threshold:%d mv!\n\r", (int)(us_adc * VOLT_REF / MAX_DIGITAL), (int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL)); break; case 3: printf("-ISR-:DAC output voltage %d mv is in the comparison window:%d-%d mv!\n\r", (int)(us_adc * VOLT_REF / MAX_DIGITAL), (int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL), (int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL)); break; case 4: printf("-ISR-:DAC output voltage %d mv is out of the comparison window:%d-%d mv!\n\r", (int)(us_adc * VOLT_REF / MAX_DIGITAL), (int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL), (int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL)); break; } adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); } }
// Check whether all conversions have been completed since the last call to AnalogStartConversion bool AnalogInCheckReady(uint32_t channels) { #if SAM3XA || SAM4S const uint32_t mask = channels & activeChannels; return (adc_get_status(ADC) & mask) == mask; #elif SAM4E channels &= activeChannels; const uint32_t afec0Mask = channels & 0x0000FFFF; const uint32_t afec1Mask = (channels >> 16) & 0x0000FFFF; return (afec_get_interrupt_status(AFEC0) & afec0Mask) == afec0Mask && (afec_get_interrupt_status(AFEC1) & afec1Mask) == afec1Mask; #elif SAME70 channels &= activeChannels; const uint32_t afec0Mask = channels & 0x000003FF; const uint32_t afec1Mask = (channels >> 10) & 0x000003FF; return (afec_get_interrupt_status(AFEC0) & afec0Mask) == afec0Mask && (afec_get_interrupt_status(AFEC1) & afec1Mask) == afec1Mask; #endif }
/** * \brief ADC interrupt handler. */ void ADC_Handler(void) { uint32_t ul_counter; int32_t l_vol; float f_temp; uint32_t ul_value = 0; uint32_t ul_temp_value = 0; if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) { /* Multisample */ for (ul_counter = 0; ul_counter < BUFFER_SIZE; ul_counter++) { ul_value += gs_s_adc_values[ul_counter]; } /* Averaging */ ul_temp_value = ul_value / 10; ul_value = ul_value / 100; ul_temp_value -= (ul_value * 10); /* Round for last decimal */ if (ul_temp_value > 4) { ul_value++; } l_vol = ul_value * VOLT_REF / MAX_DIGITAL; #if SAM3S | SAM3XA /* Using multiplication (*0.37736) instead of division (/2.65). */ f_temp = (float)(l_vol - 800) * 0.37736 + 27.0; #else /* Using multiplication (*0.21186) instead of division (/4.72). */ f_temp = (float)(l_vol - 1440) * 0.21186 + 27.0; #endif print_temp(f_temp); /* Clear the buffer. */ memset(gs_s_adc_values, 0x0, sizeof(gs_s_adc_values)); /* Start new pdc transfer. */ adc_read_buffer(ADC, gs_s_adc_values, BUFFER_SIZE); } }
int main(void) { system_init(); delay_init(); //! [setup_init] configure_adc(); //! [setup_init] //! [main] //! [start_conv] adc_start_conversion(&adc_instance); //! [start_conv] //! [get_res] uint16_t result=0; configure_console(); //! [get_res] //! [inf_loop] while (1) { /* Infinite loop */ //adc_read(&adc_instance, &result); do { /* Wait for conversion to be done and read out result */ } while (adc_read(&adc_instance, &result) == STATUS_BUSY); printf("The result is %d\n",result); uint32_t far = 9.0/5.0*((float)result*.0002441406*6.0/.01)+32.0; printf(" The temp is %d", far); adc_clear_status(&adc_instance,adc_get_status(&adc_instance)); adc_start_conversion(&adc_instance); delay_ms(500); } //! [inf_loop] //! [main] }
void ADC_Handler(void) { uint32_t ul_mode; uint16_t us_adc; /* Disable Compare Interrupt. */ adc_disable_interrupt(ADC, ADC_IDR_COMPE); if ((adc_get_status(ADC) & ADC_ISR_COMPE) == ADC_ISR_COMPE) { ul_mode = adc_get_comparison_mode(ADC); us_adc = adc_get_channel_value(ADC, ADC_CHANNEL_POTENTIOMETER); switch (ul_mode) { case 0: printf("-ISR-:Potentiometer voltage %d mv is below the low " "threshold:%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL, gs_us_low_threshold * VOLT_REF / MAX_DIGITAL); break; case 1: printf("-ISR-:Potentiometer voltage %d mv is above the high " "threshold:%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL, gs_us_high_threshold * VOLT_REF / MAX_DIGITAL); break; case 2: printf("-ISR-:Potentiometer voltage %d mv is in the comparison " "window:%d-%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL, gs_us_low_threshold * VOLT_REF / MAX_DIGITAL, gs_us_high_threshold * VOLT_REF / MAX_DIGITAL); break; case 3: printf("-ISR-:Potentiometer voltage %d mv is out of the comparison" " window:%d-%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL, gs_us_low_threshold * VOLT_REF / MAX_DIGITAL, gs_us_high_threshold * VOLT_REF / MAX_DIGITAL); break; } } }
uint16_t hal_analog_read(uint8_t adc_channel) { uint32_t ulValue = 0; // Enable the corresponding channel adc_enable_channel( ADC, adc_channel ); // Start the ADC adc_start( ADC ); // Wait for end of conversion while ((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY) ; // Read the value ulValue = adc_get_latest_value(ADC); //!! ulValue = mapResolution(ulValue, ADC_RESOLUTION, _readResolution); // Disable the corresponding channel adc_disable_channel(ADC, adc_channel); return ulValue; }
/** * \brief Systick handler, start new conversion. */ void SysTick_Handler(void) { if ((adc_get_status(ADC) & ADC_ISR_EOC15) == ADC_ISR_EOC15) { adc_start(ADC); } }
/** * \brief Configure to trigger ADC by PWM Event Line. */ static void configure_pwm_trigger(void) { /* PWM frequency in Hz. */ #define PWM_FREQUENCY 2 /* Maximum duty cycle value. */ #define MAX_DUTY_CYCLE 1000 /* Enable PWMC peripheral clock. */ pmc_enable_periph_clk(ID_PWM); /* Disable PWM channel 0. */ pwm_channel_disable(PWM, PWM_CHANNEL_0); gpio_configure_pin(PIN_PWMC_PWMH0_TRIG, PIN_PWMC_PWMH0_TRIG_FLAG); /* Set clock A to run at PWM_FREQUENCY * MAX_DUTY_CYCLE (clock B is not used). */ pwm_clock_t pwm_clock_setting = { .ul_clka = PWM_FREQUENCY * MAX_DUTY_CYCLE, .ul_clkb = 0, .ul_mck = sysclk_get_cpu_hz() }; pwm_init(PWM, &pwm_clock_setting); /* Configure PWMC for channel 0 (left-aligned). */ pwm_channel_t pwm_trigger_channel = { .channel = PWM_CHANNEL_0, .alignment = PWM_ALIGN_LEFT, .polarity = PWM_LOW, .ul_prescaler = PWM_CMR_CPRE_CLKA, .ul_period = MAX_DUTY_CYCLE, .ul_duty = MAX_DUTY_CYCLE / 2 }; pwm_channel_init(PWM, &pwm_trigger_channel); pwm_cmp_t pwm_comparison_setting = { .unit = PWM_CMP_UNIT_0, .b_enable = true, .ul_value = MAX_DUTY_CYCLE / 2, .b_pulse_on_line_0 = true }; pwm_cmp_init(PWM, &pwm_comparison_setting); /* Enable PWM channel 0. */ pwm_channel_enable(PWM, PWM_CHANNEL_0); /* Set PWM Event Line 0 trigger. */ #if SAM3S || SAM3XA || SAM4S adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0, 0); #elif SAM3U #ifdef ADC_12B adc12b_configure_trigger(ADC12B, ADC12B_TRIG_PWM_EVENT_LINE_0); #else adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0); #endif #endif } #endif /** * \brief Read converted data through PDC channel. * * \param p_adc The pointer of adc peripheral. * \param p_s_buffer The destination buffer. * \param ul_size The size of the buffer. */ #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size) { /* Check if the first PDC bank is free. */ if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) { p_adc->ADC_RPR = (uint32_t) p_s_buffer; p_adc->ADC_RCR = ul_size; p_adc->ADC_PTCR = ADC_PTCR_RXTEN; return 1; } else { /* Check if the second PDC bank is free. */ if (p_adc->ADC_RNCR == 0) { p_adc->ADC_RNPR = (uint32_t) p_s_buffer; p_adc->ADC_RNCR = ul_size; return 1; } else { return 0; } } } #elif SAM3U #ifdef ADC_12B static uint32_t adc12_read_buffer(Adc12b * p_adc, uint16_t * p_s_buffer, uint32_t ul_size) { /* Check if the first PDC bank is free. */ if ((p_adc->ADC12B_RCR == 0) && (p_adc->ADC12B_RNCR == 0)) { p_adc->ADC12B_RPR = (uint32_t) p_s_buffer; p_adc->ADC12B_RCR = ul_size; p_adc->ADC12B_PTCR = ADC12B_PTCR_RXTEN; return 1; } else { /* Check if the second PDC bank is free. */ if (p_adc->ADC12B_RNCR == 0) { p_adc->ADC12B_RNPR = (uint32_t) p_s_buffer; p_adc->ADC12B_RNCR = ul_size; return 1; } else { return 0; } } } #else static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size) { /* Check if the first PDC bank is free. */ if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) { p_adc->ADC_RPR = (uint32_t) p_s_buffer; p_adc->ADC_RCR = ul_size; p_adc->ADC_PTCR = ADC_PTCR_RXTEN; return 1; } else { /* Check if the second PDC bank is free. */ if (p_adc->ADC_RNCR == 0) { p_adc->ADC_RNPR = (uint32_t) p_s_buffer; p_adc->ADC_RNCR = ul_size; return 1; } else { return 0; } } } #endif #endif /** * \brief Start ADC sample. * Initialize ADC, set clock and timing, and set ADC to given mode. */ static void start_adc(void) { /* Enable peripheral clock. */ #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C uint32_t i; pmc_enable_periph_clk(ID_ADC); #elif SAM3U #ifdef ADC_12B pmc_enable_periph_clk(ID_ADC12B); #else pmc_enable_periph_clk(ID_ADC); #endif #endif /* Initialize ADC. */ /* * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 ) * For example, MCK = 64MHZ, PRESCAL = 4, then: * ADCClock = 64 / ((4+1) * 2) = 6.4MHz; */ #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C /* Formula: * Startup Time = startup value / ADCClock * Startup time = 64 / 6.4MHz = 10 us */ adc_init(ADC, sysclk_get_cpu_hz(), 6400000, ADC_STARTUP_TIME_4); #elif SAM3U #ifdef ADC_12B /* Formula: * Startup Time = (startup value + 1) * 8 / ADCClock * Startup time = (7 + 1) * 8 / 6.4MHz = 10 us */ adc12b_init(ADC12B, sysclk_get_cpu_hz(), 6400000, STARTUP_TIME, OFF_MODE_STARTUP_TIME); #else /* Formula: * Startup Time = (startup value + 1) * 8 / ADCClock * Startup time = (3 + 1) * 8 / 3.2MHz = 10 us */ adc_init(ADC, sysclk_get_cpu_hz(), 3200000, STARTUP_TIME); #endif #endif memset((void *)&g_adc_sample_data, 0, sizeof(g_adc_sample_data)); /* Set ADC timing. */ #if SAM3S || SAM3XA || SAM4S /* Formula: * Transfer Time = (TRANSFER * 2 + 3) / ADCClock * Tracking Time = (TRACKTIM + 1) / ADCClock * Settling Time = settling value / ADCClock * * Transfer Time = (1 * 2 + 3) / 6.4MHz = 781 ns * Tracking Time = (1 + 1) / 6.4MHz = 312 ns * Settling Time = 3 / 6.4MHz = 469 ns */ adc_configure_timing(ADC, TRACKING_TIME, ADC_SETTLING_TIME_3, TRANSFER_PERIOD); #elif SAM3N || SAM4C adc_configure_timing(ADC, TRACKING_TIME); #elif SAM3U /* Formula: * Sample & Hold Time = SHTIM/ADCClock * * Sample & Hold Time = 6 / 6.4 = 938 ns */ #ifdef ADC_12B adc12b_configure_timing(ADC12B, SAMPLE_HOLD_TIME); #else adc_configure_timing(ADC, SAMPLE_HOLD_TIME); #endif #endif #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C /* Enable channel number tag. */ adc_enable_tag(ADC); /* Enable/disable sequencer. */ if (g_adc_test_mode.uc_sequence_en) { /* Set user defined channel sequence. */ adc_configure_sequence(ADC, ch_list, 2); /* Enable sequencer. */ adc_start_sequencer(ADC); /* Enable channels. */ for (i = 0; i < 2; i++) { adc_enable_channel(ADC, (enum adc_channel_num_t)i); } /* Update channel number. */ g_adc_sample_data.uc_ch_num[0] = ch_list[0]; g_adc_sample_data.uc_ch_num[1] = ch_list[1]; } else { /* Disable sequencer. */ adc_stop_sequencer(ADC); /* Enable channels. */ adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER); #if SAM3S || SAM3XA || SAM4S || SAM4C adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR); #endif /* Update channel number. */ g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER; #if SAM3S || SAM3XA || SAM4S || SAM4C g_adc_sample_data.uc_ch_num[1] = ADC_TEMPERATURE_SENSOR; #else g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER; #endif } #elif SAM3U #ifdef ADC_12B adc12b_enable_channel(ADC12B, ADC_CHANNEL_POTENTIOMETER); #else adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER); #endif g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER; g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER; #endif #if SAM3S || SAM3XA || SAM4S || SAM4C /* Enable the temperature sensor. */ adc_enable_ts(ADC); #endif /* Set gain and offset (only single ended mode used here). */ #if SAM3S || SAM3XA || SAM4S adc_disable_anch(ADC); /* Disable analog change. */ #endif if (g_adc_test_mode.uc_gain_en) { #if SAM3S || SAM3XA || SAM4S adc_enable_anch(ADC); /* gain = 2 */ adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_2); #elif SAM3U #ifdef ADC_12B adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_2); #endif #endif } else { #if SAM3S || SAM3XA || SAM4S /* gain = 1 */ adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_0); #elif SAM3U #ifdef ADC_12B adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_0); #endif #endif } if (g_adc_test_mode.uc_offset_en) { #if SAM3S || SAM3XA || SAM4S adc_enable_anch(ADC); adc_enable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER); #elif SAM3U #ifdef ADC_12B adc12b_enable_input_offset(ADC12B); #endif #endif } else { #if SAM3S || SAM3XA || SAM4S adc_disable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER); #elif SAM3U #ifdef ADC_12B adc12b_disable_input_offset(ADC12B); #endif #endif } /* Set Auto Calibration Mode. */ #if SAM3S8 || SAM3SD8 || SAM4S if (g_adc_test_mode.uc_auto_calib_en) { adc_set_calibmode(ADC); while (1) { if ((adc_get_status(ADC) & ADC_ISR_EOCAL) == ADC_ISR_EOCAL) break; } } #endif #if SAM3S8 || SAM4S || SAM3N || SAM3SD8 /* Set power save. */ if (g_adc_test_mode.uc_power_save_en) { adc_configure_power_save(ADC, 1, 0); } else { adc_configure_power_save(ADC, 0, 0);; } #elif SAM3U || SAM4C #ifdef ADC_12B /* Set power save. */ if (g_adc_test_mode.uc_power_save_en) { adc12b_configure_power_save(ADC12B, 1, 0); } else { adc12b_configure_power_save(ADC12B, 0, 0);; } #else /* Set power save. */ if (g_adc_test_mode.uc_power_save_en) { adc_configure_power_save(ADC, 1); } else { adc_configure_power_save(ADC, 0);; } #endif #endif #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C /* Transfer with/without PDC. */ if (g_adc_test_mode.uc_pdc_en) { adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE); /* Enable PDC channel interrupt. */ adc_enable_interrupt(ADC, ADC_IER_RXBUFF); } else { /* Enable Data ready interrupt. */ adc_enable_interrupt(ADC, ADC_IER_DRDY); } /* Enable ADC interrupt. */ NVIC_EnableIRQ(ADC_IRQn); #elif SAM3U #ifdef ADC_12B /* Transfer with/without PDC. */ if (g_adc_test_mode.uc_pdc_en) { adc12_read_buffer(ADC12B, g_adc_sample_data.us_value, BUFFER_SIZE); /* Enable PDC channel interrupt. */ adc12b_enable_interrupt(ADC12B, ADC12B_IER_RXBUFF); } else { /* Enable Data ready interrupt. */ adc12b_enable_interrupt(ADC12B, ADC12B_IER_DRDY); } /* Enable ADC interrupt. */ NVIC_EnableIRQ(ADC12B_IRQn); #else /* Transfer with/without PDC. */ if (g_adc_test_mode.uc_pdc_en) { adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE); /* Enable PDC channel interrupt. */ adc_enable_interrupt(ADC, ADC_IER_RXBUFF); } else { /* Enable Data ready interrupt. */ adc_enable_interrupt(ADC, ADC_IER_DRDY); } /* Enable ADC interrupt. */ NVIC_EnableIRQ(ADC_IRQn); #endif #endif /* Configure trigger mode and start convention. */ switch (g_adc_test_mode.uc_trigger_mode) { case TRIGGER_MODE_SOFTWARE: #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C adc_configure_trigger(ADC, ADC_TRIG_SW, 0); /* Disable hardware trigger. */ #elif SAM3U #ifdef ADC_12B adc12b_configure_trigger(ADC12B, ADC12B_TRIG_SW); #else adc_configure_trigger(ADC, ADC_TRIG_SW); #endif #endif break; case TRIGGER_MODE_ADTRG: #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG); adc_configure_trigger(ADC, ADC_TRIG_EXT, 0); #elif SAM3U #ifdef ADC_12B gpio_configure_pin(PINS_ADC12B_TRIG, PINS_ADC12B_TRIG_FLAG); adc12b_configure_trigger(ADC12B, ADC12B_TRIG_EXT); #else gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG); adc_configure_trigger(ADC, ADC_TRIG_EXT); #endif #endif break; case TRIGGER_MODE_TIMER: configure_time_trigger(); break; #if SAM3S || SAM3U || SAM3XA || SAM4S case TRIGGER_MODE_PWM: configure_pwm_trigger(); break; #endif #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C case TRIGGER_MODE_FREERUN: adc_configure_trigger(ADC, ADC_TRIG_SW, 1); break; #endif default: break; } } /** * \brief Systick handler. */ void SysTick_Handler(void) { gs_ul_ms_ticks++; } #if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C /** * \brief Interrupt handler for the ADC. */ void ADC_Handler(void) { uint32_t i; uint32_t ul_temp; uint8_t uc_ch_num; /* With PDC transfer */ if (g_adc_test_mode.uc_pdc_en) { if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) { g_adc_sample_data.us_done = ADC_DONE_MASK; adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE); /* Only keep sample value, and discard channel number. */ for (i = 0; i < NUM_CHANNELS; i++) { g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk; } } } else { /* Without PDC transfer */ if ((adc_get_status(ADC) & ADC_ISR_DRDY) == ADC_ISR_DRDY) { ul_temp = adc_get_latest_value(ADC); for (i = 0; i < NUM_CHANNELS; i++) { uc_ch_num = (ul_temp & ADC_LCDR_CHNB_Msk) >> ADC_LCDR_CHNB_Pos; if (g_adc_sample_data.uc_ch_num[i] == uc_ch_num) { g_adc_sample_data.us_value[i] = ul_temp & ADC_LCDR_LDATA_Msk; g_adc_sample_data.us_done |= 1 << i; } } } } }
/** * \brief ACC example application entry point. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint8_t uc_key; int16_t s_volt = 0; uint32_t ul_value = 0; volatile uint32_t ul_status = 0x0; int32_t l_volt_dac0 = 0; /* Initialize the system */ sysclk_init(); board_init(); /* Initialize debug console */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Initialize DACC */ /* Enable clock for DACC */ pmc_enable_periph_clk(ID_DACC); /* Reset DACC registers */ dacc_reset(DACC); /* External trigger mode disabled. DACC in free running mode. */ dacc_disable_trigger(DACC); /* Half word transfer mode */ dacc_set_transfer_mode(DACC, 0); /* Power save: * sleep mode - 0 (disabled) * fast wake-up - 0 (disabled) */ dacc_set_power_save(DACC, 0, 0); /* Timing: * refresh - 0x08 (1024*8 dacc clocks) * max speed mode - 0 (disabled) * startup time - 0xf (960 dacc clocks) */ dacc_set_timing(DACC, 0x08, 0, 0xf); /* Disable TAG and select output channel DACC_CHANNEL */ dacc_set_channel_selection(DACC, DACC_CHANNEL_0); /* Enable output channel DACC_CHANNEL */ dacc_enable_channel(DACC, DACC_CHANNEL_0); /* Setup analog current */ dacc_set_analog_control(DACC, DACC_ANALOG_CONTROL); /* Set DAC0 output at ADVREF/2. The DAC formula is: * * (5/6 * VOLT_REF) - (1/6 * VOLT_REF) volt - (1/6 * VOLT_REF) * ----------------------------------- = -------------------------- * MAX_DIGITAL digit * * Here, digit = MAX_DIGITAL/2 */ dacc_write_conversion_data(DACC, MAX_DIGITAL / 2); l_volt_dac0 = (MAX_DIGITAL / 2) * (2 * VOLT_REF / 3) / MAX_DIGITAL + VOLT_REF / 6; /* Initialize ADC */ /* Enable clock for ADC */ pmc_enable_periph_clk(ID_ADC); /* * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 ) * For example, MCK = 64MHZ, PRESCAL = 4, then: * ADCClock = 64 / ((4+1) * 2) = 6.4MHz; */ adc_init(ADC, sysclk_get_cpu_hz(), ADC_CLOCK, ADC_STARTUP_TIME_SETTING); /* Formula: * Startup Time = startup value / ADCClock * Transfer Time = (TRANSFER * 2 + 3) / ADCClock * Tracking Time = (TRACKTIM + 1) / ADCClock * Settling Time = settling value / ADCClock * For example, ADC clock = 6MHz (166.7 ns) * Startup time = 512 / 6MHz = 85.3 us * Transfer Time = (1 * 2 + 3) / 6MHz = 833.3 ns * Tracking Time = (0 + 1) / 6MHz = 166.7 ns * Settling Time = 3 / 6MHz = 500 ns */ /* Set ADC timing */ adc_configure_timing(ADC, ADC_TRACK_SETTING, ADC_SETTLING_TIME_3, ADC_TRANSFER_SETTING); /* Channel 5 has to be compared */ adc_enable_channel(ADC, ADC_CHANNEL_5); //! [acc_enable_clock] /** Enable clock for ACC */ pmc_enable_periph_clk(ID_ACC); //! [acc_enable_clock] //! [acc_init] /** Initialize ACC */ acc_init(ACC, ACC_MR_SELPLUS_AD5, ACC_MR_SELMINUS_DAC0, ACC_MR_EDGETYP_ANY, ACC_MR_INV_DIS); //! [acc_init] //! [acc_irq_enable] /** Enable ACC interrupt */ NVIC_EnableIRQ(ACC_IRQn); /** Enable */ acc_enable_interrupt(ACC); //! [acc_irq_enable] dsplay_menu(); while (1) { while (uart_read(CONSOLE_UART, &uc_key)) { } printf("input: %c\r\n", uc_key); switch (uc_key) { case 's': case 'S': printf("Input DAC0 output voltage (%d~%d mv): ", (VOLT_REF / 6), (VOLT_REF * 5 / 6)); s_volt = get_input_voltage(); puts("\r"); if (s_volt > 0) { l_volt_dac0 = s_volt; /* The DAC formula is: * * (5/6 * VOLT_REF) - (1/6 * VOLT_REF) volt - (1/6 * VOLT_REF) * ----------------------------------- = -------------------------- * MAX_DIGITAL digit * */ ul_value = ((s_volt - (VOLT_REF / 6)) * (MAX_DIGITAL * 6) / 4) / VOLT_REF; dacc_write_conversion_data(DACC, ul_value); puts("-I- Set ok\r"); } else { puts("-I- Input voltage is invalid\r"); } break; case 'v': case 'V': /* Start conversion */ adc_start(ADC); ul_status = adc_get_status(ADC); while ((ul_status & ADC_ISR_EOC5) != ADC_ISR_EOC5) { ul_status = adc_get_status(ADC); } /* Conversion is done */ ul_value = adc_get_channel_value(ADC, ADC_CHANNEL_5); /* * Convert ADC sample data to voltage value: * voltage value = (sample data / max. resolution) * reference voltage */ s_volt = (ul_value * VOLT_REF) / MAX_DIGITAL; printf("-I- Voltage on potentiometer(AD5) is %d mv\n\r", s_volt); printf("-I- Voltage on DAC0 is %ld mv \n\r", (long)l_volt_dac0); break; case 'm': case 'M': dsplay_menu(); break; } } }
/** * \brief Test ADCIFE in Differential mode. * * \param test Current test case. */ static void run_adcife_diff_test(const struct test_case *test) { uint32_t timeout = ADC_NUM_OF_ATTEMPTS; bool conversion_timeout = false; struct adc_seq_config adc_seq_cfg = { /* Select Vref for shift cycle */ .zoomrange = ADC_ZOOMRANGE_0, /* Pad Ground */ .muxneg = ADC_MUXNEG_1, /* Scaled Vcc, Vcc/10 */ .muxpos = ADC_MUXPOS_2, /* Enables the internal voltage sources */ .internal = ADC_INTERNAL_3, /* Disables the ADC gain error reduction */ .gcomp = ADC_GCOMP_DIS, /* Disables the HWLA mode */ .hwla = ADC_HWLA_DIS, /* 12-bits resolution */ .res = ADC_RES_12_BIT, /* Enables the differential mode */ .bipolar = ADC_BIPOLAR_DIFFERENTIAL }; struct adc_ch_config adc_ch_cfg = { .seq_cfg = &adc_seq_cfg, /* Internal Timer Max Counter */ .internal_timer_max_count = 60, /* Window monitor mode is off */ .window_mode = 0, .low_threshold = 0, .high_threshold = 0, }; adc_ch_set_config(&g_adc_inst, &adc_ch_cfg); adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); while (!((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) == ADCIFE_SR_SEOC)) { if (!timeout--) { conversion_timeout = true; } } test_assert_true(test, conversion_timeout == false, "ADCIFE Differential conversion timeout"); /* Because selected channel is positive input, then in differential mode * the output conversion result will = 2047 + (Vin/Vref)*2047. */ test_assert_true(test, adc_get_last_conv_value(&g_adc_inst) > 2047, "ADCIFE Differential test failed"); } /** * \brief Test ADCIFE in internal timer trigger mode, * which also tests interrupt driven conversions. * * \param test Current test case. */ static void run_adcife_itimer_trig_test(const struct test_case *test) { struct adc_seq_config adc_seq_cfg = { /* Select Vref for shift cycle */ .zoomrange = ADC_ZOOMRANGE_0, /* Pad Ground */ .muxneg = ADC_MUXNEG_1, /* Scaled Vcc, Vcc/10 */ .muxpos = ADC_MUXPOS_2, /* Enables the internal voltage sources */ .internal = ADC_INTERNAL_3, /* Disables the ADC gain error reduction */ .gcomp = ADC_GCOMP_DIS, /* Disables the HWLA mode */ .hwla = ADC_HWLA_DIS, /* 12-bits resolution */ .res = ADC_RES_12_BIT, /* Enables the single-ended mode */ .bipolar = ADC_BIPOLAR_SINGLEENDED }; struct adc_ch_config adc_ch_cfg = { .seq_cfg = &adc_seq_cfg, /* Internal Timer Max Counter */ .internal_timer_max_count = 60, /* Window monitor mode is off */ .window_mode = 0, .low_threshold = 0, .high_threshold = 0, }; adc_ch_set_config(&g_adc_inst, &adc_ch_cfg); adc_set_callback(&g_adc_inst, ADC_SEQ_SEOC, adcife_set_conv_flag, ADCIFE_IRQn, 1); adc_configure_trigger(&g_adc_inst, ADC_TRIG_INTL_TIMER); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); adc_configure_itimer_period(&g_adc_inst, adc_ch_cfg.internal_timer_max_count); adc_start_itimer(&g_adc_inst); delay_ms(100); test_assert_true(test, g_uc_condone_flag == 1, "ADCIFE Internal Timer trigger test failed"); } /* When VDDANA is in MIN value = 2.4V, the equivalent voltage value is * (2400 * 255) / ((1 << 10) - 1) = 598mv. The relative digital value is * 598 * 4095 / 1000 = 2449. */ #define DAC_INTERNAL_MIN_VALUE 2449 /* When VDDANA is in MAX value = 3.6V the equivalent voltage value is * (3600 * 255) / ((1 << 10) - 1) = 897mv. The relative digital value is * 897 * 4095 / 1000 = 3673. */ #define DAC_INTERNAL_MAX_VALUE 3673 /* When VCC is in MIN value = 1.6V, the equivalent voltage value is * 1600 / 10 = 160mv. The relative digital value is * 160 * 4095 / 1000 = 434. */ #define VCC_SCALED_MIN_VALUE 434 /* When VCC is in MAX value = 3.6V, the equivalent voltage value is * 3600 / 10 = 360mv. The relative digital value is * 360 * 4095 / 1000 = 1474. */ #define VCC_SCALED_MAX_VALUE 1474 /** * \brief Test ADCIFE in multiple channel mode. * * \param test Current test case. */ static void run_adcife_multichannel_test(const struct test_case *test) { start_dac(); adc_pdca_set_config(&g_adc_pdca_cfg); pdca_channel_set_callback(CONFIG_ADC_PDCA_RX_CHANNEL, pdca_transfer_done, PDCA_0_IRQn, 1, PDCA_IER_TRC); adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); delay_ms(100); /* The DAC output voltage value is 823mv, so the equivalent ADC value should be * 4095 * 823 / 1000 = 3370. The scaled VCC output voltage is 330mv, so the * equivalent ADC value should be 4095 * 330 / 1000 = 1351. */ test_assert_true(test, ((DAC_INTERNAL_MIN_VALUE < g_adc_sample_data[0] < DAC_INTERNAL_MAX_VALUE) && (VCC_SCALED_MIN_VALUE < g_adc_sample_data[1] < VCC_SCALED_MAX_VALUE)), "ADCIFE Multichannel test failed"); } /** * \brief Test ADCIFE in window monitor mode. * * \param test Current test case. */ static void run_adcife_wm_test(const struct test_case *test) { struct adc_seq_config adc_seq_cfg = { /* Select Vref for shift cycle */ .zoomrange = ADC_ZOOMRANGE_0, /* Pad Ground */ .muxneg = ADC_MUXNEG_1, /* Scaled Vcc, Vcc/10 */ .muxpos = ADC_MUXPOS_2, /* Enables the internal voltage sources */ .internal = ADC_INTERNAL_3, /* Disables the ADC gain error reduction */ .gcomp = ADC_GCOMP_DIS, /* Disables the HWLA mode */ .hwla = ADC_HWLA_DIS, /* 12-bits resolution */ .res = ADC_RES_12_BIT, /* Enables the single-ended mode */ .bipolar = ADC_BIPOLAR_SINGLEENDED }; struct adc_ch_config adc_ch_cfg = { .seq_cfg = &adc_seq_cfg, /* Internal Timer Max Counter */ .internal_timer_max_count = 60, /* Window monitor mode is off */ .window_mode = ADC_WM_MODE_3, /* The equivalent voltage value is 205 * 1000 / 4095 = 50mv. */ .low_threshold = 205, /* The equivalent voltage value is 2050 * 1000 / 4095 = 500mv. */ .high_threshold = 2050, }; adc_ch_set_config(&g_adc_inst, &adc_ch_cfg); adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); adc_set_callback(&g_adc_inst, ADC_WINDOW_MONITOR, adcife_set_wm_flag, ADCIFE_IRQn, 1); delay_ms(100); test_assert_true(test, g_uc_enter_win_flag == 1, "ADCIFE Inside Window Mode test failed"); /* The teseted channel voltage is outside window */ adc_disable(&g_adc_inst); g_uc_enter_win_flag = 0; adc_seq_cfg.muxpos = ADC_MUXPOS_3; adc_ch_set_config(&g_adc_inst, &adc_ch_cfg); adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); delay_ms(100); test_assert_true(test, g_uc_enter_win_flag == 0, "ADCIFE Outside Window Mode test failed"); } /** * \brief Run ADCIFE driver unit tests. */ int main(void) { const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS }; /* Initialize the system clock and board */ sysclk_init(); board_init(); /* Enable the debug uart */ stdio_serial_init(CONF_TEST_USART, &usart_serial_options); #if defined(__GNUC__) setbuf(stdout, NULL); #endif /* Define all the test cases */ DEFINE_TEST_CASE(adcife_init_test, NULL, run_adcife_init_test, NULL, "ADCIFE Initialize test"); DEFINE_TEST_CASE(adcife_diff_test, NULL, run_adcife_diff_test, NULL, "ADCIFE Differential test"); DEFINE_TEST_CASE(adcife_itmer_trig_test, NULL, run_adcife_itimer_trig_test, NULL, "ADCIFE Internal Timer trigger test"); DEFINE_TEST_CASE(adcife_multichannel_test, NULL, run_adcife_multichannel_test, NULL, "ADCIFE Multichannel test"); DEFINE_TEST_CASE(adcife_wm_test, NULL, run_adcife_wm_test, NULL, "ADCIFE Window Monitor Mode test"); /* Put test case addresses in an array */ DEFINE_TEST_ARRAY(adcife_tests) = { &adcife_init_test, &adcife_diff_test, &adcife_itmer_trig_test, &adcife_multichannel_test, &adcife_wm_test, }; /* Define the test suite */ DEFINE_TEST_SUITE(adcife_suite, adcife_tests, "SAM ADCIFE driver test suite"); /* Run all tests in the test suite */ test_suite_run(&adcife_suite); while (1) { /* Busy-wait forever. */ } }