cancel
Showing results for 
Search instead for 
Did you mean: 

Problem setting up ADC1 on STM32F103C6 to do single programmed read (of Vrefint) - bare metal

wb0gaz
Senior

I am trying to set up ADC1 on STM32F103C6 "bare metal" (no HAL or LL). I've successfully done this on F0 series without difficulty, but this has me stumped. I've also referred to source code generated by STM32CubeMX (for just this device on this target) but it appears that is not succeeding.

Below is relevant code and some print statements generated by that code (the CPU is set for 24 MHz, ADC prescaler is divide-by-2, so ADC clock is at 12 MHz and proceeds from there):

//   STM32F103C6

//   CPU clock 24 MHz

//   Initialize ADC1

//   Single reading from mux 17 (Vrefint)

//   ADC1 prescaler set to divide-by-2:

//  RCC->CFGR ADCPRE[1:0] = 00: PCLK2 divided by 2

//   ADC1 clock frequency = 12 MHz

  

Before initialization

ADC1 Base:    40012400

ADC1->CR1:    00000000

ADC1->CR2:    00000000

ADC1->SQR1:   00000000

ADC1->SQR2:   00000000

ADC1->SQR3:   00000000

//   STM32F103: Initialize ADC1 for single software-initiated conversions

      RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // Turn on ADC1 clock

      for (uint16_t volatile i = 0; i < 1000; i++); // time delay --- wait for turn-on to complete

      ADC1->CR2 |= ADC_CR2_TSVREFE; // Turn on temperature sensor, refint channels

      ADC1->CR2 |= ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0; // Regular group SWSTART only

      ADC1->CR2 |= ADC_CR2_ADON; // Turn on ADC1

      for (uint16_t volatile i = 0; i < 1000; i++); // time delay --- wait for turn-on to complete

      ADC1->SQR1 = 0; // Single channel in regular group

      ADC1->SQR2 = 0; // Single channel in regular group

      ADC1->SQR3 = 0x11; // Single channel in regular group - Channel 0x11 - Vrefint

After initialization, before first conversion

ADC1 Base:    40012400

ADC1->CR1:    00000000

ADC1->CR2:    008E0001

ADC1->SQR1:   00000000

ADC1->SQR2:   00000000

ADC1->SQR3:   00000011

// STM32F103: Perform one conversion from channel 0x11 (Vrefint)

   ADC1->CR2 |= ADC_CR2_SWSTART; // Start conversion

// Before ADC_CR2_SWSTART is set

ADC1->SR.EOC: 0

// After ADC_CR2_SWSTART is set

ADC1->SR.EOC: 0

// After time delay (EOC never appears)

ADC1->SR.EOC: 0

ADC1->DR:     00000000

1 REPLY 1
wb0gaz
Senior

Problems fixed - -

Unable to get STM32CubeIDE to recognize new device class added to project after project first created with STM32CubeMX:

Copy .../DRIVERS/HAL/Inc/stm32f1xx_ll_adc.h and .../DRIVERS/HAL/Src/stm32f1xx_ll_adc.c from another project and "clean" (so that it can find the newly added files) then "build"

ADC not initiating conversions:

I was using SWSTART to initiate an ADC conversion. Turns out ADON is used both to turn on the ADC as well as initiate a conversion.

Very memory constrained, so now need to work out replacing the length LL initialization code with register-level code, but have working starting point.

Tks!