2

Working on a simple ADC project reading voltages from a potential divider on a number of channels. I am using the STM32f103rb on a commercial and well made PCB. I am reading pins on PORTA and the following pins work and return a voltage:

PA0, PA1, PA4, PA5, PA6, PA7.

However the following pins do not work and return a raw value of around 2000-2700 approx:

PA8, PA11 and PA12.

The nature of the project and the fact that the PCB is of a fixed design means that we are stuck with these pin selections. The datasheet is quite specific about these pins being usable as AIN. All set-up and config is as per standard STM32, taken from basic example code and modified for our purposes. The included code is a debugging version we made in an attempt to find the cause but to no avail.

Voltage at the pins has been measured and is correct for the type of voltage divider.

Any help would be greatly appreciated on this.

    /* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stdio.h"
#include "stdlib.h"

// Standard STM peripheral config functions
void RCC_Configuration(void);
void GPIO_Configuration(void);

// ADC config - STM example code
void NEW_ADC_Configuration(void);

// Function to read ADC channel and output value
u16 NEW_readADC1(u8 channel);


// Variables
double voltage_su;          // Variable to store supply voltage
double voltage7;
double voltage8;

//*****************************************************************************
// Main program
int main(void)
{
    // Initialise peripheral modules
    RCC_Configuration();
    GPIO_Configuration();
    NEW_ADC_Configuration();

    // Infinate loop
    while (1)
    {       

        // Get value of supply voltage and convert
        voltage_su =  (((3.3 * NEW_readADC1(ADC_Channel_12)) / 4095));

    }
}
//*****************************************************************************
// STM RCC config
void RCC_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);   // Connect PORTC
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // Connect PORTB...
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // Connect PORTA...
}
//*****************************************************************************
// STM GPIO config
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;    // Value for setting up the pins

    // Sup
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

}
//*****************************************************************************
void NEW_ADC_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    ADC_InitTypeDef ADC_InitStructure;  // Varibale used to setup the ADC
    RCC_ADCCLKConfig(RCC_PCLK2_Div4);   // Set ADC clock to /4

    // Enable ADC 1 so we can use it
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    // Conenct the port A to peripheral clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    // Restore to defaults
    ADC_DeInit(ADC1);

    /* ADC1 Configuration ----------------------------------------------------*/
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    // Scan 1 at a time
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    // No continuous conversions - do them on demand
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    // Start conversion on software request - not bu external trigger
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    // Conversions are 12 bit - put them in the lower 12 bits of the result 
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    // How many channels are to be sued by the sequencer
    ADC_InitStructure.ADC_NbrOfChannel = 1;

    // Setup ADC
    ADC_Init(ADC1, &ADC_InitStructure);
    // Enable ADC 1
    ADC_Cmd(ADC1, ENABLE);

    // Enable ADC1 reset calibaration register
    ADC_ResetCalibration(ADC1);
    // Check end of reset calib reg
    while(ADC_GetResetCalibrationStatus(ADC1));
    //Start ADC1 calib
    ADC_StartCalibration(ADC1);
    // Check the end of ADC1 calib
    while(ADC_GetCalibrationStatus(ADC1));
}
//*****************************************************************************
// Function to return the value of ADC ch
u16 NEW_readADC1(u8 channel)
{
    // Config the channel to be sampled
    ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);
    // Start the conversion
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    // Wait until conversion complete
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
    // Get the conversion value
    return ADC_GetConversionValue(ADC1);
}
//*****************************************************************************
Lundin
  • 195,001
  • 40
  • 254
  • 396
Adam893
  • 143
  • 1
  • 3
  • 16
  • Hello and welcome to stackoverflow.com. Please take some time to read [the Stack Overflow question checklist](http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist). You might also want to learn what a [SSCCE](http://sscce.org/) is. – Some programmer dude Feb 13 '14 at 11:58
  • Hi and thanks for the welcome. I have been researching this issue for many weeks - are you saying that an answer/question of this sort already exists? Have read the guidelines but felt as this represents the code in it's entirety, it was of use. – Adam893 Feb 13 '14 at 12:05
  • This question is very broad and since the answer might be found in either hardware or software, it is better to ask at http://electronics.stackexchange.com. Or if you suspect some oddity with the MCU, ask ST support directly. – Lundin Feb 13 '14 at 12:12
  • The code you posted is much too long to read and comprehend quickly, as well as it containing code unrelated to your problem. Please try to make a minimal program that exhibits your problem, for example without the UART code and maybe only one working and one non-working input. It's quite possible that while writing such a program (a ["SSCCE"](http://sscce.org/)) you might figure out the problem yourself. – Some programmer dude Feb 13 '14 at 12:12
  • Have you tried different boards/different MCUs? Maybe some ADC pins are damaged? Does the board work as expected with different software on it (if not, your question is definitely off-topic for this site...)? Have you measured the analog voltage in at all pins using a volt meter or oscilloscope? Have you read the MCU errata for the particular silicon mask? Does the manual mention any particular hw peripheral mapping considerations on the chip? – Lundin Feb 13 '14 at 12:16
  • Are these pins available on your particular silicon? Commonly, MCUs are released with one full version on a LQFP112, LQFP144 or BGA, and then physically smaller packages are available for the same MCU, for example LQFP80, LQFP48, QFN48 etc. If you are using a smaller package, then most likely some ADC channels etc have been removed. – Lundin Feb 13 '14 at 12:18
  • Thanks for the comments which have been noted - will edit the question accordingly. – Adam893 Feb 13 '14 at 12:19
  • We tried many boards/MCUs during the development phase and selected this one. Other software does work on the MCU, expect for these same pins not behaving. Voltage measured at the pins both ons cope and with multimeter and is as expected from the potential divider. Datasheet is quite clear about these pins being GPIO by default on reset. Nothing else is mentioned in the manual. Yes the pins are definatly available on this silicon. Thanks for the answers. – Adam893 Feb 13 '14 at 12:27
  • Solved, found answer here: http://goo.gl/6FIJjD Thanks for all your input. – Adam893 Feb 13 '14 at 13:56
  • Were you in fact able to read analog signals from PA8, PA10, and PA11? The data sheet doesn't really seem to list these pins as among those for which analog input is supported as an Alternate Function, but perhaps there's some lower-quality routing to an additional analog mux. If you have a solution, please post the primary details in your own answer, and eventually accept it, so that the question shows as resolved. – Chris Stratton Feb 13 '14 at 16:29

2 Answers2

5

I have never worked with this chip, but after looking at the hardware data sheet for 5 minutes I came up with the following naive conclusions:

  • The chip has 2 ADCs with 8 channels each, a total of 16.
  • PA0, PA1, PA4, PA5, PA6, PA7 sounds as if they will belong to the first ADC.
  • I then assume that PA8, PA11 and PA12 belong to the second ADC, called ADC2 by ST.
  • Your code seems to only ever mention and initialize ADC1. No trace of ADC2.

Maybe these pins don't work because you haven't even initialized or activated the ADC they belong to?

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Brilliant, thank you. I found something similar here: http://goo.gl/6FIJjD. I appreciate your efforts. – Adam893 Feb 13 '14 at 14:00
0

Also, you should check the data sheet for contention due to those pins being used as "Alternate Function".

Typically, they will list what needs to be done/disconnected in order to utilize the pins without contention (e.g. disconnect some resistor)

bunkerdive
  • 2,031
  • 1
  • 25
  • 28