2023-04-28 04:59 AM
Hello guys, I'm new to the ST controllers. My question would be how can I initialize an ADC that is waiting for an external signal from a timer. I have initialized a timer interrupt that is triggered every 1 ms at 170 Mhz clock frequency. The timer also works, but there is no ADC conversion, the conversion should be triggered each time via a timer. I work with direct access to the registers without using the hal library because I want to save memory. I've looked through the St examples a bit, but they're all made with the HAL library. I want to use Timer 2 and ADC channel 0 on GPIOA PA0. The timer is only running, my ADC(adc_value is empty) is not working can someone help me with what I have initialized incorrectly here or what is still missing. Thanks for your help guys, I'll post the code here.
Kind regards, Markus
void initADC()
{
// Enable ADC clock
RCC->AHB2ENR |= RCC_AHB2ENR_ADC12EN;
// Configure GPIO pin as analog input
GPIOA->MODER |= (0b11<<(0 * 2U));
// Disable ADC deep power-down mode and enable ADC voltage regulator
ADC1->CR &= ~ADC_CR_DEEPPWD;
ADC1->CR |= ADC_CR_ADVREGEN;
//wait for voltage 2ms
for(uint32_t i = 0;i < 340000;i++); //170Mhz ->340000 2ms
// Configure ADC trigger source and mode
ADC1->CFGR |= (ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3); // Trigger on rising edge + Trigger TIM2_TRGO
ADC2->CFGR |= (ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3); // Trigger on rising edge + Trigger TIM2_TRGO
ADC1->SQR1 |= (ADC_SQR1_SQ1_0 | ADC_SQR1_L_0 );
// Enable ADC
ADC1->CR |= ADC_CR_ADEN;
// Start ADC conversion on Timer 2 TRGO event
ADC1->CR |= ADC_CR_ADSTART;
}
void initCPU_Timer1()
{
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN;
TIM2->PSC = 169;
TIM2->ARR = 999;
TIM2->CR1 = TIM_CR1_ARPE | TIM_CR1_URS;
TIM2->DIER = TIM_DIER_UIE; // Enable Interrupt
TIM2->EGR = TIM_EGR_UG; // Update Event
TIM2->CR2 |= TIM_CR2_MMS_2;
// Interrupt-Config
NVIC_SetPriority(TIM2_IRQn, 0);
NVIC_EnableIRQ(TIM2_IRQn);
// Timer-start
TIM2->CR1 |= TIM_CR1_CEN;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
initADC();
initCPU_Timer1();
while (1)
{
}
}
volatile uint16_t adc_value = 0;
void TIM2_IRQHandler(void)
{
if (TIM2->SR & TIM_SR_UIF) // Timer Overflow Event
{
ADC1->CR |= ADC_CR_ADSTART; // start ADC
TIM2->SR &= ~TIM_SR_UIF; // Clear Timer Overflow Flag
adc_value = ADC1->DR;
}
}
2023-05-02 02:15 PM
I think i found mistake in your code:
TIM2->CR2 |= TIM_CR2_MMS_2;
TIM_CR2_MMS_2 it equals 0x100 and in manual means :
0100: Compare - tim_oc1refc signal is used as trigger output (tim_trgo)
You have to use TIM_CR2_MMS_1:
0010: Update - The update event is selected as trigger output (tim_trgo). For instance a master timer can then be used as a prescaler for a slave timer.
And you musn't use ADC start again in TIM IRQ handler :
Line 79: ADC1->CR |= ADC_CR_ADSTART; // start ADC
because trigger is automatically relaunch