Jump to content

    

stm32f4+adc+dma+tim

Может кто-нибудь помочь разобраться или поделиться кодом (если кто уже писал) для работы adc+dma+tim? Я использую камень stm32f405vgt6. Один раз заходи в прерывания от DMA и всё. Что я делаю не так?

	//Enable ADC1 clock
	RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
	__NOP();	
	
	ADC1->CR2 = 0;	//off ADC

	//ADC control register 1
	#define OVRIE		0	//0: Overrun interrupt disabled
	#define RES			0	//00: 12-bit (15 ADCCLK cycles)
	#define AWDEN		0	//0: Analog watchdog disabled on regular channels
	#define JAWDEN	0	//0: Analog watchdog disabled on injected channels
	#define DISCNUM	0	//1 channels
	#define JDISCEN	0	//0: Discontinuous mode on injected channels disabled
	#define DISCEN	0	//0: Discontinuous mode on regular channels disabled
	#define JAUTO		0	//0: Automatic injected group conversion disabled
	#define AWDSGL	0	//0: Analog watchdog enabled on all channels
	#define SCAN		1	//0: Scan mode disabled
	#define JEOCIE	0	//0: JEOC interrupt disabled
	#define AWDIE		0	//0: Analog watchdog interrupt disabled
	#define EOCIE		0	//1: EOC interrupt enabled
	#define AWDCH		0	//00000: ADC analog input Channel0
	
	ADC1->CR1 = (OVRIE << ADC_CR1_OVRIE_Pos) | (RES << ADC_CR1_RES_Pos) | (AWDEN << ADC_CR1_AWDEN_Pos) |
	(JAWDEN << ADC_CR1_JAWDEN_Pos) | (DISCNUM << ADC_CR1_DISCNUM_Pos) | (JDISCEN << ADC_CR1_JDISCEN_Pos) |
	(JAUTO << ADC_CR1_JAUTO_Pos) | (AWDSGL << ADC_CR1_AWDSGL_Pos) | (SCAN << ADC_CR1_SCAN_Pos) |
	(JEOCIE << ADC_CR1_JEOCIE_Pos) | (AWDIE << ADC_CR1_AWDIE_Pos) | (EOCIE << ADC_CR1_EOCIE_Pos) |
	(AWDCH << ADC_CR1_AWDCH_Pos);

	//ADC control register 2
	#define SWSTART		0		//0: Reset state
	#define EXTEN			1		//00: Trigger detection disabled
	#define EXTSEL		0x8	//1000: Timer 3 TRGO event
	#define JSWSTART	0		//0: Reset state
	#define JEXTEN		0		//00: Trigger detection disabled
	#define JEXTSEL		0		//0000: Timer 1 CC4 event
	#define ALIGN			0		//0: Right alignment
	#define EOCS			1		//0:  The EOC bit is set at the end of each sequence of regular conversions. Overrun detection is enabled only if DMA=1
	#define DDS				1		//0: No new DMA request is issued after the last transfer (as configured in the DMA controller)
	#define DMA				1		//0: DMA mode disabled
	#define CONT			0		//0: Single conversion mode
	
	ADC1->CR2 = (SWSTART << ADC_CR2_SWSTART_Pos) | (EXTEN << ADC_CR2_EXTEN_Pos) | (EXTSEL << ADC_CR2_EXTSEL_Pos) |
	(JSWSTART << ADC_CR2_JSWSTART_Pos) | (JEXTEN << ADC_CR2_JEXTEN_Pos) | (JEXTSEL << ADC_CR2_JEXTSEL_Pos) |
	(ALIGN << ADC_CR2_ALIGN_Pos) | (EOCS << ADC_CR2_EOCS_Pos) | (DDS << ADC_CR2_DDS_Pos) |
	(DMA << ADC_CR2_DMA_Pos) | (CONT << ADC_CR2_CONT_Pos);
	
	//ADC sample time register 1
	#define SMP10	1		//001: 15 cycles sampling time
	#define SMP11	1
	#define SMP12	1
	#define SMP13	1
	#define SMP14	1
	#define SMP15	1
	#define SMP16	1
	#define SMP17	1
	#define SMP18	1
											
	ADC1->SMPR1 = (SMP10 << ADC_SMPR1_SMP10_Pos) | (SMP11 << ADC_SMPR1_SMP11_Pos) | (SMP12 << ADC_SMPR1_SMP12_Pos) | 
	(SMP13 << ADC_SMPR1_SMP13_Pos) | (SMP14 << ADC_SMPR1_SMP14_Pos) | (SMP15 << ADC_SMPR1_SMP15_Pos) | 
	(SMP16 << ADC_SMPR1_SMP16_Pos) | (SMP17 << ADC_SMPR1_SMP17_Pos) | (SMP18 << ADC_SMPR1_SMP18_Pos);
	
	//ADC sample time register 2
	#define SMP0	1
	#define SMP1	1
	#define SMP2	1
	#define SMP3	1
	#define SMP4	1
	#define SMP5	1
	#define SMP6	1
	#define SMP7	1
	#define SMP8	1
	#define SMP9	1
	
	ADC1->SMPR2 = (SMP0 << ADC_SMPR2_SMP0_Pos) | (SMP1 << ADC_SMPR2_SMP1_Pos) | (SMP2 << ADC_SMPR2_SMP2_Pos) | 
	(SMP3 << ADC_SMPR2_SMP3_Pos) | (SMP4 << ADC_SMPR2_SMP4_Pos) | (SMP5 << ADC_SMPR2_SMP5_Pos) | 
	(SMP6 << ADC_SMPR2_SMP6_Pos) | (SMP7 << ADC_SMPR2_SMP7_Pos) | (SMP8 << ADC_SMPR2_SMP8_Pos) | 
	(SMP9 << ADC_SMPR2_SMP9_Pos);
	
		//ADC injected channel data offset register x
	ADC1->JOFR1 = 0;
	ADC1->JOFR2 = 0;
	ADC1->JOFR3 = 0;
	ADC1->JOFR4 = 0;
	
	//ADC regular sequence register x
	#define L			0	//Regular channel sequence length = 1
	#define IN13	0
	#define IN14	0
	#define IN15	0
	#define IN16	0
	
	ADC1->SQR1 = (L << ADC_SQR1_L_Pos) | (IN13 << ADC_SQR1_SQ13_Pos) | (IN14 << ADC_SQR1_SQ14_Pos) |
	(IN15 << ADC_SQR1_SQ15_Pos) | (IN16 << ADC_SQR1_SQ16_Pos);
	
	#define IN7		0
	#define IN8		0
	#define IN9		0
	#define IN10	0
	#define IN11	0
	#define IN12	0
	
	ADC1->SQR2 = (IN7 << ADC_SQR2_SQ7_Pos) | (IN8 << ADC_SQR2_SQ8_Pos) | (IN9 << ADC_SQR2_SQ9_Pos) |
	(IN10 << ADC_SQR2_SQ10_Pos) | (IN11 << ADC_SQR2_SQ11_Pos) | (IN12 << ADC_SQR2_SQ12_Pos);
	
	#define IN1		1 //PA1
	#define IN2		0	
	#define IN3		0
	#define IN4		0
	#define IN5		0
	#define IN6		0
	
	ADC1->SQR3 = (IN1 << ADC_SQR3_SQ1_Pos) | (IN2 << ADC_SQR3_SQ2_Pos) | (IN3 << ADC_SQR3_SQ3_Pos) | (IN4 << ADC_SQR3_SQ4_Pos) |
	(IN5 << ADC_SQR3_SQ5_Pos) | (IN6 << ADC_SQR3_SQ6_Pos);
	
	//ADC injected sequence register
	ADC1->JSQR = 0;
	
//	NVIC_SetPriority(ADC_IRQn,5);
//	NVIC_EnableIRQ(ADC_IRQn); 
	
	ADC1->CR2 |= ADC_CR2_ADON; // ON ADC
	
	//ADC common control register
	#define TSVREFE		0	//1: Temperature sensor and VREFINT channel enabled
	#define VBATE			0	//0: VBAT channel disabled
	#define ADCPRE		0	//00: PCLK2 divided by 2
	#define DMA_MULTI	0	//00: DMA mode disabled (for multi-ADC mode)
	#define DDS				1	//1: DMA requests are issued as long as data are converted and DMA = 01, 10 or 11 (for multi-ADC mode)
	#define DELAY			0	//0000: 5 * TADCCLK
	#define MULTI			0	//00000: Independent mode
	
	ADC->CCR = (TSVREFE << ADC_CCR_TSVREFE_Pos) | (VBATE << ADC_CCR_VBATE_Pos) | (ADCPRE << ADC_CCR_ADCPRE_Pos) |
	(DMA_MULTI << ADC_CCR_DMA_Pos) | (DDS << ADC_CCR_DDS_Pos) | (DELAY << ADC_CCR_DELAY_Pos) | (MULTI << ADC_CCR_MULTI_Pos);
	//--------------------------------------------------------------------------------------------------------------------------------
		//Enable DMA2 clock
	RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
	__NOP();
	
	//Disable DMA before enable
	DMA2_Stream0->CR = 0;
	while (DMA2_Stream0->CR & DMA_SxCR_EN) continue;
	
	//DMA low interrupt flag clear register
	DMA2->LIFCR = 0x0F7D0F7D;
	//DMA high interrupt flag clear register
	DMA2->HIFCR = 0x0F7D0F7D;
	
	//DMA stream x configuration register
	#define CHSEL			0	//000: channel 0 selected
	#define MBURST		0	//00: single transfer
	#define PBURST		0	//00: single transfer
	#define PL				3	//11: Very high
	#define PINCOS		0	//0: The offset size for the peripheral address calculation is linked to the PSIZE
	#define MSIZE			1	//01: half-word (16-bit)
	#define PSIZE			1	//01: Half-word (16-bit)
	#define MINC			1	//1: Memory address pointer is incremented after each data transfer (increment is done according to MSIZE)
	#define PINC			0	//0: Peripheral address pointer is fixed
	#define CIRC			1	//1: Circular mode enabled
	#define DIR				0	//00: Peripheral-to-memory
	#define PFCTRL		0	//0: The DMA is the flow controller
											//1: The peripheral is the flow controller
	#define TCIE			1	//1: TC interrupt enabled
	#define HTIE			0	//0: HT interrupt disabled
	#define TEIE			0	//0: TE interrupt disabled
	#define DMEIE			0	//0: DME interrupt disabled
	#define EN				1	//1: Stream enabled
	
	DMA2_Stream0->CR = (CHSEL << DMA_SxCR_CHSEL_Pos) | (MBURST << DMA_SxCR_MBURST_Pos) | (PBURST << DMA_SxCR_PBURST_Pos) | (PL << DMA_SxCR_PL_Pos) |
	(PINCOS << DMA_SxCR_PINCOS_Pos) | (MSIZE << DMA_SxCR_MSIZE_Pos) | (PSIZE << DMA_SxCR_PSIZE_Pos) | (MINC << DMA_SxCR_MINC_Pos) | (PINC << DMA_SxCR_PINC_Pos) |
	(CIRC << DMA_SxCR_CIRC_Pos) | (DIR << DMA_SxCR_DIR_Pos) | (PFCTRL << DMA_SxCR_PFCTRL_Pos) | (TCIE << DMA_SxCR_TCIE_Pos) | (HTIE << DMA_SxCR_HTIE_Pos) |
	(TEIE << DMA_SxCR_TEIE_Pos) | (DMEIE << DMA_SxCR_DMEIE_Pos);
	
	//Number of data items to transfer
	DMA2_Stream0->NDTR = 1;
	
	//Peripheral address
	DMA2_Stream0->PAR = (uint32_t)&ADC2->DR;
	
	//Memory 0 address
	DMA2_Stream0->M0AR = (uint32_t)&BUFF;
	
	//DMA stream x FIFO control register
	#define FEIE	0	//0: FE interrupt disabled
	#define DMDIS	0	//0: Direct mode enabled
									//1: Direct mode disabled
	#define FTH		3	//11: full FIFO
	DMA2_Stream0->FCR = (FEIE << DMA_SxFCR_FEIE_Pos) | (DMDIS << DMA_SxFCR_DMDIS_Pos) | (FTH << DMA_SxFCR_FTH_Pos);
	
	//Enable DMA
	DMA2_Stream0->CR |= DMA_SxCR_EN;
	
	NVIC_SetPriority(DMA2_Stream0_IRQn,5);
	NVIC_EnableIRQ(DMA2_Stream0_IRQn);
	//--------------------------------------------------------------------------------------------------------------------------------
	//Enable TIMER3 clock
	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
	__NOP();
	
	TIM3->CR1 = 0;
	
	//TIMx control register 1
	#define CKD		0	//00: tDTS = tCK_INT
	#define ARPE	0	//0: TIMx_ARR register is not buffered
	#define CMS		0	//00: Edge-aligned mode. The counter counts up or down depending on the direction bit (DIR)
	#define DIR		0	//0: Counter used as upcounter
	#define OPM		0	//0: Counter is not stopped at update event
	#define URS		1	//0: Any of the following events generate an update interrupt or DMA request if enabled.
	#define UDIS	0	//0: UEV enabled
	
	TIM3->CR1 = (CKD << TIM_CR1_CKD_Pos) | (ARPE << TIM_CR1_ARPE_Pos) | (CMS << TIM_CR1_CMS_Pos) |
	(DIR << TIM_CR1_DIR_Pos) | (OPM << TIM_CR1_OPM_Pos) | (URS << TIM_CR1_URS_Pos) | (UDIS << TIM_CR1_UDIS_Pos);
	
	//TIMx control register 2
	#define TI1S	0	//0: The TIMx_CH1 pin is connected to TI1 input
	#define MMS		2	//000: Reset - the UG bit from the TIMx_EGR register is used as trigger output (TRGO)
									//010: Update - The update event is selected as trigger output (TRGO)
	#define CCDS	0	//0: CCx DMA request sent when CCx event occurs
									//1: CCx DMA requests sent when update event occurs
	
	TIM3->CR2 = (TI1S << TIM_CR2_TI1S_Pos) | (MMS << TIM_CR2_MMS_Pos) | (CCDS << TIM_CR2_CCDS_Pos);
	
	//TIMx slave mode control register
	#define ETP		0	//0: ETR is noninverted, active at high level or rising edge
	#define ECE		0	//0: External clock mode 2 disabled
	#define ETPS	0	//00: Prescaler OFF
	#define ETF		0	//0000: No filter, sampling is done at fDTS
	#define MSM		0	//0: No action
	#define TS		0	//000: Internal Trigger 0 (ITR0)
	#define SMS		0	//000: Slave mode disabled - if CEN = ?1 then the prescaler is clocked directly by the internal clock.
	
	TIM3->SMCR = 0;
	TIM3->SMCR = (ETP << TIM_SMCR_ETP_Pos) | (ECE << TIM_SMCR_ECE_Pos) | (ETPS << TIM_SMCR_ETPS_Pos) |
	(ETF << TIM_SMCR_ETF_Pos) | (MSM << TIM_SMCR_MSM_Pos) | (TS << TIM_SMCR_TS_Pos);
	
	TIM3->SMCR |= (SMS << TIM_SMCR_SMS_Pos);
	
	//TIMx DMA/Interrupt enable register
	TIM3->DIER = 0;
	
	//TIMx status register
	TIM3->SR = 0;
	
	//TIMx event generation register
	#define TG		0	//0: No action
	#define CC4G	0	//0: No action
	#define CC3G	0	//0: No action
	#define CC2G	0	//0: No action
	#define CC1G	0	//0: No action
	#define UG		0	//0: No action
	
	TIM3->EGR = (TG << TIM_EGR_TG_Pos) | (CC4G << TIM_EGR_CC4G_Pos) | (CC3G << TIM_EGR_CC3G_Pos) | 
	(CC2G << TIM_EGR_CC2G_Pos) | (CC1G << TIM_EGR_CC1G_Pos) | (UG << TIM_EGR_UG_Pos);
	
	//TIMx capture/compare mode register 1
	TIM3->CCMR1 = 0;
	
	//TIMx capture/compare mode register 2
	TIM3->CCMR2 = 0;
	
	//TIMx capture/compare enable register
	TIM3->CCER = 0;
	
	//TIMx counter
	TIM3->CNT = 0;
	
	//TIMx prescaler
	TIM3->PSC = 84-1;
	
	//TIMx auto-reload register
	TIM3->ARR = 50-1;
	
	//TIMx capture/compare register 1
	TIM3->CCR1 = 0;
	
	//TIMx capture/compare register 2
	TIM3->CCR2 = 0;
	
	//TIMx capture/compare register 3
	TIM3->CCR3 = 0;
	
	//TIMx capture/compare register 4
	TIM3->CCR4 = 0;
	
	//TIMx DMA control register
	TIM3->DCR = 0;
	
	//TIMx DMA address for full transfer
	TIM3->DMAR = 0;
	
	TIM3->CR1 |= TIM_CR1_CEN;

void DMA2_Stream0_IRQHandler(void)
{
	//DMA low interrupt flag clear register
	DMA2->LIFCR = 0x0F7D0F7D;
	//DMA high interrupt flag clear register
	DMA2->HIFCR = 0x0F7D0F7D;
	
	GPIOB->ODR^=(LED_G_Pin);
}	

 

Edited by red-30

Share this post


Link to post
Share on other sites

Ну, разбираться у меня мозгов не хватит.
Проверяй следующее, и найдёшь причину:
  - в прерывании сбрасывается флаг прерывания ?
  - в DMA включен циклический режим ?
  - DMA продолжает работать ? Т.е. данные в то месте, куда они пишутся, обновляются ? Т.е. не работает прерывание или ДМА ?
  - Аналогичный вопрос про АЦП и таймер: в регистре АЦП данные обновляются ? Т.е. АЦП продолжает работать по триггеру от таймера ?

Share this post


Link to post
Share on other sites

У меня получалось так

1) перед каждым новым преобразованием я включаю бит ADC.CR2.DMA=1, конфигурация DMA для АЦП,запуск таймера

2) преобразовалось по флагу DMA_streamx.TCIF-> стоп таймер, ADC.CR2.DMA=0

то есть бит ADC.CR2.DMA переключать необходимо

Edited by romas2010

Share this post


Link to post
Share on other sites

Тоже разбираться особо некогда, но вот код обработчика, который перезапускает АЦП с ДМА:
 

void EXTI2_IRQHandler (void)    //Конец выборки УВХ                    
{
    EXTI->PR = EXTI_PR_PR2;
    DMA2_Stream2->CR &= ~DMA_SxCR_EN;
    if(num_k == 1) {DMA2_Stream2->M0AR = (uint32_t)&Kupol_1;}    
    if(num_k == 2) {DMA2_Stream2->M0AR = (uint32_t)&Kupol_2;}    
    if(num_k == 3) {DMA2_Stream2->M0AR = (uint32_t)&Kupol_3;}        
    if(num_k == 4) {DMA2_Stream2->M0AR = (uint32_t)&Kupol_4;}    
    DMA2_Stream2->NDTR = sample_size_adc; //NDT[15:0]: Number of data items to transfer
    DMA2->LIFCR |= ((1UL<<20)|(1<<21));
    ADC2->SR &= ~ADC_SR_OVR;
    ADC2->CR2 &= ~ADC_CR2_DMA;
    ADC2->CR2 |= ADC_CR2_DMA;
    DMA2_Stream2->CR |= DMA_SxCR_EN;//EN: Stream enable / flag stream ready when read low
    ADC2->CR2 |= ADC_CR2_SWSTART;
}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now