/** \brief Main function - init and loop to display ADC values */ int main(void) { /* GPIO pin/ADC-function map. */ const gpio_map_t ADCIFB_GPIO_MAP = { {EXAMPLE_ADCIFB_PIN, EXAMPLE_ADCIFB_FUNCTION} }; /* ADCIFB Configuration */ adcifb_opt_t adcifb_opt = { /* Resolution mode */ .resolution = AVR32_ADCIFB_ACR_RES_12BIT, /* Channels Sample & Hold Time in [0,15] */ .shtim = 15, .ratio_clkadcifb_clkadc = (sysclk_get_pba_hz() / EXAMPLE_TARGET_CLK_ADC_FREQ_HZ), /* * Startup time in [0,127], where * Tstartup = startup * 8 * Tclk_adc (assuming Tstartup ~ 15us max) */ .startup = 3, /* ADCIFB Sleep Mode disabled */ .sleep_mode_enable = false }; uint32_t adc_data; /* Initialize the system clocks */ sysclk_init(); /* Init debug serial line */ init_dbg_rs232(sysclk_get_pba_hz()); /* Assign and enable GPIO pins to the ADC function. */ gpio_enable_module(ADCIFB_GPIO_MAP, sizeof(ADCIFB_GPIO_MAP) / sizeof(ADCIFB_GPIO_MAP[0])); /* Enable and configure the ADCIFB module */ if (adcifb_configure(&AVR32_ADCIFB, &adcifb_opt) != PASS) { /* Config error. */ while (true) { gpio_tgl_gpio_pin(LED0_GPIO); delay_ms(100); } } /* Configure the trigger mode */ /* "No trigger, only software trigger can start conversions". */ if (adcifb_configure_trigger(&AVR32_ADCIFB, AVR32_ADCIFB_TRGMOD_NT, 0) != PASS) { /* Config error. */ while (true) { gpio_tgl_gpio_pin(LED1_GPIO); delay_ms(100); } } /* Enable the ADCIFB channel the battery is connected to. */ adcifb_channels_enable(&AVR32_ADCIFB, EXAMPLE_ADCIFB_CHANNEL_MASK); while (true) { while (adcifb_is_ready(&AVR32_ADCIFB) != true) { /* Wait until the ADC is ready to perform a conversion. */ } /* Start an ADCIFB conversion sequence. */ adcifb_start_conversion_sequence(&AVR32_ADCIFB); while (adcifb_is_drdy(&AVR32_ADCIFB) != true) { /* Wait until the converted data is available. */ } /* Get the last converted data. */ adc_data = adcifb_get_last_data(&AVR32_ADCIFB); /* Display the current voltage of the battery. */ print_dbg("\x1B[2J\x1B[H\r\nADCIFB Example\r\nHEX Value for " EXAMPLE_ADCIFB_CHANNEL_NAME " : 0x"); print_dbg_hex(adc_data & AVR32_ADCIFB_LCDR_LDATA_MASK); print_dbg("\r\n"); delay_ms(500); /* * Note1: there is a resistor bridge between the battery and the * ADC pad on the AT32UC3L-EK. The data converted is thus half * of * the battery voltage. */ /* * Note2: if the battery is not in place, the conversion is out * of * spec because the ADC input is then higher than ADVREF. */ } }
//##################################################### void adc_init(unsigned long chanels_mask, unsigned char mode, unsigned short period) { // Assign and enable GPIO pin to the ADC function. if(chanels_mask & (1 << 0)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_0_PIN, AVR32_ADCIFB_AD_0_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 0); } if(chanels_mask & (1 << 1)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_1_PIN, AVR32_ADCIFB_AD_1_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 1); } if(chanels_mask & (1 << 2)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_2_PIN, AVR32_ADCIFB_AD_2_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 2); } if(chanels_mask & (1 << 3)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_3_PIN, AVR32_ADCIFB_AD_3_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 3); } if(chanels_mask & (1 << 4)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_4_PIN, AVR32_ADCIFB_AD_4_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 4); } if(chanels_mask & (1 << 5)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_5_PIN, AVR32_ADCIFB_AD_5_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 5); } if(chanels_mask & (1 << 6)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_6_PIN, AVR32_ADCIFB_AD_6_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 6); } if(chanels_mask & (1 << 7)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_7_PIN, AVR32_ADCIFB_AD_7_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 7); } unsigned long pba_clock = sysclk_get_pba_hz(); adcifb_opt_t adcifb_opt = { .resolution = AVR32_ADCIFB_ACR_RES_8BIT, .shtim = 15, .ratio_clkadcifb_clkadc = pba_clock / 6000000, .startup = 3, .sleep_mode_enable = false }; // Enable and configure the ADCIFB module sysclk_enable_peripheral_clock(&AVR32_ADCIFB); adcifb_configure(&AVR32_ADCIFB, &adcifb_opt); // Configure the trigger (No trigger, only software trigger) adcifb_configure_trigger(&AVR32_ADCIFB, mode /*AVR32_ADCIFB_TRGR_TRGMOD_PT*/, period); adcifb_channels_enable(&AVR32_ADCIFB, chanels_mask); } //##################################################### void adc_channels_enable_pio(unsigned long chanels_mask) { // Assign and enable GPIO pin to the ADC function. if(chanels_mask & (1 << 0)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_0_PIN, AVR32_ADCIFB_AD_0_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 0); } if(chanels_mask & (1 << 1)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_1_PIN, AVR32_ADCIFB_AD_1_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 1); } if(chanels_mask & (1 << 2)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_2_PIN, AVR32_ADCIFB_AD_2_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 2); } if(chanels_mask & (1 << 3)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_3_PIN, AVR32_ADCIFB_AD_3_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 3); } if(chanels_mask & (1 << 4)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_4_PIN, AVR32_ADCIFB_AD_4_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 4); } if(chanels_mask & (1 << 5)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_5_PIN, AVR32_ADCIFB_AD_5_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 5); } if(chanels_mask & (1 << 6)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_6_PIN, AVR32_ADCIFB_AD_6_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 6); } if(chanels_mask & (1 << 7)) { gpio_enable_module_pin(AVR32_ADCIFB_AD_7_PIN, AVR32_ADCIFB_AD_7_FUNCTION); //adcifb_channels_enable(&AVR32_ADCIFB, 1 << 7); } adcifb_channels_enable(&AVR32_ADCIFB, chanels_mask); } //##################################################### void adc_channels_enable(unsigned long chanels_mask) { adcifb_channels_enable(&AVR32_ADCIFB, chanels_mask); }
/** * \brief Initialize ADC driver to read the board temperature sensor. * * Initializes the board's ADC driver module and configures the ADC channel * connected to the onboard NTC temperature sensor ready for conversions. */ static void init_adc(void) { // Assign and enable GPIO pin to the ADC function. gpio_enable_module_pin(ADC_TEMPERATURE_PIN, ADC_TEMPERATURE_FUNCTION); const adcifb_opt_t adcifb_opt = { .resolution = AVR32_ADCIFB_ACR_RES_12BIT, .shtim = 15, .ratio_clkadcifb_clkadc = 2, .startup = 3, .sleep_mode_enable = false }; // Enable and configure the ADCIFB module sysclk_enable_peripheral_clock(&AVR32_ADCIFB); adcifb_configure(&AVR32_ADCIFB, &adcifb_opt); // Configure the trigger (No trigger, only software trigger) adcifb_configure_trigger(&AVR32_ADCIFB, AVR32_ADCIFB_TRGMOD_NT, 0); // Enable the ADCIFB channel to NTC temperature sensor adcifb_channels_enable(&AVR32_ADCIFB, ADC_TEMPERATURE_CHANNEL); } /** * \brief Initializes the USART. * * Initializes the board USART ready for serial data to be transmitted and * received. */ static void init_usart(void) { const usart_options_t usart_options = { .baudrate = 57600, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_1_STOPBIT, .channelmode = USART_NORMAL_CHMODE }; // Initialize USART in RS232 mode with the requested settings. sysclk_enable_peripheral_clock(USART); usart_init_rs232(USART, &usart_options, sysclk_get_pba_hz()); } /** * \brief Initializes the PWM subsystem ready to generate the RGB LED PWM * waves. * * Initializes the on-chip PWM module and configures the RGB LED PWM outputs so * the the brightness of the three individual channels can be adjusted. */ static void init_pwm(void) { // GPIO pin/function map for the RGB LEDs. gpio_enable_module_pin(LED_RED_PWMA, LED_PWMA_FUNCTION); gpio_enable_module_pin(LED_GREEN_PWMA, LED_PWMA_FUNCTION); gpio_enable_module_pin(LED_BLUE_PWMA, LED_PWMA_FUNCTION); const scif_gclk_opt_t genclk3_opt = { .clock_source = SCIF_GCCTRL_CPUCLOCK, .divider = 8, .diven = true, }; // Start generic clock 3 for the PWM outputs. scif_start_gclk(AVR32_PM_GCLK_GCLK3, &genclk3_opt); // Enable RGB LED PWM. sysclk_enable_peripheral_clock(&AVR32_PWMA); pwma_config_enable(&AVR32_PWMA,EXAMPLE_PWMA_FREQUENCY,EXAMPLE_PWMA_GCLK_FREQUENCY,0); pwma_set_channels_value(&AVR32_PWMA,PWM_CHANNEL_RED | PWM_CHANNEL_BLUE| PWM_CHANNEL_GREEN,255); } /** * \brief Application main loop. */ int main(void) { board_init(); sysclk_init(); sysclk_enable_peripheral_clock(USART); // Initialize touch, ADC, USART and PWM init_adc(); init_usart(); init_pwm(); init_touch(); while (true) { uint32_t adc_data; // Read slider and button and update RGB led touch_handler(); // Wait until the ADC is ready to perform a conversion. do { } while (!adcifb_is_ready(&AVR32_ADCIFB)); // Start an ADCIFB conversion sequence. adcifb_start_conversion_sequence(&AVR32_ADCIFB); // Wait until the converted data is available. do { } while (!adcifb_is_drdy(&AVR32_ADCIFB)); // Get the last converted data. adc_data = (adcifb_get_last_data(&AVR32_ADCIFB) & 0x3FF); // Write temperature data to USART do { } while (!usart_tx_empty(USART)); usart_write_char(USART, (adc_data >> 8)); do { } while (!usart_tx_empty(USART)); usart_write_char(USART, (adc_data & 0xFF)); } }
/** * \brief Initializes the ADCIFB module with trigger * - Initialize the trigger mode & compare interrupts for ADCIFB * * \retval STATUS_OK Configuration OK * \retval ERR_TIMEOUT Timeout on configuring ADCIFB module * \retval ERR_BUSY ADCIFB module unable to configure the trigger */ static status_code_t adc_init() { /* GPIO pin/adc - function map. */ static const gpio_map_t ADCIFB_GPIO_MAP = { {EXAMPLE_ADCIFB_PIN, EXAMPLE_ADCIFB_FUNCTION} }; /* ADCIFB Configuration */ adcifb_opt_t adcifb_opt = { /* Resolution mode */ .resolution = AVR32_ADCIFB_ACR_RES_10BIT, /* Channels Sample & Hold Time in [0,15] */ .shtim = ADC_SAMPLE_HOLD_TIME, /* ADC Clock Prescaler */ .ratio_clkadcifb_clkadc = (sysclk_get_pba_hz()) / ADC_FREQUENCY, .startup = ADC_STARTUP_TIME, /* ADCIFB Sleep Mode enabled */ .sleep_mode_enable = true }; /* Disable pull up on ADCIFB channel input pin */ gpio_disable_pin_pull_up(EXAMPLE_ADCIFB_PIN); /* Enable the ADC pins */ gpio_enable_module(ADCIFB_GPIO_MAP, sizeof(ADCIFB_GPIO_MAP) / sizeof(ADCIFB_GPIO_MAP[0])); /* Enable ADCIFB clock */ sysclk_enable_pba_module(SYSCLK_ADCIFB); /* Configure the ADCIFB peripheral */ if (adcifb_configure(adcifb, &adcifb_opt)) { /* Error configuring the ADCIFB */ return ERR_TIMEOUT; } /* Configure the trigger for ADCIFB peripheral */ if (adcifb_configure_trigger(adcifb, AVR32_ADCIFB_TRGR_TRGMOD_EVT, 0)) { /* Error configuring the trigger for ADCIFB */ return ERR_BUSY; } /* Enable ADCIFB Channel 0 */ adcifb_channels_enable(adcifb, EXAMPLE_ADCIFB_CHANNEL); /* Disable global interrupts */ cpu_irq_disable(); /* * Initialize the interrupt vectors * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_initialize_vectors(); /* * Register the ADCIFB interrupt handler * Note: This function adds nothing for IAR as the interrupts are * handled by the IAR compiler itself. It provides an abstraction * between GCC & IAR compiler to use interrupts. * Refer function implementation in interrupt_avr32.h */ irq_register_handler(&ADCIFB_interrupt_handler, AVR32_ADCIFB_IRQ, ADC_INTERRUPT_PRIORITY); /* * Set the threshold value in CVR.LV register to generate interrupt * when the value detected is above the threshold. * 1.500 V with 10-bit resolution */ adcifb_set_high_compare_value(adcifb, ADC_COMPARE_VALUE); /* Enable the Analog Compare option in ADCIFB */ adcifb_enable_analog_compare_mode(adcifb); /* Enable the data ready interrupt for ADCIFB */ adcifb_enable_compare_gt_interrupt(adcifb); return STATUS_OK; } /* End of adc_init() */ /** * \brief Asynchronous Timer Initialization * - Start the 32KHz Oscillator * - Initializes the AST module with periodic trigger events * * \retval STATUS_OK Configuration OK * \retval ERR_TIMEOUT Error in configuring the AST module */ static status_code_t ast_init() { /* Initial Count value to write in AST */ unsigned long ast_counter = 0; /* Set the prescaler to set a periodic trigger from AST */ avr32_ast_pir0_t pir = { .insel = AST_TRIGGER_PRESCALER }; /* Set the OSC32 parameters */ scif_osc32_opt_t osc32_opt = { .mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR, .startup = OSC32_STARTUP_8192, .pinsel = BOARD_OSC32_PINSEL, .en1k = false, .en32k = true }; /* Enable the 32KHz Oscillator */ scif_start_osc32(&osc32_opt, true); /* Enable the Peripheral Event System Clock */ sysclk_enable_hsb_module(SYSCLK_EVENT); /* Enable PBA clock for AST clock to switch its source */ sysclk_enable_pba_module(SYSCLK_AST); /* Initialize the AST in counter mode */ if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER, ast_counter)) { return ERR_TIMEOUT; } /* Initialize the periodic value register with the prescaler */ ast_set_periodic0_value(&AVR32_AST, pir); /* Enable the AST periodic event */ ast_enable_periodic0(&AVR32_AST); /* Clear All AST Interrupt request and clear SR */ ast_clear_all_status_flags(&AVR32_AST); /* Enable the AST */ ast_enable(&AVR32_AST); /* Disable PBA clock for AST after switching its source to OSC32 */ sysclk_disable_pba_module(SYSCLK_AST); return STATUS_OK; } /* End of ast_init() */ /** * \brief Low Power Configuration * Initializes the power saving measures to reduce power consumption * - Enable pullups on GPIO pins * - Disable the clocks to unused modules * - Disable internal voltage regulator when in 1.8V supply mode */ static void power_save_measures_init() { uint8_t i; uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0}; /* * Enable internal pull-ups on all unused GPIO pins * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they * are not used as an oscillator or JTAG pin respectively. */ for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) { gpio_mask[gpio_used_pins[i] >> 5] |= 1 << (gpio_used_pins[i] & 0x1F); } for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) { gpio_configure_group(i, ~(gpio_mask[i]), GPIO_PULL_UP | GPIO_DIR_INPUT); } /* Disable OCD clock which is not disabled by sysclk service */ sysclk_disable_cpu_module(SYSCLK_OCD); #if POWER_SUPPLY_MODE_1_8V /* * When using 1.8V Single supply mode, the Voltage Regulator can be * shut-down using the code below, in-order to save power. * See Voltage Regulator Calibration Register in datasheet for more *info. * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator * cannot be shut-down and the application will hang in this loop. */ uint32_t tmp = (AVR32_SCIF.vregcr); tmp &= (~(1 << 5 | 1 << 18)); AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR; AVR32_SCIF.vregcr = tmp; /* Wait until internal voltage regulator is disabled. */ while ((AVR32_SCIF.vregcr & 0x00040020)) { } #endif } /* End of power_save_measures_init() */