This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

STM8 microcontroller although it is 8 microcontroller, but the function is still very powerful, today to realize the analog watchdog function of STM8 microcontroller ADC.

The official introduction is as follows:

The function of the watchdog is well known, but what is this simulated watchdog? To put it simply, the analog watchdog can monitor the ADC sampled data in real time. When the sampled data value is less than the set minimum value or greater than the set maximum value, the microcontroller will trigger the ADC interrupt. This is very practical in temperature monitoring. For example, when the temperature value of the device is not in the set range, the interruption will be triggered automatically, without the need for the program to collect the value of the ADC channel all the time, and then use the software to judge whether the current temperature value exceeds the normal range.

Here is a demonstration of how this simulated watchdog function works:

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

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

// The AD channel pin is initialized
void ADC_GPIO_Init( void )
{
    PD_DDR &= ~( 1 << 3 );              //PD3 is set to input current
    PD_CR1 &= ~( 1 << 3 );              //PD3 is set to dangling input
}
void ADC_CH_Init( u8 ch )
{
    char l = 0;
    ADC_CR1  = 0x00;                    //fADC = fMASTER/2, 8Mhz single conversion, no conversion
    ADC_CSR  |= ch ;                     // Select AD input channel such as PD2(AIN3)
    ADC_CR2  = 0x00;                    // By default, data is read high and low first
 
    ADC_TDRL = ( 1 <<  ch  );           // Disable schmidt trigger function 1 of corresponding channel by ch+1 bit
    ADC_CR1 |= 0x01;                    // Enable ADC and start conversion
    
    // Set the upper threshold value
    ADC_HTRH = ( u8 )( 800 >> ( u8 )2 );    // Store the top 8 bits of 10 bits of data
    ADC_HTRL = ( u8 )800;                   // Store the lower 8 bits of 10 bits of data
    // Set the lower threshold
    ADC_LTRH = ( u8 )( 300 >> ( u8 )2 );    // Store the top 8 bits of 10 bits of data
    ADC_LTRL = ( u8 )300;                   // Store the lower 8 bits of 10 bits of data
    ADC_CSR |= 0x10;                       // Enable watchdog interrupt

    for( l = 0; l < 100; l++ );         // Delay to ensure that the ADC module is powered on for at least 7us
    ADC_CR1 = ADC_CR1 | 0x01;           // Again enable ADC at the lowest position 1 of register CR1 and begin conversion
}

// Collect PD2 voltage
u16 ReadVol_CH3( void )
{
    u16 voltage = 0;
    while( ( ADC_CSR & 0x80) = =0 );      // Wait for the conversion to finish
    if( ADC_CSR & 0x80 )
    {
        DATAH = ADC_DRH;                    // Read the high 8 bits of the ADC result
        DATAL = ADC_DRL;                    // Read the lower 8 bits of the ADC result
        voltage = ( DATAH << 2 ) + DATAL ; // Get ten digit precision data 0--1024
        ADC_CR1 = ADC_CR1 | 0x01;          // Start the next conversion again with the CR1 register's lowest position 1
        ADC_CSR &= 0x7F;
    };
    return voltage;
}

//AD interrupt service function Interrupt number 22
#pragma vector = 24                     // Interrupt number in IAR, add 2 to interrupt number in STVD
__interrupt void ADC_Handle( void )
{
    ADC_CSR &= ~0x40;
    // Handle temperature anomalies
}

Copy the code

ADC uses single-trigger mode, and then sets the ADC_HTR register to the upper alarm value (800), and the ADC_LTRL register to the lower alarm value (300), that is, when the ADC sample value is greater than 800 or less than 300, the ADC will interrupt. Then set bit 4 of the ADC_CSR register, the AWDIE bit, to 1 to turn on the analog watchdog interrupt. The ADC sample values are then read looping through the main function.

The main program code is as follows:

#include "iostm8s103f3.h"
#include "led.h"
#include "adc.h"

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

u16 val1 = 0;
void main( void )
{
    SysClkInit();
    __asm( "sim" );                       // Disable interrupts
    LED_GPIO_Init();
    ADC_CH_Init( 3 );
    __asm( "rim" );                       // Enable interrupts
    while( 1) { LED = ! LED;/ / samplingval1 = ReadVol_CH3(); }}Copy the code

Val1 is the sampled voltage value. Run the program at full speed and observe the sampled value in the observation window:

When the sampling voltage is between 300 and 800, the ADC interrupt function does not fire.

When the voltage value is below 300, the ADC interrupt is triggered at position 6 of the ADC_CSR register, indicating that an analog watchdog interrupt has been generated.

When the sample value is greater than 800, interrupts can also occur

After an interrupt occurs, manually clear the AWD flag in the interrupt.

One particular problem to note here is that when setting the upper and lower limits for the simulated watchdog, the high register stores the high 8 bits of the 10 bit value, and the low register stores the low 2 bits of the 10 bit value.

Please refer to the Register Settings in the English manual. The description of these four registers in the Chinese reference manual is wrong. If you follow the instructions in the Chinese manual, the simulated watchdog will never come out of the interrupt. Be careful.

The description of these registers in the Chinese manual is wrong

The Chinese reference manual here was downloaded from the official website of ST. I don’t know whether the official staff made some mistakes in writing or made some mistakes in translation. Be careful with this four-register setting when using the analog watchdog.