red-30 0 16 апреля, 2019 Опубликовано 16 апреля, 2019 (изменено) · Жалоба Может кто-нибудь помочь разобраться или поделиться кодом (если кто уже писал) для работы 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); } Изменено 16 апреля, 2019 пользователем red-30 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 20 апреля, 2019 Опубликовано 20 апреля, 2019 · Жалоба Ну, разбираться у меня мозгов не хватит. Проверяй следующее, и найдёшь причину: - в прерывании сбрасывается флаг прерывания ? - в DMA включен циклический режим ? - DMA продолжает работать ? Т.е. данные в то месте, куда они пишутся, обновляются ? Т.е. не работает прерывание или ДМА ? - Аналогичный вопрос про АЦП и таймер: в регистре АЦП данные обновляются ? Т.е. АЦП продолжает работать по триггеру от таймера ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
romas2010 1 25 апреля, 2019 Опубликовано 25 апреля, 2019 (изменено) · Жалоба У меня получалось так 1) перед каждым новым преобразованием я включаю бит ADC.CR2.DMA=1, конфигурация DMA для АЦП,запуск таймера 2) преобразовалось по флагу DMA_streamx.TCIF-> стоп таймер, ADC.CR2.DMA=0 то есть бит ADC.CR2.DMA переключать необходимо Изменено 25 апреля, 2019 пользователем romas2010 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 4 мая, 2019 Опубликовано 4 мая, 2019 · Жалоба Тоже разбираться особо некогда, но вот код обработчика, который перезапускает АЦП с ДМА: 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться