本程序,有两种ADC模式可选择,一种 正常模式,一种 增加模式,本例可通过串口显示结果,也可通过串口切换ADC模式。
而ADC是通过不断查询ADC中断来完成的。然后把结果显示到串口。
以下是运行的截图:
以下是运行的程序:
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #include "asf.h"
- /** Reference voltage for AFEC in mv. */
- #define VOLT_REF (3300)
- /** The maximal digital value */
- #define MAX_DIGITAL_12_BIT (4095UL)
- #define STRING_EOL "\r"
- #define STRING_HEADER "-- AFEC Enhanced Resolution Example --\r\n" \
- "-- "BOARD_NAME" --\r\n" \
- "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
- #define MENU_HEADER "\n\r-- press a key to change the resolution mode--\n\r" \
- "-- n: Normal Resolution Mode--\n\r" \
- "-- e: Enhanced Resolution Mode--\n\r" \
- "-- q: Quit Configuration--\n\r"
- /** AFEC sample data */
- struct {
- uint32_t value;
- bool is_done;
- } g_afec_sample_data;
- /** The maximal digital value */
- static uint32_t g_max_digital;
- /**
- * \brief Configure UART console.
- */
- static void configure_console(void)
- {
- const usart_serial_options_t uart_serial_options = {
- .baudrate = CONF_UART_BAUDRATE,
- .paritytype = CONF_UART_PARITY
- };
- /* Configure console UART. */
- sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
- stdio_serial_init(CONF_UART, &uart_serial_options);
- }
- /**
- * \brief Display main menu.
- */
- static void display_menu(void)
- {
- puts(MENU_HEADER);
- }
- /**
- * \brief Set AFEC resolution mode.
- */
- static void set_afec_resolution(void)
- {
- uint8_t uc_key;
- uint8_t uc_done = 0;
- display_menu();
- while (!uc_done) {
- while (uart_read(CONF_UART, &uc_key));
- switch (uc_key) {
- case 'n':
- g_max_digital = MAX_DIGITAL_12_BIT;
- afec_set_resolution(AFEC0, AFEC_12_BITS);
- puts(" Set Resolution to Normal \n\r");
- break;
- case 'e':
- g_max_digital = MAX_DIGITAL_12_BIT * 16;
- afec_set_resolution(AFEC0, AFEC_16_BITS);
- puts(" Set Resolution to Enhanced \n\r");
- break;
- case 'q':
- uc_done = 1;
- puts(" Quit Configuration \n\r");
- break;
- default:
- break;
- }
- }
- }
- /**
- * \brief AFEC interrupt callback function.
- */
- static void afec_data_ready(void)
- {
- g_afec_sample_data.value = afec_get_latest_value(AFEC0);
- g_afec_sample_data.is_done = true;
- }
- /**
- * \brief Application entry point.
- *
- * \return Unused (ANSI-C compatibility).
- */
- int main(void)
- {
- uint8_t uc_key;
- /* Initialize the SAM system. */
- sysclk_init();
- board_init();
- configure_console();
- /* Output example information. */
- puts(STRING_HEADER);
- g_afec_sample_data.value = 0;
- g_afec_sample_data.is_done = false;
- g_max_digital = MAX_DIGITAL_12_BIT;
- afec_enable(AFEC0);
- struct afec_config afec_cfg;
- afec_get_config_defaults(&afec_cfg);
- afec_init(AFEC0, &afec_cfg);
- struct afec_ch_config afec_ch_cfg;
- afec_ch_get_config_defaults(&afec_ch_cfg);
- afec_ch_set_config(AFEC0, AFEC_CHANNEL_POTENTIOMETER, &afec_ch_cfg);
- /*
- * Because the internal ADC offset is 0x800, it should cancel it and shift
- * down to 0.
- */
- afec_channel_set_analog_offset(AFEC0, AFEC_CHANNEL_POTENTIOMETER, 0x800);
- afec_set_trigger(AFEC0, AFEC_TRIG_SW);
- /* Enable channel for potentiometer. */
- afec_channel_enable(AFEC0, AFEC_CHANNEL_POTENTIOMETER);
- afec_set_callback(AFEC0, AFEC_INTERRUPT_DATA_READY, afec_data_ready, 1);
- display_menu();
- afec_start_calibration(AFEC0);
- while((afec_get_interrupt_status(AFEC0) & AFEC_ISR_EOCAL) != AFEC_ISR_EOCAL);
- while (1) {
- afec_start_software_conversion(AFEC0);
- delay_ms(1000);
- /* Check if AFEC sample is done. */
- if (g_afec_sample_data.is_done == true) {
- printf("Potentiometer Voltage: %4d mv.",
- (int)(g_afec_sample_data.value * VOLT_REF
- / g_max_digital));
- puts("\r");
- g_afec_sample_data.is_done = false;
- }
- /* Check if the user enters a key. */
- if (!uart_read(CONF_UART, &uc_key)) {
- /* Disable all afec interrupt. */
- afec_disable_interrupt(AFEC0, AFEC_INTERRUPT_ALL);
- set_afec_resolution();
- afec_enable_interrupt(AFEC0, AFEC_INTERRUPT_DATA_READY);
- }
- }
- }
|