adc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * File : adc.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2017-12-04 Haley the first version
  23. */
  24. #include <rtdevice.h>
  25. #include "am_mcu_apollo.h"
  26. #include "board.h"
  27. #ifdef RT_USING_ADC
  28. /* sem define */
  29. rt_sem_t adcsem = RT_NULL;
  30. #define BATTERY_GPIO 29 /* Battery */
  31. #define BATTERY_ADC_PIN AM_HAL_PIN_29_ADCSE1
  32. #define BATTERY_ADC_CHANNEL AM_HAL_ADC_SLOT_CHSEL_SE1 /* BATTERY ADC采集通道 */
  33. #define BATTERY_ADC_CHANNELNUM 1 /* BATTERY ADC采集通道号 */
  34. #define ADC_CTIMER_NUM 3 /* ADC使用定时器 */
  35. #define ADC_CHANNEL_NUM 1 /* ADC采集通道个数 */
  36. #define ADC_SAMPLE_NUM 8 /* ADC采样个数, NE_OF_OUTPUT */
  37. rt_uint8_t bat_adc_cnt = (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM;
  38. rt_int16_t am_adc_buffer_pool[64];
  39. rt_uint8_t am_adc_data_get(rt_int16_t *buff, rt_uint16_t size)
  40. {
  41. /* wait adc interrupt release sem forever */
  42. rt_sem_take(adcsem, RT_WAITING_FOREVER);
  43. /* copy the data */
  44. rt_memcpy(buff, am_adc_buffer_pool, size*sizeof(rt_int16_t));
  45. return 0;
  46. }
  47. void am_adc_start(void)
  48. {
  49. /* adcsem create */
  50. adcsem = rt_sem_create("adcsem", 0, RT_IPC_FLAG_FIFO);
  51. /* Start the ctimer */
  52. am_hal_ctimer_start(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
  53. /* Trigger the ADC once */
  54. am_hal_adc_trigger();
  55. }
  56. void am_adc_stop(void)
  57. {
  58. /* Stop the ctimer */
  59. am_hal_ctimer_stop(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
  60. /* adcsem delete */
  61. rt_sem_delete(adcsem);
  62. }
  63. /**
  64. * @brief Interrupt handler for the ADC
  65. *
  66. * This function is Interrupt handler for the ADC
  67. *
  68. * @return None.
  69. */
  70. void am_adc_isr(void)
  71. {
  72. uint32_t ui32Status, ui32FifoData;
  73. /* Read the interrupt status */
  74. ui32Status = am_hal_adc_int_status_get(true);
  75. /* Clear the ADC interrupt */
  76. am_hal_adc_int_clear(ui32Status);
  77. /* If we got a FIFO 75% full (which should be our only ADC interrupt), go ahead and read the data */
  78. if (ui32Status & AM_HAL_ADC_INT_FIFOOVR1)
  79. {
  80. do
  81. {
  82. /* Read the value from the FIFO into the circular buffer */
  83. ui32FifoData = am_hal_adc_fifo_pop();
  84. if(AM_HAL_ADC_FIFO_SLOT(ui32FifoData) == BATTERY_ADC_CHANNELNUM)
  85. am_adc_buffer_pool[bat_adc_cnt++] = AM_HAL_ADC_FIFO_SAMPLE(ui32FifoData);
  86. if(bat_adc_cnt > (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM - 1)
  87. {
  88. /* shift data */
  89. 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));
  90. bat_adc_cnt = (ADC_CHANNEL_NUM + 1)*ADC_SAMPLE_NUM;
  91. /* release adcsem */
  92. rt_sem_release(adcsem);
  93. }
  94. } while (AM_HAL_ADC_FIFO_COUNT(ui32FifoData) > 0);
  95. }
  96. }
  97. static void timerA3_for_adc_init(void)
  98. {
  99. /* Start a timer to trigger the ADC periodically (1 second) */
  100. am_hal_ctimer_config_single(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA,
  101. AM_HAL_CTIMER_XT_2_048KHZ |
  102. AM_HAL_CTIMER_FN_REPEAT |
  103. AM_HAL_CTIMER_INT_ENABLE |
  104. AM_HAL_CTIMER_PIN_ENABLE);
  105. am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA3);
  106. /* Set 512 sample rate */
  107. am_hal_ctimer_period_set(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA, 3, 1);
  108. /* Enable the timer A3 to trigger the ADC directly */
  109. am_hal_ctimer_adc_trigger_enable();
  110. /* Start the timer */
  111. //am_hal_ctimer_start(ADC_CTIMER_NUM, AM_HAL_CTIMER_TIMERA);
  112. }
  113. /**
  114. * @brief Initialize the ADC
  115. *
  116. * This function initialize the ADC
  117. *
  118. * @return None.
  119. */
  120. int rt_hw_adc_init(void)
  121. {
  122. am_hal_adc_config_t sADCConfig;
  123. /* timer for adc init*/
  124. timerA3_for_adc_init();
  125. /* Set a pin to act as our ADC input */
  126. am_hal_gpio_pin_config(BATTERY_GPIO, BATTERY_ADC_PIN);
  127. /* Enable interrupts */
  128. am_hal_interrupt_enable(AM_HAL_INTERRUPT_ADC);
  129. /* Enable the ADC power domain */
  130. am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_ADC);
  131. /* Set up the ADC configuration parameters. These settings are reasonable
  132. for accurate measurements at a low sample rate */
  133. sADCConfig.ui32Clock = AM_HAL_ADC_CLOCK_HFRC;
  134. sADCConfig.ui32TriggerConfig = AM_HAL_ADC_TRIGGER_SOFT;
  135. sADCConfig.ui32Reference = AM_HAL_ADC_REF_INT_2P0;
  136. sADCConfig.ui32ClockMode = AM_HAL_ADC_CK_LOW_POWER;
  137. sADCConfig.ui32PowerMode = AM_HAL_ADC_LPMODE_0;
  138. sADCConfig.ui32Repeat = AM_HAL_ADC_REPEAT;
  139. am_hal_adc_config(&sADCConfig);
  140. /* For this example, the samples will be coming in slowly. This means we
  141. can afford to wake up for every conversion */
  142. am_hal_adc_int_enable(AM_HAL_ADC_INT_FIFOOVR1);
  143. /* Set up an ADC slot */
  144. am_hal_adc_slot_config(BATTERY_ADC_CHANNELNUM, AM_HAL_ADC_SLOT_AVG_1 |
  145. AM_HAL_ADC_SLOT_14BIT |
  146. BATTERY_ADC_CHANNEL |
  147. AM_HAL_ADC_SLOT_ENABLE);
  148. /* Enable the ADC */
  149. am_hal_adc_enable();
  150. rt_kprintf("adc_init!\n");
  151. return 0;
  152. }
  153. #ifdef RT_USING_COMPONENTS_INIT
  154. INIT_BOARD_EXPORT(rt_hw_adc_init);
  155. #endif
  156. #endif
  157. /*@}*/