13x DMA + ADC

1.一般に、特定のチャネルは、特定の数のADCデータを抽出するために開始されます。

方法1:ADCをソフトウェアトリガーおよび連続サンプリングとして設定します。DMAを通常モードに設定します。DMA転送が完了したら、DMA完了割り込みをオンにし、割り込みのADCをオフにします。

このように、ADCは実際の内部動作中に継続的にサンプリングしますが、DMAカウンタは0にデクリメントされて実行を停止し、定量的なADC数を実現します。

方法2:ADCをソフトウェアトリガーに設定し、シングルサンプリングし、DMAを通常モードに設定し、DMAの最初の位置で連鎖移動を開始します。これにより、最初のADC変換が完了し、次のDMAが自動的に開始され、ADCが自動的に開始されます。これが実現されます。ADCの数を定量化するために、このアプローチの利点はDMA割り込みをオンにする必要がありませんが、連鎖移動は方法1ほど継続的ではありません。

#define ADC_OPERMODE_SELECT     /* ADC Operation mode: select mode */
	#define ADC_TRIGGER_SOFTWARE    /* ADC Trigger: software trigger */
	#define ADC_CONVMODE_ONESHOT    /* ADC Conversion mode: one-shot */
	#define ADC_VREF_VDD_VSS        /* ADC reference voltage: VDD/VSS */
	// ADC DMA
	// 开启ADC时钟
    CGC->PER0 |= CGC_PER0_ADCEN_Msk;    /* enables input clock supply */
    ADC->ADM0  = 0x00U;                 /* disable AD conversion and clear ADM0 register */
	// P62
    PORT->PMC6 |= (1 << 2);
	// 48M/8 = 6M
    /* AD operation mode: select or scan mode  */
    ADC->ADM0 = _28_AD_CONVERSION_CLOCK_1 | _00_AD_COMPARATOR_DISABLE;

    /* AD conversion mode setting */
    ADC->ADM1 = _00_AD_HISPEED;
#ifdef ADC_OPERMODE_SELECT     
    ADC->ADM1 |= _00_AD_OPERMODE_SELECT;
#endif
#ifdef ADC_OPERMODE_SCAN     
    ADC->ADM1 |= _80_AD_OPERMODE_SCAN;
#endif

#ifdef ADC_CONVMODE_SEQUENTIAL
    ADC->ADM1 |= _00_AD_CONVMODE_SEQUENTIAL;
#endif
#ifdef ADC_CONVMODE_ONESHOT
    ADC->ADM1 |= _08_AD_CONVMODE_ONESHOT;
#endif    

    /* AD reference voltage setting */
#ifdef ADC_VREF_VDD_VSS
    ADC->ADM2 = _00_AD_POSITIVE_VDD | _00_AD_NEGATIVE_VSS | _00_AD_AREA_MODE_1 ;
#endif
#ifdef ADC_VREF_AVREFP_AVREFM
    ADC->ADM2 = _40_AD_POSITIVE_AVREFP | _20_AD_NEGATIVE_AVREFM | _00_AD_AREA_MODE_1 ;
#endif

    /* AD trigger selection */
#ifdef ADC_TRIGGER_SOFTWARE
    ADC->ADTRG = _00_AD_TRIGGER_SOFTWARE;
#endif
#ifdef ADC_TRIGGER_HARDWARE_NOWAIT
    ADC->ADTRG = _80_AD_TRIGGER_HARDWARE_NOWAIT;
#endif
#ifdef ADC_TRIGGER_HARDWARE_WAIT
    ADC->ADTRG = _C0_AD_TRIGGER_HARDWARE_WAIT;
#endif

    /* AD comversion result comprision upper limit setting */
    ADC->ADUL = _FF_AD_ADUL_VALUE;
    /* AD comversion result comprision lower limit setting */
    ADC->ADLL = _00_AD_ADLL_VALUE;

    /* adhard power up */
    ADC->ADM0 |= ADCE;  
	
	{
	    uint8_t ctrl_data_num = 0;
	
		// DMA_VECTOR_ADC DMA中断向量位置
		DMAVEC->VEC[DMA_VECTOR_ADC] = ctrl_data_num;
		// CTRL_DMACR_SZ_Pos 数据长度(1表示16位 应为ADC结果大于8位,所以选16位)
		// CTRL_DMACR_RPTINT_Pos  DMA 中断
		// CTRL_DMACR_CHNE_Pos   不使用链式触发(所谓的链传输设置过后执行完会自动提取紧挨的DMA信息块)
		// CTRL_DMACR_DAMOD_Pos 目标地址是否增加 1表示增加
		// CTRL_DMACR_SAMOD_Pos 源地址是否增加 0表示不增加
		// CTRL_DMACR_RPTSEL_Pos DMA传输的方向 0表示为 从源地址提取到目标地址
		// CTRL_DMACR_MODE_Pos  1 表示否则一直执行 循环模式还是单次模式
		DMAVEC->CTRL[ctrl_data_num].DMACR = (1 << CTRL_DMACR_SZ_Pos) | (0 << CTRL_DMACR_RPTINT_Pos)|(1<<CTRL_DMACR_CHNE_Pos)|
										(1 << CTRL_DMACR_DAMOD_Pos)  | (0 << CTRL_DMACR_SAMOD_Pos) |
										(0 << CTRL_DMACR_RPTSEL_Pos)| (0 << CTRL_DMACR_MODE_Pos);
		// 块大小
		DMAVEC->CTRL[ctrl_data_num].DMBLS = 1;
		// 每个DMA循环传输次数
		DMAVEC->CTRL[ctrl_data_num].DMACT = 10;
		// DMA 传输重载值
		DMAVEC->CTRL[ctrl_data_num].DMRLD = 10;
		// DMA传输源地址
		DMAVEC->CTRL[ctrl_data_num].DMSAR = (uint32_t)&ADC->ADCR;
		// DMA传输目标地址 
		DMAVEC->CTRL[ctrl_data_num].DMDAR = (uint32_t)&adc_dma_buf[0];
		
		ctrl_data_num = ctrl_data_num+1;
		// 8位传输
		DMAVEC->CTRL[ctrl_data_num].DMACR = (0 << CTRL_DMACR_SZ_Pos) | (0 << CTRL_DMACR_RPTINT_Pos)|
										(0 << CTRL_DMACR_DAMOD_Pos)  | (0 << CTRL_DMACR_SAMOD_Pos) |
										(0 << CTRL_DMACR_RPTSEL_Pos)| (0 << CTRL_DMACR_MODE_Pos);
		// 块大小
		DMAVEC->CTRL[ctrl_data_num].DMBLS = 1;
		// 每个DMA循环传输次数
		DMAVEC->CTRL[ctrl_data_num].DMACT = 1;
		// DMA 传输重载值
		DMAVEC->CTRL[ctrl_data_num].DMRLD = 1;
		static uint8_t temp;
		temp = (1<<7)|(1<<0)|(ADC->ADM0);
		// DMA传输源地址
		DMAVEC->CTRL[ctrl_data_num].DMSAR = (uint32_t)&temp;
		// DMA传输目标地址 
		DMAVEC->CTRL[ctrl_data_num].DMDAR = (uint32_t)&ADC->ADM0;
		
	
		/* init DMA registers */
		// 开启 DMA时钟
		CGC->PER1   |= CGC_PER1_DMAEN_Msk;
		// 指定信息块内置地址
		DMA->DMABAR  = DMAVEC_BASE;
		// 开启对应的 DMA
		DMA->DMAEN0 |= 1 << 5;
	}
	ADC->ADM0 |= ADCS; 

 

おすすめ

転載: blog.csdn.net/C_ROOKIES/article/details/109326828