| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #include "gd32_adc.h"
- #include "gpio.h"
- #include "clock.h"
- #include "libs/shark_types.h"
- #include "libs/shark_task.h"
- /* For 12-bits resolution, the total conversion time is
- *sampling time + 12.5 ADCCLK cycles
- *all channel is enabled oversample to reach 16bit accurate
- */
- static int volatile adc_work = ADC_WORK_IDLE;
- //#define DMA_ADC_CH DMA_CH0
- #ifdef DMA_ADC_CH
- #define dma_irq DMA_Channel0_IRQn
- #define dma_buf_len 66
- static uint16_t dma_buf[dma_buf_len];
- #endif
- int gd32_adc_error = 0;
- void gd32_adc_init(void){
- rcu_periph_clock_enable(RCU_GPIOA);
- rcu_periph_clock_enable(RCU_GPIOB);
- gpio_mode_analog_input(GPIOA, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
- gpio_mode_analog_input(GPIOB, GPIO_PIN_1|GPIO_PIN_0);
- /* config ADC clock */
- rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); //adc clock:7M
- rcu_periph_clock_enable(RCU_ADC);
- adc_deinit();
- /* ADC trigger config */
- adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
- /* ADC data alignment config */
- adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
- /* ADC channel length config */
- adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
- adc_resolution_config(ADC_RESOLUTION_12B);
-
- //adc_special_function_config(ADC_SCAN_MODE,ENABLE);
- adc_discontinuous_mode_config(ADC_REGULAR_CHANNEL, 1);
- adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
- #ifdef DMA_ADC_CH
- dma_config();
- #endif
- }
- void gd32_adc_deinit(void){
- adc_deinit();
- rcu_periph_clock_disable(RCU_ADC);
- }
- #ifdef DMA_ADC_CH
- void dma_config(void)
- {
- /* ADC_DMA_channel configuration */
- dma_parameter_struct dma_data_parameter;
-
- /* ADC DMA_channel configuration */
- dma_deinit(DMA_ADC_CH);
-
- /* initialize DMA single data mode */
- dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA);
- dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
- dma_data_parameter.memory_addr = (uint32_t)dma_buf;
- dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_DISABLE;
- dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
- dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT;
- dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY;
- dma_data_parameter.number = 1U;
- dma_data_parameter.priority = DMA_PRIORITY_HIGH;
- dma_init(DMA_ADC_CH, &dma_data_parameter);
- dma_circulation_disable(DMA_ADC_CH);
- dma_interrupt_enable(DMA_ADC_CH, DMA_INT_FTF);
-
- nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
- nvic_irq_enable(dma_irq, 4U, 0U);
- }
- /* step 1 */
- int adc_is_idle(void){
- return adc_work == ADC_WORK_IDLE;
- }
- int adc_start_sample(int chan, int number){
- //hardware oversample to 16bit
- adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_4B, ADC_OVERSAMPLING_RATIO_MUL256);
- adc_oversample_mode_enable();
- /* use max convert time to make sure the adc work fine */
- adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//55.5 + 12.5 = 68 cycle, 68/(7*1000000)
- adc_enable();
- delay_us(1000); //MUST delay, for adc work fine
-
- adc_calibration_enable();
- DMA_CHCNT(DMA_ADC_CH) = (number & DMA_CHANNEL_CNT_MASK);
- dma_channel_enable(DMA_ADC_CH);
- /* ADC DMA function enable */
- adc_dma_mode_enable();
- /* ADC software trigger enable */
- adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
- adc_work = ADC_WORK_ING;
- }
- void DMA_Channel0_IRQHandler(void){
- adc_disable();
- dma_channel_disable(DMA_ADC_CH);
- dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
- adc_work = ADC_WORK_SAMPLE_COMPLTE
- }
- int adc_is_complete(void){
- return adc_work == ADC_WORK_SAMPLE_COMPLTE;
- }
- int adc_get_sample(void){
- if (adc_work != ADC_WORK_SAMPLE_COMPLTE){
- return adc_work;
- }
- int value = 0;
- int count = DMA_CHCNT(DMA_ADC_CH) & DMA_CHANNEL_CNT_MASK;
- int min = 0xFFFFF;
- int max = -0xFFFFF;
- int i;
- for (i = 0; i < count; i++){
- int one = dma_buf[i];
- value += one;
- if (one > max){
- max = one;
- }
- if (one < min) {
- min = one;
- }
- }
- adc_work = ADC_WORK_IDLE;
- return (value - min - max)/(count - 2);
- }
- int adc_sample_avg(int chan, int times){
- int value = 0;
- int count = 0;
- int min = 0xFFFFF;
- int max = -0xFFFFF;
- if (adc_work == ADC_WORK_ING){
- adc_disable();
- dma_channel_disable(DMA_ADC_CH);
- adc_dma_mode_disable();
- dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
- adc_work = ADC_WORK_INTERTUPED;
- }
- //hardware oversample to 16bit
- adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
- adc_oversample_mode_enable();
- /* use max convert time to make sure the adc work fine */
- adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
- adc_enable();
- delay_us(1000); //MUST delay, for adc work fine
- /* ADC calibration and reset calibration */
- adc_calibration_enable();
- while(count < times){
- adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
- while(SET != adc_flag_get(ADC_FLAG_EOC));
- int one = adc_regular_data_read();
- adc_flag_clear(ADC_FLAG_EOC);
- value += (one & 0xFFFF);
- count ++;
- if (one > max){
- max = one;
- }
- if (one < min) {
- min = one;
- }
- }
- adc_disable();
- return (value - min - max)/(times-2);
- }
- #else
- int adc_sample(int chan, int calibration){
- int value = -0xFFFFFF;
- int mask = 0xFFFF;
- //hardware oversample to 16bit
- adc_oversample_mode_config(ADC_OVERSAMPLING_ALL_CONVERT, ADC_OVERSAMPLING_SHIFT_2B, ADC_OVERSAMPLING_RATIO_MUL64);
- adc_oversample_mode_enable();
- /* use max convert time to make sure the adc work fine */
- adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);//239.5 + 12.5 = 242 cycle, 242/(28*1000000)
- adc_enable();
- delay_us(1000); //MUST delay, for adc work fine
- if (calibration) {
- /* ADC calibration and reset calibration */
- adc_calibration_enable();
- }
-
- adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
- while(SET != adc_flag_get(ADC_FLAG_EOC));
- value = adc_regular_data_read();
- adc_flag_clear(ADC_FLAG_EOC);
- adc_disable();
- return value & mask;
- }
- static int adc_sample_internal(int chan, int times, int *error) {
- int value = 0;
- int count = 0;
- int min = 0xFFFFF;
- int max = -0xFFFFF;
- adc_regular_channel_config(0, chan, ADC_SAMPLETIME_55POINT5);////55.5 + 12.5 = 68 cycle, 68 * 256/(7*1000000)
- adc_enable();
- delay_us(1000); //MUST delay, for adc work fine
- /* ADC calibration and reset calibration */
- adc_calibration_enable();
- *error = 0;
- while(count < times){
- u64 start_time = shark_get_mseconds();
- adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
- while(SET != adc_flag_get(ADC_FLAG_EOC)){
- if (shark_get_mseconds() - start_time >= 10){
- *error = -1;
- break;
- }
- };
- int one = adc_regular_data_read();
- adc_flag_clear(ADC_FLAG_EOC);
- value += (one & 0xFFF);
- count ++;
- if (one > max){
- max = one;
- }
- if (one < min) {
- min = one;
- }
- }
- adc_disable();
- if (times <= 2) {
- return value/times;
- }
- return (value - min - max)/(times-2);
-
- }
- //times * 0.6ms + 1ms
- int adc_sample_avg(int chan, int times){
- int error = 0;
- int value = adc_sample_internal(chan, times, &error);
- if (error < 0) {
- gd32_adc_error ++;
- gd32_adc_deinit();
- delay_us(5 * 1000);
- gd32_adc_init();
- value = adc_sample_internal(chan, times, &error);
- }
- return value;
- }
- #endif /* DMA_ADC_CH */
|