2017-10-27 08:44 AM
I'm trying to do a bare metal setup for a STM32F303K8 and am trying to understand how STM ADCx_INx pins are connected/routed to an ADC. Is there a multiplexer that is setup to 'gate' one of the the many ADC INx pins to a ADC?
In particular which registers do I manually configure, for example, to connect ADC2_IN4 to the ADC2. I'm assuming I would first set the pin to analog using the MODER register. But what register should I do next? My goal is to do a reading on one pin one time.
Thanks for any direction.
Solved! Go to Solution.
2017-10-30 07:33 AM
I was able to get a reading on ADC2_IN4 using the STM32F303K8 on a STM32F303 Nucleo-32 evaluation/development board. I had found an example using ADC1_IN1 and was attempting to modify for
mailto:ADC@_IN4
. My issue was understanding the ADCx_SQR register. My read on this register it that it is a list of channels (IN1,IN2,...) pins, in a regular group, that will be read/converted in a particular order. So for ADC2_IN4, setup as the first (and only) pin, I had to setADC2_SQR1's SQ1 as a 0x4. The ADC2_SQR1's 'L' field describes the length or number of channels to convert and defaults to 0x00 or 1 conversion.
My converted the sample code from ADC1_IN1 to ADC2_IN4 and it now works. The code is listed below.
Thanks to all that read and thought about my question.
Randy
//
// clocks are already setup
//
GPIOA_MODER |= BIT15+BIT14; //make PA7, ADC2_IN4, analog
RCC_AHBENR |= BIT28; // turn on ADC clock
ADC12_CCR |= BIT17; // Set ADC clock = HCLK / 2=32MHz ADC2_CR &= ~BIT0; // disable the ADC // enable the ADC voltage regulator ADC2_CR &= ~BIT29; ADC2_CR |= BIT28; // start ADC calibration cycle ADC2_CR |= BIT31; while (ADC2_CR & BIT31); // wait for calibration to complete ADC2_CR |= BIT0; // enable the ADC ADC2_SQR1 = (1 << 8); // Select ADC Channel 4, This is important and what I was missingwhile(1) {
ADC2_CR |= BIT2; // start conversion
while (ADC2_CR & BIT2); // wait for end of conversion
int_var_V1 = ADC2_DR; //also a break point for debug
}
2017-10-27 10:01 AM
If available use the Injected channel. Each channel has its own DR, no need to use DMA to unmux the shared DR on normal channel. You can also use a trigger pin to launch a conversion so it can be done manually.
You might even have fun in debug mode by manually changing the ADC registers and see how to get a valid conversion, otherwise, use HAL or LL to get there from a Nucleo or Discovery example.
2017-10-29 12:51 PM
Thanks for the info but I do not understand 'use the Injected' channel. I do not remember seeing this in the data sheet. Is 'DR' 'data register'? Do not understand this either. I understand setting up a GPIO pin manually. I also understand that certain GPIO pins are also ADCx pins such as ADC2_IN3. What I cannot find is what register to set to connect ADC2_IN3 to the ADC2. Do I use the SQR register? if yes then what is the value for the ADC2_IN3? Is it 0x3? I cannot find this mapping?
Thanks for any direction. I'm simply trying to read a voltage at ADC2_IN3 in the simplest fashion. No DMA.
2017-10-29 10:00 PM
Injected Channels are typically on STM32F4, maybe you are using an M0? Then you might need to use DMA as shown in some board example.
2017-10-30 07:33 AM
I was able to get a reading on ADC2_IN4 using the STM32F303K8 on a STM32F303 Nucleo-32 evaluation/development board. I had found an example using ADC1_IN1 and was attempting to modify for
mailto:ADC@_IN4
. My issue was understanding the ADCx_SQR register. My read on this register it that it is a list of channels (IN1,IN2,...) pins, in a regular group, that will be read/converted in a particular order. So for ADC2_IN4, setup as the first (and only) pin, I had to setADC2_SQR1's SQ1 as a 0x4. The ADC2_SQR1's 'L' field describes the length or number of channels to convert and defaults to 0x00 or 1 conversion.
My converted the sample code from ADC1_IN1 to ADC2_IN4 and it now works. The code is listed below.
Thanks to all that read and thought about my question.
Randy
//
// clocks are already setup
//
GPIOA_MODER |= BIT15+BIT14; //make PA7, ADC2_IN4, analog
RCC_AHBENR |= BIT28; // turn on ADC clock
ADC12_CCR |= BIT17; // Set ADC clock = HCLK / 2=32MHz ADC2_CR &= ~BIT0; // disable the ADC // enable the ADC voltage regulator ADC2_CR &= ~BIT29; ADC2_CR |= BIT28; // start ADC calibration cycle ADC2_CR |= BIT31; while (ADC2_CR & BIT31); // wait for calibration to complete ADC2_CR |= BIT0; // enable the ADC ADC2_SQR1 = (1 << 8); // Select ADC Channel 4, This is important and what I was missingwhile(1) {
ADC2_CR |= BIT2; // start conversion
while (ADC2_CR & BIT2); // wait for end of conversion
int_var_V1 = ADC2_DR; //also a break point for debug
}