123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /*
- * File : adc.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date Author Notes
- * 2017-12-04 Haley the first version
- */
- #include <rtdevice.h>
- #include "am_mcu_apollo.h"
- #include "board.h"
- #ifdef RT_USING_ADC
- /* sem define */
- rt_sem_t adcsem = RT_NULL;
- #define BATTERY_GPIO 29 /* Battery */
- #define BATTERY_ADC_PIN AM_HAL_PIN_29_ADCSE1
- #define BATTERY_ADC_CHANNEL AM_HAL_ADC_SLOT_CHSEL_SE1 /* BATTERY ADC采集通道 */
- #define BATTERY_ADC_CHANNELNUM 1 /* BATTERY ADC采集通道号 */
- #define ADC_CTIMER_NUM 3 /* ADC使用定时器 */
- #define ADC_CHANNEL_NUM 1 /* ADC采集通道个数 */
- #define ADC_SAMPLE_NUM 8 /* ADC采样个数, NE_OF_OUTPUT */
- rt_uint8_t bat_adc_cnt = (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM;
- rt_int16_t am_adc_buffer_pool[64];
- rt_uint8_t am_adc_data_get(rt_int16_t *buff, rt_uint16_t size)
- {
- /* wait adc interrupt release sem forever */
- rt_sem_take(adcsem, RT_WAITING_FOREVER);
- /* copy the data */
- rt_memcpy(buff, am_adc_buffer_pool, size*sizeof(rt_int16_t));
- return 0;
- }
- void am_adc_start(void)
- {
- /* adcsem create */
- adcsem = rt_sem_create("adcsem", 0, RT_IPC_FLAG_FIFO);
- /* Start the ctimer */
- am_hal_ctimer_start(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
- /* Trigger the ADC once */
- am_hal_adc_trigger();
- }
- void am_adc_stop(void)
- {
- /* Stop the ctimer */
- am_hal_ctimer_stop(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
- /* adcsem delete */
- rt_sem_delete(adcsem);
- }
- /**
- * @brief Interrupt handler for the ADC
- *
- * This function is Interrupt handler for the ADC
- *
- * @return None.
- */
- void am_adc_isr(void)
- {
- uint32_t ui32Status, ui32FifoData;
- /* Read the interrupt status */
- ui32Status = am_hal_adc_int_status_get(true);
- /* Clear the ADC interrupt */
- am_hal_adc_int_clear(ui32Status);
- /* If we got a FIFO 75% full (which should be our only ADC interrupt), go ahead and read the data */
- if (ui32Status & AM_HAL_ADC_INT_FIFOOVR1)
- {
- do
- {
- /* Read the value from the FIFO into the circular buffer */
- ui32FifoData = am_hal_adc_fifo_pop();
- if(AM_HAL_ADC_FIFO_SLOT(ui32FifoData) == BATTERY_ADC_CHANNELNUM)
- am_adc_buffer_pool[bat_adc_cnt++] = AM_HAL_ADC_FIFO_SAMPLE(ui32FifoData);
- if(bat_adc_cnt > (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM - 1)
- {
- /* shift data */
- rt_memmove(am_adc_buffer_pool, am_adc_buffer_pool + ADC_CHANNEL_NUM*ADC_SAMPLE_NUM, ADC_CHANNEL_NUM*ADC_SAMPLE_NUM*sizeof(rt_int16_t));
- bat_adc_cnt = (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM;
- /* release adcsem */
- rt_sem_release(adcsem);
- }
- } while (AM_HAL_ADC_FIFO_COUNT(ui32FifoData) > 0);
- }
- }
- static void timerA3_for_adc_init(void)
- {
- /* Start a timer to trigger the ADC periodically (1 second) */
- am_hal_ctimer_config_single(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA,
- AM_HAL_CTIMER_XT_2_048KHZ |
- AM_HAL_CTIMER_FN_REPEAT |
- AM_HAL_CTIMER_INT_ENABLE |
- AM_HAL_CTIMER_PIN_ENABLE);
- am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA3);
- /* Set 512 sample rate */
- am_hal_ctimer_period_set(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA, 3, 1);
- /* Enable the timer A3 to trigger the ADC directly */
- am_hal_ctimer_adc_trigger_enable();
- /* Start the timer */
- //am_hal_ctimer_start(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
- }
- /**
- * @brief Initialize the ADC
- *
- * This function initialize the ADC
- *
- * @return None.
- */
- int rt_hw_adc_init(void)
- {
- am_hal_adc_config_t sADCConfig;
- /* timer for adc init*/
- timerA3_for_adc_init();
- /* Set a pin to act as our ADC input */
- am_hal_gpio_pin_config(BATTERY_GPIO, BATTERY_ADC_PIN);
- /* Enable interrupts */
- am_hal_interrupt_enable(AM_HAL_INTERRUPT_ADC);
- /* Enable the ADC power domain */
- am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_ADC);
- /* Set up the ADC configuration parameters. These settings are reasonable
- for accurate measurements at a low sample rate */
- sADCConfig.ui32Clock = AM_HAL_ADC_CLOCK_HFRC;
- sADCConfig.ui32TriggerConfig = AM_HAL_ADC_TRIGGER_SOFT;
- sADCConfig.ui32Reference = AM_HAL_ADC_REF_INT_2P0;
- sADCConfig.ui32ClockMode = AM_HAL_ADC_CK_LOW_POWER;
- sADCConfig.ui32PowerMode = AM_HAL_ADC_LPMODE_0;
- sADCConfig.ui32Repeat = AM_HAL_ADC_REPEAT;
- am_hal_adc_config(&sADCConfig);
- /* For this example, the samples will be coming in slowly. This means we
- can afford to wake up for every conversion */
- am_hal_adc_int_enable(AM_HAL_ADC_INT_FIFOOVR1);
- /* Set up an ADC slot */
- am_hal_adc_slot_config(BATTERY_ADC_CHANNELNUM, AM_HAL_ADC_SLOT_AVG_1 |
- AM_HAL_ADC_SLOT_14BIT |
- BATTERY_ADC_CHANNEL |
- AM_HAL_ADC_SLOT_ENABLE);
- /* Enable the ADC */
- am_hal_adc_enable();
- rt_kprintf("adc_init!\n");
- return 0;
- }
- #ifdef RT_USING_COMPONENTS_INIT
- INIT_BOARD_EXPORT(rt_hw_adc_init);
- #endif
- #endif
- /*@}*/
|