AnsweredAssumed Answered

Dual ADC frustrating Me (I need Urgent Help!!)

Question asked by slimsly on Feb 12, 2013
Latest reply on Feb 13, 2013 by baird.hal.001
Hello,

I have been trying for 3 days to configure the AD Converter of STM32F103RB in Injected dual  mode to no avail. I keep getting wrong  converted values on all channels during debugging. The ADC is in dual injected mode and it shuld be be trigger by TIM1 CC4 event. CH10 (PhaseA) , CH11(PhaseB) is assigned to ADC1 while CH12(PhaseC) and CH13(Current) is assigned to ADC2.I Connect 3.3V through 10K current limiting Resistor to the Channels. I got the following value during my debug session

PhaseA = 2043
PhaseB = 2179
PhaseC = 2235
Current = 2136

I also got that the same value when the Channels are connected to ground.I was expecting value close to 4096 (12 Bit). Something is seriously wrong with my code. I have been trying to figure out the problem for the past 3 days with no success.I have read the ADC section in the REFERENCE Manual a dozen times but no clue. I prefer direct configuration of peripherals so I do not want to use ST Peripherals Library.

I will be more than Happy if someone could take his time and go through my code to figure out the error.


============Code=================


#include "stm32f10x.h"


#define Inject_CH10_CH11 ((uint32_t)0x0005A800)
#define Inject_CH12_CH13 ((uint32_t)0x0006B000)
#define TIM1_CC4_TRIG ((uint32_t)0x00001000)
#define SOFTWARE_TRIG ((uint32_t)0x000E0000)
#define INJECTED_DUAL_MODE_ONLY ((uint32_t)0x00050000)
#define DEADTIME_1US ((uint16_t)0x0038)


void Init_SysClock(void);
void Init_PWM(void);
void Init_RCC(void);
void Init_ADC(void);
void Init_ExtIO(void);


//=============================================================================
// Global variables
//=============================================================================
uint32_t PhaseA,PhaseB,PhaseC,Current;


int main(void)
{


  Init_SysClock();              //Initialize GPIO & Peripherals Clocks
  Init_RCC();                   //Initialize GPIO
  Init_ExtIO();
  Init_PWM();                  //Initialize 20KHz PWM on CH 1-3
  Init_ADC();                 //Initialize ADC1 & ADC2 in Dual Injected Mode


    while(1)
      {


       }
}


void ADC1_2_IRQHandler(void)
{
 extern uint32_t PhaseA,PhaseB,PhaseC,Current;


  if (ADC1->SR & ADC_SR_JEOC)  //Injected channel end of conversion Completed
    {
      GPIOB->ODR ^= 0x00000300;        //Toggle GPIOB8 & GPIOB9
      ADC1->SR &= ~ADC_SR_JEOC; //Clear Flag
      ADC1->SR &= ~ADC_SR_JSTRT; //Clear Flag
      PhaseA = ADC1->JDR1;
      PhaseB = ADC1->JDR2;
      PhaseC = ADC2->JDR1;
      Current = ADC2->JDR2;
      GPIOB->ODR = 0x00000000;        //Toggle GPIOB8 & GPIOB9
    }
}


//========================================================================
// ADC Configuration for CH10 - CH13 in Dual Simultaneous Injected Mode
//========================================================================
void Init_ADC(void)
{
//Scan Enable| Injected Simultaneous Dual Mode Only |Discontinuous mode on injected channels Enable
//Injected Interrupt Enable
  ADC1->CR1 = ADC_CR1_SCAN | INJECTED_DUAL_MODE_ONLY |
              ADC_CR1_JDISCEN |ADC_CR1_JEOCIE;


//ADC2 Config=>Interrupt enable for injected channels | Scan Mode*/
  ADC2->CR1 = ADC_CR1_SCAN | ADC_CR1_JDISCEN | ADC_CR1_JEOCIE;


//Power Up ADC1 |Conversion on External Event Enabled | Enable TIM1 CC4 Trigger
  ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_JEXTTRIG | TIM1_CC4_TRIG;
//Power Up ADC2 |Conversion on External Event Enabled | Enable Software Trigger
  ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_JEXTTRIG | SOFTWARE_TRIG;


  ADC1->SMPR1 = ((uint32_t)0x00000000); //CH10 - CH11 Sample Time = 1.5 cycles
  ADC2->SMPR1 = ((uint32_t)0x00000000); //CH12 - CH13 Sample Time = 1.5 cycles


  ADC1->JSQR = ADC_JSQR_JL_0 | Inject_CH10_CH11;  //2 Injected conversions (CH10 & CH11)
  ADC2->JSQR = ADC_JSQR_JL_0 | Inject_CH12_CH13;  //2 Injected conversions (CH12 & CH13)


  ADC1->CR2 |= ADC_CR2_RSTCAL;   //Initialize ADC1 calibration register
  while ( ADC1->CR2 & ADC_CR2_RSTCAL );


  ADC2->CR2 |= ADC_CR2_RSTCAL;   //Initialize ADC2 calibration register
  while( ADC2->CR2 & ADC_CR2_RSTCAL );


  ADC1->CR2 |= ADC_CR2_CAL;   //Start ADC2 calibration
  while ( ADC1->CR2 & ADC_CR2_CAL );//Calibration Completed


  ADC2->CR2 |= ADC_CR2_CAL;   //Start ADC2 calibration
  while( ADC2->CR2 & ADC_CR2_CAL );//Calibration Completed


  NVIC_EnableIRQ(ADC1_2_IRQn);//Enable ADC1_2 Interrupt in NVIC
}




void Init_PWM(void)
{


  TIM1->PSC = 0;            //Pre-Scale Value=>0
  TIM1->ARR = (1400 - 1);  // Auto reload value 2800 (Period = 50us)
  TIM1->CCR1 = 700;       // Start PWM duty for channel 1
  TIM1->CCR2 = 700;        // Start PWM duty for channel 2
  TIM1->CCR3 = 700;       // Start PWM duty for channel 3
  TIM1->CCR4 = 700;      //CH4 Compare Value


  TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 |  //CH1-3 PWM mode 1
                 TIM_CCMR1_OC2M_2 |TIM_CCMR1_OC2M_1;   //CH3-4 PWM mode 1


  TIM1->CCMR2 |= TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | //CH3 & CH4 is configured as output
                 TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;


  /* Channel 1-4 active high | CH1-4 O/P Compare Enable | CH1-3N O/P Enable*/
  TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E |
                TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE;


  TIM1->BDTR |= TIM_BDTR_MOE | TIM_BDTR_OSSR | DEADTIME_1US; //Enable Main O/P & Enable OSSR
  TIM1->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE | TIM_CR1_CMS; //Enable Counter,Center Align Mode 1,Automatic Reload Enable


 }


void Init_RCC(void)
{


  /*Partial Remap TIM1: CH1/PA8,CH2/PA9,CH3/PA10,CH4/PA11,CH1N/PA7,CH2N/PB0,CH3N/PB1
  Remap USART1: TX/PB6, RXPB7*/
    AFIO->MAPR |= AFIO_MAPR_TIM1_REMAP_PARTIALREMAP | AFIO_MAPR_USART1_REMAP;


   //PA2, PA7 Alternate Function Push Pull Output | PA0 Input Floating
    GPIOA->CRL = 0xA4444B44;
    GPIOA->CRH = 0x4444AAAA;  //PA8 - PA11 Alternate Function Push Pull Output


    //PB0 & PB1 =>Alt Function Push Pull O/P | PB6-PB7 Alt Function Open Drain
    GPIOB->CRL = 0xFF4444AA;
    GPIOB->CRH = 0x44444433;    //Configure PB8 & PB9 as Output (Push Pull)
    GPIOC->CRH = 0x40000044;  //GPIOC10- GPIOC14 Analog Input
}


void Init_SysClock(void)
{
  RCC-> CFGR |= RCC_CFGR_ADCPRE_DIV4;     //ADC divided by 4
  /*Enable Alternate Function,GPIOA,GPIOB,GPIOC, GPIOD & TIMER1, ADC1 & ADC2 Clock Clock*/
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
                  RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_TIM1EN |
                  RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN;


  /*Enable TIMER2, TIMER3,I2C1  & USART2 Clock*/
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN |RCC_APB1ENR_I2C1EN |
                  RCC_APB1ENR_TIM4EN | RCC_APB1ENR_USART2EN;


  RCC->AHBENR = RCC_AHBENR_DMA1EN ;   //DMA1 clock enable


}

Regards
Slim
Please forgive my English

Outcomes