Question

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);
}
//*****************************************************************************
Was it helpful?

Solution

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?

OTHER TIPS

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top