STM8 MCU ADC single sampling mode

  the internal ADC of STM8S003 single chip microcomputer is 12 bits. Each channel of A/D conversion can perform single and continuous conversion mode.

  single conversion mode means that the ADC will stop conversion after converting data once every time. If it needs to continue conversion, it needs to manually turn on the second conversion function.

  continuous conversion mode means that after each conversion, the system will automatically start the second conversion without manually setting the start of the second conversion, that is, the continuous conversion mode only needs to be started once.

ADC block diagram is as follows:

ADC conversion sequence diagram is as follows:

The following code is used to realize the single conversion mode of ADC:

#include "adc.h"
#include "main.h"

u16  DATAH = 0;                          //ADC conversion value high 8 bits
u16  DATAL = 0;                          //ADC conversion value lower 8 bits
_Bool ADC_flag = 0;                     //ADC conversion success flag

//AD channel pin initialization
void ADC_GPIO_Init( void )
{
    PD_DDR &= ~( 1 << 3 );              //PD3 is set to input current
    PD_CR1 &= ~( 1 << 3 );              //PD3 is set as suspended input
}
//ch is the corresponding pin of MCU
void ADC_CH_Init( u8 ch )
{
    char l = 0;
    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz single conversion, conversion prohibited
    ADC_CSR  = ch + 1;                  //Control status register to select AD input channel, such as PD2(AIN3)
    ADC_CR2  = 0x00;                    //By default, when reading data with left alignment, read high first and read low
    ADC_TDRL = ( 1 << ( ch + 1 ) );     //The Schmitt trigger function 1 of the corresponding channel is prohibited to shift to the left by ch+1 bit
    ADC_CR1 |= 0x01;                    //Enable ADC and start conversion
    ADC_CSR |= 0x20;                    //EOCIE enable conversion end interrupt EOC interrupt enable
    for( l = 0; l < 100; l++ );         //Delay to ensure that the power on of ADC module is completed for at least 7us
    ADC_CR1 = ADC_CR1 | 0x01;           //Enable the ADC again at the lowest position 1 of the CR1 register and start the conversion
}

//Collect PD3 voltage value
u16 ReadVol_CH3( void )
{
    u16 voltage = 0;
    if( ADC_flag )
    {
        ADC_flag = 0;
        voltage = ( DATAH << 2 ) + DATAL ; //Get ten bit precision data 0 -- 1024
        ADC_CR1 = ADC_CR1 | 0x01;          //Start the next conversion again at the lowest position 1 of CR1 register
    };
    return voltage;
}
//AD interrupt service function interrupt number 22
#Pragma vector = 24 / / for the interrupt number in IAR, add 2 to the interrupt number in STVD
__interrupt void ADC_Handle( void )
{
    ADC_CSR &= ~0x80;                   // The conversion end flag bit is cleared EOC
    //By default, when reading data with left alignment, first read the high 8 bits and then the low 8 bits
    DATAH = ADC_DRH;                    // Read the upper 8 bits of the ADC result
    DATAL = ADC_DRL;                    // Read the lower 8 bits of the ADC result
    ADC_flag = 1;                       // ADC interrupt flag set to 1
}

A stabilization time is required when the ADC is started for the first time. Therefore, during initialization, it takes a certain time to wait for the ADC to stabilize. After it is stable, the ADC conversion can be started. Here, the interrupt is used to read the conversion result. When the ADC conversion is replaced, an interrupt will be generated. Then, the conversion result will be read in the interrupt, and the flag bit will be set at the same time. The program loops to read the flag bit. When the flag bit is 1, the conversion is completed, and the conversion result can be output. Then the ADC_ The lowest bit of CR1 register is manually set to 1 to start the next conversion.

ADC_CR1 registers are as follows:

ADON bit is the conversion switch of ADC. In single mode, write 1 to ADON bit to start conversion.

Only one channel is used here. It can be seen from the top ADC block diagram that there are many channels in an ADC. What should I do if I want to collect multiple channels?

#include "adc.h"
#include "main.h"

u16  DATAH = 0;                          //ADC conversion value high 8 bits
u16  DATAL = 0;                          //ADC conversion value lower 8 bits
_Bool ADC_flag = 0;                     //ADC conversion success flag

//AD channel pin initialization
void ADC_GPIO_Init( void )
{
    PD_DDR &= ~( 1 << 3 );              //PD3 is set to input current
    PD_CR1 &= ~( 1 << 3 );              //PD3 is set as suspended input
}
//ch is the corresponding pin of MCU
void ADC_CH_Init( u8 ch )
{
    char l = 0;
    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz single conversion, conversion prohibited
    ADC_CSR  = ch + 1;                  //Control status register to select AD input channel, such as PD2(AIN3)
    ADC_CR2  = 0x00;                    //By default, when reading data with left alignment, read high first and read low
    ADC_TDRL = ( 1 << ( ch + 1 ) );     //The Schmitt trigger function 1 of the corresponding channel is prohibited to shift to the left by ch+1 bit
    ADC_CR1 |= 0x01;                    //Enable ADC and start conversion
    //ADC_CSR |= 0x20;                    //EOCIE enable conversion end interrupt EOC interrupt enable
    for( l = 0; l < 100; l++ );         //Delay to ensure that the power on of ADC module is completed for at least 7us
    ADC_CR1 = ADC_CR1 | 0x01;           //Enable the ADC again at the lowest position 1 of the CR1 register and start the conversion
}

//Collect PD3 voltage value
u16 ReadVol_CH3( void )
{
    u16 voltage = 0;
    //If it is called only once during program initialization, the sampling speed is very fast.
    //If initialization is called every time, the speed will be 1 / 10 of the original
    ADC_CH_Init( 3 );
    while( ( ADC_CSR & 0x80 ) == 0 );      //Wait for the conversion to end
    if( ADC_CSR & 0x80 )
    {
        DATAH = ADC_DRH;                    // Read the upper 8 bits of the ADC result
        DATAL = ADC_DRL;                    // Read the lower 8 bits of the ADC result
        voltage = ( DATAH << 2 ) + DATAL ; //Get ten bit precision data 0 -- 1024
        ADC_CR1 = ADC_CR1 | 0x01;          //Start the next conversion again at the lowest position 1 of CR1 register
        ADC_CSR &= 0x7F;
    };
    return voltage;
}

//Collect PD2 voltage value
u16 ReadVol_CH4( void )
{
    u16 voltage = 0;
    //If it is called only once during program initialization, the sampling speed is very fast.
    //If initialization is called every time, the speed will be 1 / 10 of the original
    ADC_CH_Init( 2 );
    while( ( ADC_CSR & 0x80 ) == 0 );      //Wait for the conversion to end
    if( ADC_CSR & 0x80 )
    {
        DATAH = ADC_DRH;                    // Read the upper 8 bits of the ADC result
        DATAL = ADC_DRL;                    // Read the lower 8 bits of the ADC result
        voltage = ( DATAH << 2 ) + DATAL ; //Get ten bit precision data 0 -- 1024
        ADC_CR1 = ADC_CR1 | 0x01;          //Start the next conversion again at the lowest position 1 of CR1 register
        ADC_CSR &= 0x7F;
    };
    return voltage;

If multiple channels need to be converted, after one channel is converted, it needs to be reinitialized to switch the conversion channels. Since the ADC needs stabilization time after switching channels, if multiple channels switch sampling data back and forth, it is much slower than sampling data alone for one channel, because switching channels once requires waiting for a period of time to stabilize the ADC.

When data is read, the corresponding function is called directly in the main function.

#include "iostm8s103F3.h"
#include "led.h"
#include "adc.h"
#include "stdio.h"

void SysClkInit( void )
{
    CLK_SWR = 0xe1;       //HSI is the main clock source, 16MHz CPU clock frequency
    CLK_CKDIVR = 0x00;    //CPU clock 0 frequency division, system clock 0 frequency division
}

void main( void )
{
    u16 val1 = 0;
    u16 i=0;
    SysClkInit();
    __asm( "sim" );                       //Prohibit interrupt
    LED_GPIO_Init();
    ADC_CH_Init( 3 );
    __asm( "rim" );                       //Open interrupt
    while( 1 )
    {
        LED = !LED;
        val1 = ReadVol_CH3();
    }
}

Keywords: Single-Chip Microcomputer ADC STM8

Added by able on Thu, 23 Dec 2021 01:07:16 +0200