|
|
@@ -5,6 +5,13 @@
|
|
|
*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
|
|
|
void adc_init(void){
|
|
|
rcu_periph_clock_enable(RCU_GPIOA);
|
|
|
rcu_periph_clock_enable(RCU_GPIOB);
|
|
|
@@ -33,6 +40,92 @@ void adc_init(void){
|
|
|
|
|
|
}
|
|
|
|
|
|
+#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_start_sample(int chan){
|
|
|
+ //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);//239.5 + 12.5 = 242 cycle, 242/(28*1000000)
|
|
|
+ adc_enable();
|
|
|
+ adc_work = ADC_WORK_ING;
|
|
|
+}
|
|
|
+/* step 2 */
|
|
|
+int adc_start_calibration(void){
|
|
|
+ /* ADC calibration and reset calibration */
|
|
|
+ adc_calibration_enable();
|
|
|
+}
|
|
|
+int adc_sample_avg(int chan, int times){
|
|
|
+ /* configure the number of remaining data to be transferred */
|
|
|
+ DMA_CHCNT(DMA_ADC_CH) = (times & 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);
|
|
|
+}
|
|
|
+
|
|
|
+void DMA_Channel0_IRQHandler(void){
|
|
|
+ adc_disable();
|
|
|
+ dma_interrupt_flag_clear(DMA_ADC_CH, DMA_INT_FLAG_FTF);
|
|
|
+ dma_channel_disable(DMA_ADC_CH);
|
|
|
+}
|
|
|
+
|
|
|
+int adc_get_sample(void){
|
|
|
+ if (adc_work != ADC_WORK_FINISH){
|
|
|
+ return 0x7FFFFFFF;
|
|
|
+ }
|
|
|
+ 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_FINISH;
|
|
|
+ return (value - min - max)/(count - 2);
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
int adc_sample(int chan, int calibration){
|
|
|
int value = -0xFFFFFF;
|
|
|
int mask = 0xFFFF;
|
|
|
@@ -90,3 +183,4 @@ int adc_sample_avg(int chan, int times){
|
|
|
adc_disable();
|
|
|
return (value - min - max)/(times-2);
|
|
|
}
|
|
|
+#endif /* DMA_ADC_CH */
|