2020-08-12 07:04 AM
I am using ADC2 Channel 10 with external trigger TIMER 2 TRGO Update. Although I am viewing the ADC values over USART and it is sampled but the sampling time is not 2Hz. Which I set in TIMER 2 just to make sure that I can control the sampling time via TIMER 2. But this is not the case. It is being sampled too fast. I am not able to figure it out why it is not being sampled the same way my LED is blinking in TIMER2_IRQ
Here is the configuration functions which I used in KEIL VU5 using CMSIS Core.
void init_ADC(void)
{
RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN; //GPIOC clock enable
GPIOC->MODER|=(3u<<(2*0)); //ADC input pin is analogue mode
RCC->APB2ENR|=RCC_APB2ENR_ADC1EN; //ADC clock enable
ADC1->SQR1&=~ADC_SQR1_L; //set number of conversions per sequence to 1
ADC1->SQR3&=~ADC_SQR3_SQ1; //clear channel select bits
ADC1->SQR3|=10; //set channel
ADC1->CR1 &= ~ADC_CR1_SCAN; //SCAN mode disabled
ADC1->CR2 &= ~ADC_CR2_CONT; //Disable continuous conversion
ADC1->CR2 &= ~(1<<29);
ADC1->CR2 |= (1<<28); //Trigger on Rising edge
//External Event TIM2 TRGO
ADC1->CR2 &= ~(1<<3);
ADC1->CR2 |= (1<<2);
ADC1->CR2 |= (1<<1);
ADC1->CR2 &= ~(1<<0);
ADC1->SMPR1 |= ADC_SMPR1_SMP10;
ADC1->CR2|=ADC_CR2_ADON; //enable ADC
ADC1->CR2|=ADC_CR2_SWSTART;
}
unsigned short read_adc(void)
{
ADC1->CR2|=ADC_CR2_SWSTART; //start ADC conversion
while((ADC1->SR&ADC_SR_EOC)==0){__NOP();} //wait for ADC conversion complete
return ADC1->DR; //return converted value
}
void TIM2_Configuration(void){
// enable TIM2 clock (bit0)
RCC->APB1ENR |= (1 << 0);
//TIM2->PSC = 1749; //FOR DISCOVERY
//TIM2->PSC = 1874; //FOR NECLUEO
TIM2->PSC = 8199; //For 82Mhz
TIM2->ARR = 10000; //it will get one second delay
/* Reset the MMS Bits */
TIM2->CR2 &= (uint16_t)~TIM_CR2_MMS;
/* Select the TRGO source */
TIM2->CR2 |= TIM_CR2_MMS_1; //UPDATE EVENT
// Update Interrupt Enable
TIM2->DIER |= (1 << 0);
// enable TIM2 IRQ from NVIC
NVIC_EnableIRQ(TIM2_IRQn);
// Enable Timer 2 module (CEN, bit0)
TIM2->CR1 |= (1 << 0);
}
/*************************************************
* timer 2 interrupt handler
*************************************************/
void TIM2_IRQHandler(void)
{
// clear interrupt status
if (TIM2->DIER & 0x01) {
if (TIM2->SR & 0x01) {
TIM2->SR &= ~(1U << 0);
}
}
GPIOD->ODR ^= (1 << 13);
}
and this is how I am reading in while(True) loop
while(1)
{
char str[10];
while((ADC1->SR&ADC_SR_EOC)==0){__NOP();}
//unsigned int volts = read_adc();
unsigned int volts = ADC1->DR;
// GPIOD->ODR ^= (1 << 13); // Toggle LED
uart_tx(((volts/10000)%10)+48);
uart_tx(((volts/1000)%10)+48);
uart_tx(((volts/100)%10)+48);
uart_tx(((volts/10)%10)+48);
uart_tx(((volts)%10)+48);
uart_tx('\r');
uart_tx('\n');
// slow down
//
delay(300);
}
Also the Next thing is I want to send this data automatically via Usart Interrupt and DMA. But I am not sure where to go from this point? How to use DMA with both the ADC and the USART so that It circularly transfer data automatically. Any suggestions? or any CMSIS examples related to this?
2020-08-12 01:19 PM
Which STM32?
Write a minimal but complete compilable code exhibiting the problem, and post. Also read out and post the relevant ADC and TIM registers content.
JW
PS.
> TIM2->SR &= ~(1U << 0);
Not the problem here, but don't RMW TIMx_SR.