STC8H Development (Part 3): Introduction and demonstration of analog-to-digital conversion ADC based on FwLib_STC8

Publisher:数据梦想Latest update time:2022-06-09 Source: eefocusKeywords:ADC Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The previous section introduces how to use FwLib_STC8 in Keil5 and PlatformIO environments. Next, we will focus on the STC8H series and introduce ADC (analog-to-digital conversion) in combination with the demonstration use cases in the demo.


ADC analog-to-digital conversion of STC8G and STC8H

The ADC part of STC8G and STC8H is basically the same in register settings, but the channel numbers, channel quantities and accuracy corresponding to different models are different.


Number of channels and accuracy

The number of channels and accuracy of each series corresponding to STC8G/STC8H are as follows.

image.png

The channel selection uses the lower 4 bits of the register ADC_CONTR, corresponding to the various series of STC8G/STC8H. The channels corresponding to the values ​​of this register are as follows

image.png

Alignment format of conversion results

The ADC sampling accuracy cannot actually be set. The sampling is performed with the maximum accuracy of the current model, and the results are stored in the two registers [ADC_RES, ADC_RESL]. In order to facilitate the use of results of different accuracy in different occasions, the results can be set to left-aligned or right-aligned.


When set to left-aligned, you can only take the value of ADC_RES (8 bits) and ignore the last two bits.

When the bit is set to right-align, according to the actual accuracy, the lower 4 bits (12-bit accuracy) or lower 2 bits (10-bit accuracy) of ADC_RES can be taken and added to ADC_RESL to get the final result.

Time consumption for conversion

A complete ADC conversion time = Tsetup + Tduty + Thold + Tconvert


Tsetup: Channel switching time for conversion, can be set to 1 or 2 ADC clock cycles

Tduty: The sampling time of the conversion, the default is the minimum 11 ADC clocks, the maximum is 32 ADC clock cycles

Thold: Channel selection hold time, can be selected as 1, 2, 3, 4 ADC clock cycles

Tconvert: The conversion time is fixed, 10-bit precision is 10 ADC clocks, 12-bit precision is 12 ADC clocks

The above time units are all ADC clock cycles. The number of system clocks (SYSCLK) occupied by each ADC clock cycle can be set. Using the lower three bits of the ADCCFG register, it can be set from a minimum of 2 system clock cycles to a maximum of 32 system clock cycles.


For the highest conversion frequency, a global limit is written on DS


The speed of 10-bit ADC cannot exceed 500KHz

The speed of 12-bit ADC cannot exceed 800KHz

The conversion sampling time cannot be less than 10, and it is recommended to set it to 15

Hardware Connection

There are two types of ADC hardware connections for STC8G/STC8H: with AVcc, AGRND and without AVcc, AGRND


带 AVcc, AGrnd

The high-end model STC8H3K64S2 series, for example, has these two pins, which correspond to the voltage reference value and ground reference value of the conversion target. For ordinary use, these two can be directly connected to VCC and GND, and the connection is


   AGrnd   -> GND

   AVcc    -> VCC

   AVref   -> VCC 

   Vcc     -> VCC

   Gnd     -> GND

   ADC1 -> sampling point


Without AVcc,AGrnd

Low-end models and STC8G series do not have these two pins. You only need to connect AVref. The sampling point is connected to the MCU ground. The connection is


   AVref   -> VCC 

   Vcc     -> VCC

   Gnd     -> GND

   ADC1    -> Test voltage


Demonstration use case description

The following demonstration use cases are based on FwLib_STC8. The source code is located in the FwLib_STC8/demo/adc directory. You can download or view it yourself. Due to version evolution, the code may differ from the code in the repository. The latest version in the repository shall prevail.


For information on how to run the demo, please refer to the configuration instructions for Keil C51 and VSCode PlatformIO described earlier.


Use ADC1 for 8-bit ADC conversion, active polling mode

In the following example, the active query method is used to perform ADC conversion on the P1.1 port every 0.1 seconds with an accuracy of 8 bits, and the result is output to the serial port


main.c code


#include "fw_hal.h"


void main(void)

{

    uint8_t res;

    // Adjust the system frequency. If you use STC-ISP to set the frequency, you need to comment out this line

    SYS_SetClock();

    // For result output

    UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);

    // Set ADC1 (GPIO P1.1) to high impedance input

    GPIO_P1_SetMode(GPIO_Pin_1, GPIO_Mode_Input_HIP);

    // Channel used: ADC1

    ADC_SetChannel(0x01);

    // Set ADC clock = SYSCLK / 2 / (1+1) = SYSCLK / 4

    ADC_SetClockPrescaler(0x01);

    // Set the result to left-align, just need to take the value of ADC_RES

    ADC_SetResultAlignmentLeft();

    // Turn on ADC power

    ADC_SetPowerState(HAL_State_ON);


    while(1)

    {

        // Start conversion

        ADC_Start();

        // Wait for two system clocks

        NOP();

        NOP();

        // Check if the conversion result flag is set

        while (!ADC_SamplingFinished());

        // Clear the result flag

        ADC_ClearInterrupt();

        // Read the result

        res = ADC_RES;


        // Output through serial port 1

        UART1_TxString("Result: ");

        UART1_TxHex(res);

        UART1_TxString("rn");

        // Wait 100ms and convert again

        SYS_Delay(100);

    }

}


Use ADC1 for 10-bit/12-bit ADC conversion, interrupt mode

In the following example, the ADC of P1.1 port is continuously converted using interrupts, with a precision of 10 bits (or 12 bits, depending on the MCU model), and the result is output to the serial port every 0.1 seconds.


#include "fw_hal.h"


// 16-bit variable used to record the conversion result

uint16_t res;


// Method for handling interrupts, using macro definitions to ensure compatibility between Keil C51 and SDCC

INTERRUPT(ADC_Routine, EXTI_VectADC)

{

    // Clear the interrupt bit first

    ADC_ClearInterrupt();

    // The lower 8 bits of the result

    res = ADC_RESL;

    // High 8 bits of the result

    res |= (ADC_RES & 0x0F) << 8;

    // Start again to make the ADC convert continuously, 

    ADC_Start();

}


void main(void)

{

    // Set the system frequency

    SYS_SetClock();

    // Result output

    UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);

    // Set P11 to high impedance input mode

    GPIO_P1_SetMode(GPIO_Pin_1, GPIO_Mode_Input_HIP);

    // Channel used: ADC1

    ADC_SetChannel(0x01);

    // ADC clock = SYSCLK / 2 / (1+15) = SYSCLK / 32

    ADC_SetClockPrescaler(0x0F);

    // Right-aligned to facilitate conversion to double-byte results

    ADC_SetResultAlignmentRight();

    // Enable global interrupt and ADC interrupt

    EXTI_Global_SetIntState(HAL_State_ON);

    EXTI_ADC_SetIntState(HAL_State_ON);

    // Turn on ADC power

    ADC_SetPowerState(HAL_State_ON);

    // Start ADC conversion

    ADC_Start();


    while(1)

    {

        //Conversion result output

        UART1_TxString("Result: ");

        UART1_TxHex(res >> 8);

        UART1_TxHex(res & 0xFF);

        UART1_TxString("rn");

        SYS_Delay(100);

    }

}


Use ADC1 and ADC2 dual channels for conversion, interrupt mode

The following is a more practical example, which performs multi-channel ADC conversion in the form of interrupts. It can be used for wireless car remote control, dual-channel audio sampling, etc.


#include "fw_hal.h"


// Used to record the channel number of the current sampling

uint8_t pos;

// Record the sampling results of each channel

uint16_t res[2];


//Interrupt handling method

INTERRUPT(ADC_Routine, EXTI_VectADC)

{

    ADC_ClearInterrupt();

    //Record sampling results

    res[pos] = ADC_RESL;

    res[pos] |= (ADC_RES & 0x0F) << 8;

    

    // Switch to the next channel

    pos = (pos+1) & 0x1;

    if (pos == 0)

    {

        /**

         * When the sampling frequency is high, adding these two sentences can improve the accuracy. The mechanism is to switch to open-drain mode to clear the residual voltage on the sampling port

        GPIO_P1_SetMode(GPIO_Pin_1, GPIO_Mode_InOut_OD);

        GPIO_P1_SetMode(GPIO_Pin_1, GPIO_Mode_Input_HIP);

        */

        ADC_SetChannel(0x01);

    }

    else

    {

        /**

         * Uncomment these lines in high speed ADC

        GPIO_P1_SetMode(GPIO_Pin_2, GPIO_Mode_InOut_OD);

        GPIO_P1_SetMode(GPIO_Pin_2, GPIO_Mode_Input_HIP);

        */

        ADC_SetChannel(0x02);

    }

    ADC_Start();

}


// The following code is basically the same as the previous one, so I won't comment it in detail.

void main(void)

{

    SYS_SetClock();

    // For debug print

    UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);

    // Channel: ADC1

    ADC_SetChannel(0x01);

    // ADC Clock = SYSCLK / 2 / (1+15) = SYSCLK / 32

    ADC_SetClockPrescaler(0x0F);

    // Right alignment, high 2-bit in ADC_RES, low 8-bit in ADC_RESL

    ADC_SetResultAlignmentRight();

    // Enable interrupts

    EXTI_Global_SetIntState(HAL_State_ON);

    EXTI_ADC_SetIntState(HAL_State_ON);

    // Turn on ADC power

    ADC_SetPowerState(HAL_State_ON);

    // Set ADC1(P1.1), ADC2(P1.2) HIP

    GPIO_P1_SetMode(GPIO_Pin_1|GPIO_Pin_2, GPIO_Mode_Input_HIP);

    // Start ADC

    ADC_Start();


    while(1)

    {

        UART1_TxString("Result: ");

        UART1_TxHex(res[0] >> 8);

        UART1_TxHex(res[0] & 0xFF);

        UART1_TxChar(' ');

        UART1_TxHex(res[1] >> 8);

        UART1_TxHex(res[1] & 0xFF);

        UART1_TxString("rn");

        SYS_Delay(100);

    }

}


Finish

The above is a demonstration of the use case of STC8H using the FwLib_STC8 package library for ADC conversion. In actual use, the delay time accuracy in the active polling mode is not high.

If there is a requirement for the accuracy of the sampling time interval, it is recommended to use the interrupt form.

Keywords:ADC Reference address:STC8H Development (Part 3): Introduction and demonstration of analog-to-digital conversion ADC based on FwLib_STC8

Previous article:STC8H Development (IV): Introduction and Precautions of FwLib_STC8 Package Library
Next article:STC8H Development (Part 2): Configuring and using the FwLib_STC8 package library in Linux VSCode

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号