help me with implementation of reading adc values and printing them via rs485, now it doesnt output anything, here are my files.
adc.h
#ifndef ADC_H
#define ADC_H

#include "ch32v20x_adc.h"
#include "ch32v20x_rcc.h"
#include "main.h"
#include "gpios.h"
#include "math.h"
#include "stdio.h"
#include "rs485.h"

class Adc {
  public:
    Adc();
    static Adc* pThis;
    void getAdc();
    void printValues();
    void sendDataOverRS485();
    inline bool startConversion() {
        if (ADC1->STATR & ADC_JEOC) return false;
        ADC1->CTLR2 |= ADC_JSWSTART; // start conversion
        return true;
    }
    bool isConversionCompleteted() {
        if (ADC1->STATR & ADC_JEOC) {
            return true;
        } else {
            return false;
        }
    }
    uint16_t averageR = 0;
    uint16_t averageI = 0;
    uint16_t R = 0;
    uint16_t I = 0;

    void handler();

  private:
    void init();

    static constexpr uint32_t MovAverLength = 128;
    constexpr uint32_t MovAverGrade() {
        return log2(MovAverLength);
    }
    uint8_t Index_mov_aver_R = 0;
    uint8_t Index_mov_aver_I = 0;
    uint32_t MovAverSum_R = 0;
    uint32_t MovAverSum_I = 0;
    uint16_t arr_R[MovAverLength] = {0};
    uint16_t arr_I[MovAverLength] = {0};
    uint8_t counterADC = 0;
    uint32_t sumR = 0;
    uint32_t sumI = 0;
    uint16_t moving_average_R(uint16_t val);
    uint16_t moving_average_I(uint16_t val);


    int8_t Calibrattion_Val = 0;
    uint16_t tempVal = 0;
    //-----------  GPIOs driver  ----------------------------------------------
    // actuator's potentiometer values
    Gpios::In<Gpios::PA, 1> a1;
    // I actuator
    Gpios::In<Gpios::PA, 2> a2;

};

#endif // ADC_H
adc.cpp
#include "adc.h"

Adc* Adc::pThis = nullptr;
Adc::Adc() {
    pThis = this;
    init();
}

uint16_t Adc::moving_average_R(uint16_t val) {
    MovAverSum_R -= arr_R[Index_mov_aver_R];
    MovAverSum_R += val;
    arr_R[Index_mov_aver_R] = val;
    Index_mov_aver_R++;
    if (Index_mov_aver_R >= MovAverLength) {
        Index_mov_aver_R = 0;
    }
    averageR = MovAverSum_R >> MovAverGrade();
    return averageR;
}

uint16_t Adc::moving_average_I(uint16_t val) {
    MovAverSum_I -= arr_I[Index_mov_aver_I];
    MovAverSum_I += val;
    arr_I[Index_mov_aver_I] = val;
    Index_mov_aver_I++;
    if (Index_mov_aver_I >= MovAverLength) {
        Index_mov_aver_I = 0;
    }
    averageI = MovAverSum_I >> MovAverGrade();
    return averageI;
}

void Adc::init() {
    // init ADC1
    // PA1 PA2 - analog input mode : 0:0:0:0
    // RCC->APB2PCENR |= RCC_IOPAEN;
    // GPIOA->CFGLR &= ~(GPIO_CFGLR_CNF0);
    // GPIOA->CFGLR &= ~(GPIO_CFGLR_MODE0);
    
    
    RCC->APB2PCENR |= RCC_ADC1EN;
    // PCLK2 = 8 MHz ADC_CLK = 4 MHz
    RCC->CFGR0 |= RCC_ADCPRE_DIV2;
    
    //TODO: if moving average method does big uncertainity remake to median 
    // with max core clock
    //
    // PCLK2 - 72MHz / 6 = ADC_CLK = 12 MHz - max Adc speed
    //RCC->CFGR0 |= RCC_ADCPRE_DIV6;

    ADC1->CTLR2 |= ADC_JEXTSEL;  // 1:1:1 JEXTTRIG software trigger
    ADC1->CTLR2 |= ADC_JEXTTRIG; // conversion on external signal
    // A1 and A2 channel
    //ADC1->SAMPTR2 |= ADC_SMP0; // 1:1:1 239 cycles conversion
    ADC1->SAMPTR2 &= ~(ADC_SMP1 | ADC_SMP2); //0:0:0 1.5 cycles conversion
    ADC1->SAMPTR2 |= (ADC_SMP1_2 | ADC_SMP2_2); //1:0:0 45 cycles conversion
    ADC1->ISQR |= (2 << 20); // two channel
    ADC1->ISQR |= (1 << 15); // channel 1
    ADC1->ISQR |= (2 << 10); // channel 2

    ADC1->CTLR2 |= ADC_ADON;

    // ADC_ResetCalibration(ADC1);
    ADC1->CTLR2 |= ADC_RSTCAL;
    // while(ADC_GetResetCalibrationStatus(ADC1));
    while (ADC1->CTLR2 & ADC_RSTCAL) {}
    // ADC_StartCalibration(ADC1);
    ADC1->CTLR2 |= ADC_CAL;
    // while (ADC_GetCalibrationStatus(ADC1));
    while (ADC1->CTLR2 & ADC_CAL) {}
    Calibrattion_Val = ADC1->RDATAR;
    // Calibrattion_Val = Get_CalibrationValue(ADC1);
}

void Adc::handler() { getAdc(); }

void Adc::sendDataOverRS485() {
    uint8_t data[2];
    data[0] = static_cast<uint8_t>(R >> 8);      // High byte of R
    data[1] = static_cast<uint8_t>(R & 0xFF);    // Low byte of R
    
    RS485::pThis->writeBytes(data, sizeof(data));  // Send the array over RS485
}

void Adc::getAdc() {
    if (startConversion()) {
        // started
    } else {
        if (isConversionCompleteted()) {
            // exclude the last two bits to reduce ADC noise
            R = ADC1->IDATAR1 & 0xFFFC;
            // moving_average_R(ADC1->IDATAR1 & 0xFFFC);
            // sendDataOverRS485();            
        }
    }
}
actuator.cpp
#include "actuator.h"
Actuator* Actuator::pThis = nullptr;
Actuator::Actuator() {
    //memset((void*)&dataReceived, 0, sizeof(ProtocolUart::DataReceive));
    pThis = this;
    init();
}
void Actuator::init() {}

void Actuator::handler() {
    //-----------------     adc handler ---------------------------------------
    adc.handler();
    #if 0
    // TODO: experimentally get ADC_max and ADC_min to count percent
    current_percent = adcToPercent(adc.averageR);
    // TODO: check I,
    // when actuator goes down, I ~ 200 mA, by controlling this I we can realize
    // that something wrong
    if (currentState == GO_DOWN) {
        uint16_t mA = (5000 * adc.averageI) / 4095; // 5A max
        if (mA > 400) {
            // TODO: pause (to remove disturbing object)
            stop();
            // TODO dummy pause, need to remake later by timer
            for (volatile int i = 0; i < 100000; ++i) {}
            down_start();
        }
    }
    #endif

    //---------------   protocol communication   ------------------------------
    if (!RS485::pThis->getIsNeedRead()) {
        //   parse received data if it is
        dataReceived =
            ProtocolUart::parseData(RS485::pThis->arr, RS485::SIZE_RECEIVE);
        RS485::pThis->setIsNeedRead(true);
        if (!dataReceived.ERR) {
            receivedNewCommand = true;
        }
    }
    if (receivedNewCommand) {
        receivedNewCommand = false;
        // reply current status
        if (dataReceived.command == ProtocolUart::STATUS) {
            Buzzer::pThis->on();
            for (int i = 0; i < 2000; i++) {}
            Buzzer::pThis->off();
            // hardcoded current percent of actuator's ADC
            // TODO: get real ADC values
            current_percent = 50;
            uint8_t arr[5] = {ProtocolUart::TO,
                              static_cast<uint8_t>(Rollette::pThis->currentRollState),
                              current_percent, 0, 0};
            uint16_t CS = ProtocolUart::crc_chk(arr, sizeof(arr) - 2);
            arr[3] = static_cast<uint8_t>(CS >> 8); 
            arr[4] = static_cast<uint8_t>(CS & 0xFF);
            RS485::pThis->writeBytes(arr, sizeof(arr));
        // open rolette mechanism    
        } else if (dataReceived.command == ProtocolUart::GET_ADC) {
            uint8_t arr[5] = {ProtocolUart::TO,
                              static_cast<uint8_t>(Adc::pThis->R),
                              0, 0, 0};
            uint16_t CS = ProtocolUart::crc_chk(arr, sizeof(arr) - 2);
            arr[3] = static_cast<uint8_t>(CS >> 8); 
            arr[4] = static_cast<uint8_t>(CS & 0xFF);
            RS485::pThis->writeBytes(arr, sizeof(arr));
        } else if (dataReceived.command == ProtocolUart::TURN_ON) {
            Buzzer::pThis->on();
            for (int i = 0; i < 2000; i++) {}
            Buzzer::pThis->off();
            // send acknowledgment msg
            RS485::pThis->writeBytes(RS485::pThis->arr, RS485::SIZE_RECEIVE);
            // proceed motor control
            Rollette::pThis->rollette_open();
        } else if (dataReceived.command == ProtocolUart::TURN_OFF) {
            // Buzzer::pThis->on();
            // send acknowledgment msg
            RS485::pThis->writeBytes(RS485::pThis->arr, RS485::SIZE_RECEIVE);
            Rollette::pThis->rollette_close();
            // proceed motor control
            // Rollette::pThis->stopMotor();
        } else if (dataReceived.command == ProtocolUart::EMERGENCY_ON) {
            IsEmergency = true;
            RS485::pThis->writeBytes(RS485::pThis->arr, RS485::SIZE_RECEIVE);
        } else if (dataReceived.command == ProtocolUart::EMERGENCY_OFF) {
            IsEmergency = false;
            RS485::pThis->writeBytes(RS485::pThis->arr, RS485::SIZE_RECEIVE);
        } else {
            // Other command reply is mirror
            RS485::pThis->writeBytes(RS485::pThis->arr, RS485::SIZE_RECEIVE);
        }
    }


    //--------------    State Machine   ---------------------------------------
    switch (currentState) {
    #if 0
    case DOWN:
        if (current_percent < 2) {}
        Rollette::pThis->handler(IsEmergency);
        if (Rollette::pThis->currentRollState == Rollette::OPENED_FULL) {
            // TODO: wait for up signal
            if (IsOn) {
                currentState = GO_UP;
            }
            // currentState = GO_UP;
            Buzzer::pThis->turnOn();
            down_stop();
            up_start();
        }
        break;
    case GO_UP:
        Rollette::pThis->WasOpened = true;
        // Emergency button press processing
        if (!EmergencyOneTime) {
            if (IsEmergency) {
                stop();
                EmergencyOneTime = true;
            }
        } else {
            if (!IsEmergency) {
                EmergencyOneTime = false;
                down_stop();
                up_start();
            }
        }
        // wait for adc in some position
        if (current_percent >= stop_percent) {
            stop();
            currentState = UP;
        }
        break;
    case UP:
        Buzzer::pThis->turnOff();
        // wait for down signal or signal to adc position
        if (receivedNewCommand) {
            receivedNewCommand = false;
            if (dataReceived.command == ProtocolUart::TURN_OFF) {
                down_start();
                timerStart(TIME_FULL_CLOSE_FROM_UP_TO_DOWN);
                // checkout timer start
                currentState = GO_DOWN;
            } else if (dataReceived.command == ProtocolUart::NEW_PERCENT) {
                // check direction
                if (current_percent > stop_percent) {
                    // go down
                    up_stop();
                    down_start();
                    currentState = GO_TO_NEW_UP;
                } else if (current_percent < stop_percent) {
                    // go up
                    down_stop();
                    up_start();
                    currentState = GO_TO_NEW_UP;
                }
            }
        }
        // by button
        if (IsOff) {
            down_start();
            currentState = GO_DOWN;
        }
        break;
    case GO_TO_NEW_UP:
        // check stop condition
        // Emergency button press processing
        Buzzer::pThis->turnOn();
        if (current_percent > stop_percent + 2) {
            // go down
            if (!EmergencyOneTime) {
                if (IsEmergency) {
                    stop();
                    EmergencyOneTime = true;
                }
            } else {
                if (!IsEmergency) {
                    EmergencyOneTime = false;
                    up_stop();
                    down_start();
                }
            }
        } else if (current_percent < stop_percent - 2) {
            // go up
            if (!EmergencyOneTime) {
                if (IsEmergency) {
                    stop();
                    EmergencyOneTime = true;
                }
            } else {
                if (!IsEmergency) {
                    EmergencyOneTime = false;
                    down_stop();
                    up_start();
                }
            }
        } else {
            // stop percent +- 1
            stop();
            currentState = UP;
        }
        break;
    case GO_DOWN:
        Buzzer::pThis->turnOn();
        // Emergency button press processing
        if (!EmergencyOneTime) {
            if (IsEmergency) {
                stop();
                EmergencyOneTime = true;
            }
        } else {
            if (!IsEmergency) {
                EmergencyOneTime = false;
                up_stop();
                down_start();
            }
        }
        // TODO: wait for adc not changing and R percent is low
        if (current_percent < 2) {
            // adc not changed checkout
            if (!AdcChanging) {
                currentState = DOWN;
            }
            //  timer checkout
            if (IsTimeout) {
                IsTimeout = false;
                currentState = DOWN;
            }
        }
        break;
    #endif
    default:
        break;
    }
}

//--------------------   timers  ---------------------------------------------
void Actuator::interruptHandler() {
    // Check full close time
    if (Actuator::pThis->TimerStart) {
        if (Actuator::pThis->timerCounter >= Actuator::pThis->timerCounterMax) {
            Actuator::pThis->timerCounter = 0;
            timeout();
        } else {
            Actuator::pThis->timerCounter++;
        }
    }
    // check adc changing
    Actuator::pThis->adcCurrent = Actuator::pThis->adc.averageR;
    if (Actuator::pThis->adcCounter >= Actuator::ADC_CHECK_CHANGING_TIME) {
        Actuator::pThis->adcCounter = 0;
        // adcPrevious != adcCurrent +- 50
        if ((Actuator::pThis->adcPrevious <=
             Actuator::pThis->adcCurrent + Actuator::ADC_DEVIATION) &&
            (Actuator::pThis->adcPrevious >=
             Actuator::pThis->adcCurrent - Actuator::ADC_DEVIATION)) {
            // set state
            Actuator::pThis->AdcChanging = false;
        } else {
            Actuator::pThis->AdcChanging = true;
        }
    } else {
        Actuator::pThis->adcCounter++;
    }
    Actuator::pThis->adcPrevious = Actuator::pThis->adcCurrent;
    // check buttons states (exclude bounce)
    if (Actuator::pThis->isOn()) {
        if (Actuator::pThis->butOnBounceCounter >= Actuator::BOUNCE_TIME_MAX) {
            Actuator::pThis->IsOn = true;
            Actuator::pThis->butOnBounceCounter = 0;
        } else {
            Actuator::pThis->IsOn = false;
            Actuator::pThis->butOnBounceCounter++;
        }
    } else {
        Actuator::pThis->IsOn = false;
        Actuator::pThis->butOnBounceCounter = 0;
    }
    if (Actuator::pThis->isOff()) {
        if (Actuator::pThis->butOffBounceCounter >= Actuator::BOUNCE_TIME_MAX) {
            Actuator::pThis->IsOff = true;
            Actuator::pThis->butOffBounceCounter = 0;
        } else {
            Actuator::pThis->IsOff = false;
            Actuator::pThis->butOffBounceCounter++;
        }
    } else {
        Actuator::pThis->IsOff = false;
        Actuator::pThis->butOffBounceCounter = 0;
    }
}

void Actuator::timerStart(uint16_t ms) {
    timerCounterMax = ms;
    TimerStart = true;
}
void Actuator::timerStop() { TimerStart = false; }
void Actuator::timeout() {
    Actuator::pThis->timerStop();
    Actuator::pThis->IsTimeout = true;
}

uint16_t Actuator::adcToPercent(uint16_t adc_val) {
    // direct dependancy
    // return (100 * (adc.averageR - ADC_VAL_MIN)) / ADC_VAL_MAX;
    // inverse dependancy
    return (100 * (ADC_VAL_MAX - (adc_val - ADC_VAL_MIN))) / ADC_VAL_MAX;
}
actuator.h
#ifndef ACTUATOR_H
#define ACTUATOR_H

#include "adc.h"
#include "gpios.h"
#include "main.h"
#include "rollette.h"
#include "rs485.h"
#include "string.h"

class Actuator {
  public:
    Actuator();
    static Actuator* pThis;
    Adc adc;
    ProtocolUart::DataReceive dataReceived = {};
    bool receivedNewCommand = false;
    bool IsEmergency = false;
    bool EmergencyOneTime = false;
    enum State : uint8_t {
        DOWN,
        GO_UP,
        UP,
        GO_TO_NEW_UP,
        GO_DOWN
    };
    State currentState = State::DOWN;

    void handler();

    static void interruptHandler();

    inline void setStopPercent(uint8_t percent) { stop_percent = percent; }
    inline uint8_t getStopPercent() { return stop_percent; }

  private:
    void init();

    //---------------  Relays  ------------------------------------------------
    inline void up_start() { open.setHigh(); }
    inline void up_stop() { open.setLow(); }

    // inline void down_start() { close.setHigh(); }
    // inline void down_stop() { close.setLow(); }
    // inline void stop() {
    //     up_stop();
    //     down_stop();
    // }
    //--------------  Buttons  ------------------------------------------------
    inline bool isOn() { return !on.getState(); }
    inline bool isOff() { return !off.getState(); }
    bool IsOn = false;
    bool IsOff = false;
    uint8_t butOnBounceCounter = 0;
    uint8_t butOffBounceCounter = 0;

    //--------------  States  -------------------------------------------------
    // adc max => current_percent = 100%, adc min => 0%;
    uint8_t current_percent = 0;
    uint8_t stop_percent = DEFAULT_PERCENT;

    //----------------  Timer -------------------------------------------------
    void timerStart(uint16_t ms);
    void timerStop();
    static void timeout();
    bool IsTimeout = false;
    bool TimerStart = false;
    uint16_t timerCounter = 0;
    uint16_t timerCounterMax = 0;

    //-----------------  Constants  -------------------------------------------
    static constexpr uint16_t TIME_FULL_CLOSE_FROM_UP_TO_DOWN = 10000;
    static constexpr uint8_t DEFAULT_PERCENT = 50;
    static constexpr uint16_t ADC_CHECK_CHANGING_TIME = 1000;
    static constexpr uint16_t ADC_DEVIATION = 50;
    // TODO: experimentally get ADC_VAL for extreme actuator positions
    static constexpr uint16_t ADC_VAL_MAX = 950;
    static constexpr uint16_t ADC_VAL_MIN = 150;
    static constexpr uint8_t BOUNCE_TIME_MAX = 100;

    //-----------------  Adc --------------------------------------------------
    uint16_t adcToPercent(uint16_t adc_val);
    // In interrupr check is adc changing
    bool AdcChanging = false;
    uint16_t adcCounter = 0;
    uint16_t adcPrevious = 0;
    uint16_t adcCurrent = 0;

    //---------------  Actuator driver  ---------------------------------------
    // On, Off buttons
    Gpios::In<Gpios::PB, 3, Gpios::InitModeIn::FLOATING> on;
    Gpios::In<Gpios::PA, 15, Gpios::InitModeIn::FLOATING> off;
    // Relays
    // Gpios::Out<Gpios::PB, 0, Gpios::InitModeOut::PUSH_PULL> close;
    Gpios::Out<Gpios::PA, 7, Gpios::InitModeOut::PUSH_PULL> open;
};

#endif // ACTUATOR_H
man.cpp
#include "main.h"

#include "actuator.h"
#include "adc.h"
#include "buzzer.h"
#include "gp_timers.h"
#include "gpios.h"
#include "rcc.h"
#include "systim.h"
#include "tirq.h"
#include "foto.h"
#include "rollette.h"

Rcc rcc(0);

RS485 rs485;
Actuator act;
Buzzer buzzer;
Foto foto;
Rollette roll;
Adc adc;

int main(void) {
    //  Static polimorphic interrupt handling subscribing to timer
    ObserverForInterrupt<TIM3_IRQn, RS485, Rollette, Actuator, Buzzer, Foto> timIrq;
    while (1) {
        act.handler();
        #if 0
        if (!Rollette::pThis->endstop.getState()) {
            Buzzer::pThis->on();
            for (int i = 0; i < 200; i++) {}
            Buzzer::pThis->off();
        }
        #endif
        // if (Rollette::pThis->endstop.getState()) {Buzzer::pThis->on();}
    }
    return 0;
}