AnsweredAssumed Answered

Problem with STM8S103 ADC

Question asked by Frank Tang on Jun 27, 2012
Latest reply on Jun 27, 2012 by de_craemer.klaas
I am using STM8S103 to measure three channels of voltage signals named vs12, vs5 and vs3 respectively. Timer 4 is enabled to generate interrupt every 10ms and three voltage signals are measured alternately. That is, in the 1st 10ms interrupt, vs12 is measured. In the 2nd 10ms interrupt, vs5 is measured. In the 3rd 10ms interrupt, vs3 is measured, and so on. During each measurement, mcu makes 16 captures for further average processing. The measurement result will be displayed in HyperTerminal via UART.

The problem is that when only 1 channel (vs12, vs5, or vs3) is enabled, the measurement is correct. But when two channels are enabled, both channels' measurements are wrong. Could anyone have a look at the following code and give me some suggestions?

The C code is described as follows.
main()
{
      ADC1->CR1 |= (ADC1_CR1_SPSEL & (0x02<<4)); //fADC = 4 MHz
      ADC1->CR2 |= ADC1_CR2_ALIGN;     //right aligment
     
     while(1){
           // select the ADC channel
           if (vs_sel==0){
               ADC1->CSR |= (ADC1_CSR_CH & CH_VS12);     
          } else if (vs_sel==1){
               ADC1->CSR |= (ADC1_CSR_CH & CH_VS5);
          }
    }
}

Timer 4 Interrupt:
@far @interrupt void irq_system_tim4_ovf (void)
{
       // If MAX NO OF SAMPLES are taken then voltage
          // values will not be recorded in array vs12_arr
          no_of_sample_vals = 0;
          while( no_of_sample_vals < MAX_NO_SAMPLE_VAL )     
          {                                            
                    //start ADC
                    ADC1->CR1 |= ADC1_CR1_ADON;          //ADC powered up
                    ADC1->CR1 |= ADC1_CR1_ADON;          //begin conversion     
                    //check for the EOC
                    while (!(ADC1->CSR & ADC1_CSR_EOC)){}; 
                    //must read LSBs first
                    if (vs_sel==0){
                         vs12_arr[no_of_sample_vals] = ADC1->DRL;                         
                         vs12_arr[no_of_sample_vals] |= ADC1->DRH << 8;
                    } else if (vs_sel==1){
                         vs5_arr[no_of_sample_vals] = ADC1->DRL;                         
                         vs5_arr[no_of_sample_vals] |= ADC1->DRH << 8;
                    }
                    //ADC powered down
                    ADC1->CR1 |= ~ADC1_CR1_ADON;     
          
                    no_of_sample_vals++;
          }
          // Update the time counter
          flag_10ms = 1;
          if (t_10ms==100){  /* 1 sec is completed */
            flag_1sec = 1;
               t_10ms = 0;
          }
          t_10ms++;
          vs_sel++;
          if (vs_sel==3) vs_sel = 0;
          // Clear the flag
    TIM4->SR1 &=~(0x01);
    return;
}





Outcomes