89 lines
3.2 KiB
C++
89 lines
3.2 KiB
C++
#ifndef STM32U5XX_HAL_ADC_HPP
|
|
#define STM32U5XX_HAL_ADC_HPP
|
|
#include "global_variable.h"
|
|
#include "delay.h"
|
|
#include "prepherials.h"
|
|
#include "queue.hpp"
|
|
#include "reg_adc_gen.h"
|
|
#include "reg_nvic.h"
|
|
#include "reg_rcc.h"
|
|
#include "reg_uart.h"
|
|
#include "stm32u5xx.h"
|
|
|
|
typedef enum {
|
|
ADC_RESOLUTION_12B = 0, ADC_RESOLUTION_10B = 1, ADC_RESOLUTION_8B = 2, ADC_RESOLUTION_6B = 3
|
|
} adc_resolution_e; // todo: check with rm0456
|
|
|
|
typedef enum {
|
|
ADC_SINGLE_ENDED = 0, ADC_DIFFERENTIAL = 1
|
|
} adc_single_diff_e; // todo: check with rm0456
|
|
|
|
class Adc {
|
|
private:
|
|
ADC_TypeDef *ins = nullptr;
|
|
reg_adc_t *reg = nullptr;
|
|
ADC_Common_TypeDef *reg_common = nullptr;
|
|
queue20u32 data_queue;
|
|
|
|
public:
|
|
Adc() = default;
|
|
|
|
void setup(ADC_TypeDef *adc, ADC_Common_TypeDef *adc_common) {
|
|
reg_common = adc_common, ins = adc, reg = (reg_adc_t *) ins;
|
|
}
|
|
|
|
hal_status_e init(int channel = 0, adc_resolution_e resolution = ADC_RESOLUTION_12B,
|
|
adc_single_diff_e single_diff = ADC_SINGLE_ENDED) {
|
|
rcc_enable_adc_clock(ins); // enable adc clock
|
|
nvic_enable_adc_irq(); // enable adc irq
|
|
reg->cr.advregen = 1; // enable adc voltage regulator
|
|
delay_us(10, true); // todo: this delay may be removed, check with rm0456
|
|
{
|
|
wait_for_true(reg->cr.advregen, 1); // wait for adc voltage regulator to be ready
|
|
}
|
|
|
|
reg->cfgr1.res = resolution; // set resolution
|
|
reg->cfgr1.autdly = 0; // disable automatic delay (delay the start of conversion)
|
|
// calibration for single-end mode
|
|
// todo: add calibration for differential mode
|
|
// todo: check set sampling time with rm0456
|
|
reg->difsel.difsel = single_diff; // set single ended mode
|
|
reg->cr.adcal = 1; // start calibration
|
|
{
|
|
wait_for_true(reg->cr.adcal, 1); // wait for calibration to finish
|
|
}
|
|
reg->sqr1.l = 0; // set number of conversion
|
|
reg->sqr1.sq1 = channel; // set channel
|
|
reg->smpr1.smp1 = 0b111; // set sampling time to 640.5 adc clock cycles
|
|
reg->cfgr1.exten = 0b00; // set trigger to software
|
|
reg->cr.aden = 1; // enable adc
|
|
return HAL_OK;
|
|
}
|
|
|
|
void start_conversion(int number_conversion = 1, bool continuous_conversion = false) {
|
|
reg->cfgr1.cont = continuous_conversion;
|
|
reg->sqr1.l = number_conversion - 1; // set number of conversion
|
|
reg->cr.adstart = 1; // start conversion
|
|
}
|
|
|
|
void stop_conversion() {
|
|
reg->cr.adstp = 1; // stop conversion
|
|
}
|
|
|
|
void interrupt_handler() {
|
|
// read isr register
|
|
reg_adc_isr_t isr = const_cast<reg_adc_isr_t &>(reg->isr);
|
|
// todo: end of sequence may not need to be checked
|
|
if (isr.eoc || isr.eos) data_queue.push(reg->dr.rdata);
|
|
// clear interrupt flag
|
|
reg->isr.eoc = 0, reg->isr.eos = 0;
|
|
// TODO: continuous conversion mode
|
|
// single conversion mode and continuous conversion mode
|
|
}
|
|
|
|
|
|
hal_status_e read_last_conversion(uint32_t *data) { return data_queue.pop(data); }
|
|
};
|
|
|
|
#endif // STM32U5XX_HAL_ADC_HPP
|