Пример #1
0
/**
 * \brief Start ADC sample.
 * Initialize ADC, set clock and timing, and set ADC to given mode.
 */
static void start_adc(void)
{
	struct adc_config adc_cfg = {
		/* System clock division factor is 16 */
		.prescal = ADC_PRESCAL_DIV16,
		/* The APB clock is used */
		.clksel = ADC_CLKSEL_APBCLK,
		/* Max speed is 150K */
		.speed = ADC_SPEED_150K,
		/* ADC Reference voltage is 0.625*VCC */
		.refsel = ADC_REFSEL_1,
		/* Enables the Startup time */
		.start_up = CONFIG_ADC_STARTUP
	};
	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* DAC internal */
		.muxpos = ADC_MUXPOS_3,
		/* 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,
	};
	if(adc_init(&g_adc_inst, ADCIFE, &adc_cfg) != STATUS_OK) {
		puts("-F- ADC Init Fail!\n\r");
		while(1);
	}
	if(adc_enable(&g_adc_inst) != STATUS_OK) {
		puts("-F- ADC Enable Fail!\n\r");
		while(1);
	}

	if (g_adc_test_mode.uc_pdc_en) {
		adc_disable_interrupt(&g_adc_inst, ADC_SEQ_SEOC);
		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);
	} else {
		pdca_channel_disable_interrupt(CONFIG_ADC_PDCA_RX_CHANNEL,
				PDCA_IDR_TRC);
		pdca_channel_disable_interrupt(CONFIG_ADC_PDCA_TX_CHANNEL,
				PDCA_IDR_TRC);
		adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
		adc_set_callback(&g_adc_inst, ADC_SEQ_SEOC, adcife_read_conv_result,
				ADCIFE_IRQn, 1);
	}

	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_SW);
		break;
	case TRIGGER_MODE_CON:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
		break;
	case TRIGGER_MODE_ITIMER:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_INTL_TIMER);
		adc_configure_itimer_period(&g_adc_inst,
				adc_ch_cfg.internal_timer_max_count);
		adc_start_itimer(&g_adc_inst);
		break;
	default:
		break;
	}

	if (g_adc_test_mode.uc_gain_en) {
		adc_configure_gain(&g_adc_inst, ADC_GAIN_2X);
	} else {
		adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);
	}
}

/**
 * \brief Start DAC ouput.
 * Initialize DAC, set clock and timing, and set DAC to given mode.
 */
static void start_dac(void)
{
	sysclk_enable_peripheral_clock(DACC);

	/* Reset DACC registers */
	dacc_reset(DACC);

	/* Half word transfer mode */
	dacc_set_transfer_mode(DACC, 0);

	/* Timing:
	 * startup                - 0x10 (17 clocks)
	 * internal trigger clock - 0x60 (96 clocks)
	 */
	dacc_set_timing(DACC, 0x10, 0x60);

	/* Enable DAC */
	dacc_enable(DACC);

	/* The DAC is 10-bit resolution, so output voltage should be
	 * (3300 * 255) / ((1 << 10) - 1) = 823mv */
	dacc_write_conversion_data(DACC, 0xFF);
}
Пример #2
0
/**
 * \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. */
	}
}