2021-06-06 02:33 AM
Hello,
currently I'am working on a STM32 project with the CMSIS core.
I want the ADC getting triggered by a Timer (TIM3). Iam trying to do that with the TRGO option.
The ADC should sample 4 different channels. Each channel then gets transfered by the DMA to the RAM.
With my current code it works only once at startup, but I dont get any new readings in the memory.
void DMA_Init()
{
//1. Channel im SYSCFG CFGR1/3 bekannt geben
//SYSCFG_CFGR1: Nichts für ADC
//SYSCFG_CFGR3: Bit 9 == 1: ADC2 mapped on DMA1 Ch2
SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ADC2_DMA_RMP_1);
//Vier Register sind wichtig
//Configuration: DMA_CCRx MINC, PINK, CIRC, /MEM2MEM
//Holding number of bytes: DMA_CNDTRx
//Source Adress: DMA_CMARx
//Destination Adress: DMA_CPARx
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_DIR); //Data Transfer Direction: 0 = Read from Peripheral
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MEM2MEM); //Nicht MEM 2 MEM
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_CIRC); //Circ Mode Disabeled, wird nur von ADC EOC ausgelöst
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_0); //Priority level
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_1); //00 low, 01 med, 10 high, 11 very high
SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_0); //Memory Size
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_1); //00 8bit, 01 16bit, 10 32 bit
SET_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_0); //Peripheral Size
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_1); //00 8bit, 01 16bit, 10 32 bit
SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MINC); //Memory Increment
CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PINC); //NICHT Periph. increment
//DMA Source und Destination Adressen setzen
DMA1_Channel1->CMAR = ( uint32_t )&ADC_raw[0];
DMA1_Channel1->CPAR = ( uint32_t )(&ADC1->DR);
DMA1_Channel1->CNDTR = 4;
SET_BIT(DMA1_Channel1->CCR, DMA_CCR_EN); //DMA enablen
}
void TIM3_Init()
{
//Timer zum Triggern des ADCs bei bestimmter Frequenz über TRGO
TIM3->PSC = 0; //Prescaler
TIM3->ARR = 72-1; //Auto Reload
TIM3->CNT = 0; //Count
SET_BIT(TIM3->CR2, TIM_CR2_MMS_1); //TRGO
SET_BIT(TIM3->DIER, TIM_DIER_UIE); //Update Interrupt Enable
NVIC_EnableIRQ(TIM3_IRQn); //TIM3 Interrupts enable
SET_BIT(TIM3->EGR, TIM_EGR_UG);
NVIC_SetPriority(TIM3_IRQn, 0);
SET_BIT(TIM3->CR1, TIM_CR1_CEN); //Timer Enable
}
static void ADC1_Init(void)
{
//GPIO_MODER gesetzt?
//RCC_AHBENR gesetzt?
//PA1 ist ADC Input
//sicher gehen, dass Clock gesetzt ist
SET_BIT(RCC->AHBENR, RCC_AHBENR_ADC12EN);
//ADC1 disablen
if(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY))
{
SET_BIT(ADC1->ISR, ADC_ISR_ADRDY);
}
if(READ_BIT(ADC1->CR, ADC_CR_ADEN))
{
SET_BIT(ADC1->CR, ADC_CR_ADDIS);
}
//Warten bis ADC1 komplett disabled ist
while(READ_BIT(ADC1->CR, ADC_CR_ADEN)) {}
//ADC1 voltage regulator enablen
//Enable sequence im Reference sheet (Seite 219)
MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, 0);
MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, ADC_CR_ADVREGEN_0);
//kurzer delay zum enablen
/********************************DELAY FUNKTION NEU SELBER SCHREIBEN****************************/
HAL_Delay(2);
//ADC1 Clock = HCLK/1
MODIFY_REG(ADC12_COMMON->CCR, ADC12_CCR_CKMODE, ADC12_CCR_CKMODE_0 + ADC12_CCR_CKMODE_1);
//Single Ended Mode für alle Kanäle
ADC1->DIFSEL = 0x0;
//Kalibrierung für single ended Mode starten
CLEAR_BIT(ADC1->CR, ADC_CR_ADCALDIF);
SET_BIT(ADC1->CR, ADC_CR_ADCAL);
//Warten bis Kalibrierung erfolgt ist
while(READ_BIT(ADC1->CR, ADC_CR_ADCAL));
//Ready Flag zurücksetzen
SET_BIT(ADC1->ISR, ADC_ISR_ADRDY);
SET_BIT(ADC1->SQR1, ADC_SQR1_L_1 + ADC_SQR1_L_0); //Sequnz Laenge = 4 (0011)
SET_BIT(ADC1->SQR1, ADC_SQR1_SQ1_1); //Erste Konv Channel 2 (0010) Vin
SET_BIT(ADC1->SQR1, ADC_SQR1_SQ2_2); //Zweit Konv Channel 4 (0100) Vout
SET_BIT(ADC1->SQR1, ADC_SQR1_SQ3_0); //Dritt Konv Channel 1 (0001) Iin
SET_BIT(ADC1->SQR1, ADC_SQR1_SQ4_0 + ADC_SQR1_SQ4_1); //Viert Konv Channel 3 (0011) Iout
SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP2_2); //Sampling Time f. Channel 2 = 32 CLK
SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP4_2); //Sampling Time f. Channel 2 = 32 CLK
SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP1_2); //Sampling Time f. Channel 2 = 32 CLK
SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP3_2); //Sampling Time f. Channel 2 = 32 CLK
SET_BIT(ADC1->CFGR, ADC_CFGR_CONT); //Single conversion mode auswählen
SET_BIT(ADC1->CFGR, ADC_CFGR_EXTSEL_2); //External Trigger für TIM3_TRGO Event EXT4 0100
SET_BIT(ADC1->CFGR, ADC_CFGR_EXTEN_0); //External Trigger auf Rising Edge 01
SET_BIT(ADC1->CFGR, ADC_CFGR_DMAEN); //DMA einschalten
CLEAR_BIT(ADC1->CFGR, ADC_CFGR_DMACFG); //DMA im One Shot Mode
//SET_BIT(ADC1->IER, ADC_IER_EOCIE); //Interrupt Enable für EOC
//SET_BIT(ADC1->IER, ADC_IER_EOSIE); //Interrupt Enable für EOS
NVIC_EnableIRQ(ADC1_IRQn);
NVIC_SetPriority(ADC1_2_IRQn, 0);
//ADC einschalten bis es funktioniert (aus Errata Sheet)
do
{
SET_BIT(ADC1->CR, ADC_CR_ADEN);
}
while(!READ_BIT(ADC1->ISR, ADC_ISR_ADRDY));
SET_BIT(ADC1->CR, ADC_CR_ADSTART);
//togled1();
}//ADC1 Init
If you'd need any more information let me know!
2021-06-06 03:29 PM
> SET_BIT(ADC1->CFGR, ADC_CFGR_CONT); //Single conversion mode auswählen
The code does not do what the comment says. In continuous mode, you are likely to cause ADC overrun, preventing further DMA.
Read the ADC chapter in RM.
JW