Finished ADC methods
This commit is contained in:
@@ -22,6 +22,13 @@ void SHAL_init();
|
||||
|
||||
//Universal structs and defines ---------------------------
|
||||
|
||||
enum class SHAL_Result{
|
||||
OKAY,
|
||||
ERROR
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef bool (*condition_fn_t)(void);
|
||||
|
||||
#define SHAL_WAIT_FOR_CONDITION_US(cond, timeout_us) \
|
||||
@@ -31,7 +38,6 @@ typedef bool (*condition_fn_t)(void);
|
||||
SHAL_wait_for_condition_ms([&](){ return (cond); }, (timeout_ms))
|
||||
|
||||
|
||||
|
||||
//Currently configures systick to count down in microseconds
|
||||
void systick_init();
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
//
|
||||
// Created by Luca on 9/21/2025.
|
||||
//
|
||||
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
@@ -9,12 +9,22 @@
|
||||
#include "SHAL_ADC_TYPES.h"
|
||||
|
||||
|
||||
enum class ADC_Key{
|
||||
|
||||
enum class ADC_Key : uint8_t{
|
||||
S_ADC1,
|
||||
NUM_ADC,
|
||||
INVALID
|
||||
};
|
||||
|
||||
ADC_TypeDef* getADCRegister(ADC_Key key){
|
||||
switch(key){
|
||||
case ADC_Key::S_ADC1:
|
||||
return ADC1;
|
||||
|
||||
case ADC_Key::NUM_ADC:
|
||||
case ADC_Key::INVALID:
|
||||
return nullptr;
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_REG_F072XB_H
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
//
|
||||
// Created by Luca on 9/21/2025.
|
||||
//
|
||||
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
@@ -5,13 +5,41 @@
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "SHAL_CORE.h"
|
||||
#include "SHAL_ADC_REG.h"
|
||||
|
||||
class SHAL_ADC {
|
||||
|
||||
friend class ADCManager;
|
||||
|
||||
public:
|
||||
|
||||
SHAL_Result init();
|
||||
|
||||
SHAL_Result calibrate();
|
||||
|
||||
/// Performs analog to digital conversion on a single channel, one time
|
||||
/// \param channel Channel to be converted
|
||||
/// \param time ADC_SampleTime - amount of clock cycles per conversion
|
||||
/// \return resulting value
|
||||
uint16_t singleConvertSingle(ADC_Channel channel, ADC_SampleTime time = ADC_SampleTime::C239);
|
||||
|
||||
/// Performs analog to digital conversion on multiple channels, one time
|
||||
/// \param channels Pointer to an array of channels to convert
|
||||
/// \param numChannels Number of channels to convert
|
||||
/// \param result Pointer to store converted channel results in
|
||||
/// \param time ADC_SampleTime - amount of clock cycles per conversion
|
||||
void singleConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time = ADC_SampleTime::C239);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
SHAL_ADC() = default;
|
||||
|
||||
ADC_Key m_ADCKey = ADC_Key::INVALID;
|
||||
|
||||
};
|
||||
|
||||
@@ -23,9 +51,13 @@ class ADCManager{
|
||||
|
||||
public:
|
||||
|
||||
static SHAL_ADC& get(ADC_Key key);
|
||||
|
||||
ADCManager() = delete;
|
||||
|
||||
private:
|
||||
|
||||
inline static SHAL_ADC m_ADCs[static_cast<uint8_t>(ADC_Key::NUM_ADC)] = {};
|
||||
|
||||
};
|
||||
|
||||
|
||||
44
SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h
Normal file
44
SHAL/Include/Peripheral/ADC/SHAL_ADC_REG.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by Luca on 9/21/2025.
|
||||
//
|
||||
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
|
||||
#if defined(STM32F030x6)
|
||||
#include "stm32f030x6.h"
|
||||
#elif defined(STM32F030x8)
|
||||
#include "stm32f030x8.h"
|
||||
#elif defined(STM32F031x6)
|
||||
#include "stm32f031x6.h"
|
||||
#elif defined(STM32F038xx)
|
||||
#include "stm32f038xx.h"
|
||||
#elif defined(STM32F042x6)
|
||||
#include "stm32f042x6.h"
|
||||
#elif defined(STM32F048xx)
|
||||
#include "stm32f048xx.h"
|
||||
#elif defined(STM32F051x8)
|
||||
#include "stm32f051x8.h"
|
||||
#elif defined(STM32F058xx)
|
||||
#include "stm32f058xx.h"
|
||||
#elif defined(STM32F070x6)
|
||||
#include "stm32f070x6.h"
|
||||
#elif defined(STM32F070xB)
|
||||
#include "stm32f070xb.h"
|
||||
#elif defined(STM32F071xB)
|
||||
#include "stm32f071xb.h"
|
||||
#elif defined(STM32F072xB)
|
||||
#include "SHAL_ADC_REG_F072xB.h"
|
||||
#elif defined(STM32F078xx)
|
||||
#include "stm32f078xx.h"
|
||||
#elif defined(STM32F091xC)
|
||||
#include "stm32f091xc.h"
|
||||
#elif defined(STM32F098xx)
|
||||
#include "stm32f098xx.h"
|
||||
#elif defined(STM32F030xC)
|
||||
#include "stm32f030xc.h"
|
||||
#else
|
||||
#error "Please select first the target STM32F0xx device used in your application (in stm32f0xx.h file)"
|
||||
#endif
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_REG_H
|
||||
40
SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h
Normal file
40
SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by Luca on 9/21/2025.
|
||||
//
|
||||
|
||||
#ifndef SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
#define SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
|
||||
enum class ADC_Channel : uint32_t {
|
||||
CH1 = ADC_CHSELR_CHSEL1,
|
||||
CH2 = ADC_CHSELR_CHSEL2,
|
||||
CH3 = ADC_CHSELR_CHSEL3,
|
||||
CH4 = ADC_CHSELR_CHSEL4,
|
||||
CH5 = ADC_CHSELR_CHSEL5,
|
||||
CH6 = ADC_CHSELR_CHSEL6,
|
||||
CH7 = ADC_CHSELR_CHSEL7,
|
||||
CH8 = ADC_CHSELR_CHSEL8,
|
||||
CH9 = ADC_CHSELR_CHSEL9,
|
||||
CH10 = ADC_CHSELR_CHSEL10,
|
||||
CH11 = ADC_CHSELR_CHSEL11,
|
||||
CH12 = ADC_CHSELR_CHSEL12,
|
||||
CH13 = ADC_CHSELR_CHSEL13,
|
||||
CH14 = ADC_CHSELR_CHSEL14,
|
||||
CH15 = ADC_CHSELR_CHSEL15,
|
||||
CHTemp = ADC_CHSELR_CHSEL16,
|
||||
CHRef = ADC_CHSELR_CHSEL17,
|
||||
CHBat = ADC_CHSELR_CHSEL18
|
||||
};
|
||||
|
||||
enum class ADC_SampleTime : uint32_t {
|
||||
C2 = 0x00, //1.5 cycles per sample
|
||||
C7 = 0x01, //7.5 cycles
|
||||
C13 = 0x02, //13.5 cycles
|
||||
C28 = 0x03, //28.5 cycles
|
||||
C41 = 0x04, //41.5 cycles
|
||||
C55 = 0x05, //55.5 cycles
|
||||
C71 = 0x06, //71.5 cycles
|
||||
C239 = 0x07 //239.5 cycles
|
||||
};
|
||||
|
||||
#endif //SHMINGO_HAL_SHAL_ADC_TYPES_H
|
||||
@@ -1,3 +1,103 @@
|
||||
//
|
||||
// Created by Luca on 9/21/2025.
|
||||
//
|
||||
|
||||
#include "SHAL_ADC.h"
|
||||
|
||||
//Can hard code registers on F0 because all F0 devices have only one ADC, and use only one clock
|
||||
SHAL_Result SHAL_ADC::init() {
|
||||
|
||||
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock
|
||||
RCC->CR2 |= RCC_CR2_HSI14ON; //Start peripheral oscillator
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((RCC->CR2 & RCC_CR2_HSI14RDY) != 0),50)){ //Wait for clock OKAY
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
if((ADC_reg->ISR & ADC_ISR_ADRDY) != 0){ //Set ADRDY to 0
|
||||
ADC_reg->ISR |= ADC_ISR_ADRDY;
|
||||
}
|
||||
|
||||
ADC_reg->CR |= ADC_CR_ADEN; //Enable
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_ADRDY) != 0),50)){ //Wait for disable
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
if(calibrate() != SHAL_Result::OKAY){ //Calibrate
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
SHAL_Result SHAL_ADC::calibrate() {
|
||||
|
||||
if(m_ADCKey == ADC_Key::INVALID || m_ADCKey == ADC_Key::NUM_ADC){
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
if((ADC_reg->CR & ADC_CR_ADEN) != 0){ //Clear ADEN (enable)
|
||||
ADC_reg->CR |= ADC_CR_ADDIS;
|
||||
}
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->CR & ADC_CR_ADEN) == 0),50)){ //Wait for disable
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
ADC_reg->CFGR1 &= ~ADC_CFGR1_DMAEN; //Clear DMAEN
|
||||
ADC_reg->CR |= ADC_CR_ADCAL; //Launch calibration by setting ADCAL
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->CR & ADC_CR_ADCAL) == 0),50)){ //Wait for calibration
|
||||
return SHAL_Result::ERROR;
|
||||
}
|
||||
|
||||
return SHAL_Result::OKAY;
|
||||
}
|
||||
|
||||
uint16_t SHAL_ADC::singleConvertSingle(ADC_Channel channel, ADC_SampleTime time) {
|
||||
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_TSEN; //Enable VREFINT and Temp sensor in global ADC struct
|
||||
|
||||
ADC_reg->CHSELR = static_cast<uint32_t>(channel); //Enable channel for conversion
|
||||
ADC_reg->SMPR |= static_cast<uint32_t>(time); //Set sampling time
|
||||
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_EOC) != 0),500)){ //Wait for conversion
|
||||
return 0; //Failed
|
||||
}
|
||||
|
||||
uint16_t result = ADC_reg->DR;
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHAL_ADC::singleConvertSingle(ADC_Channel* channels, const int numChannels, uint16_t* result, ADC_SampleTime time) {
|
||||
ADC_TypeDef* ADC_reg = getADCRegister(m_ADCKey);
|
||||
|
||||
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_TSEN; //Enable VREFINT and Temp sensor in global ADC struct
|
||||
|
||||
for(int i = 0; i < numChannels; i++){ //Enable all channels
|
||||
ADC_reg->CHSELR = static_cast<uint32_t>(channels[i]);
|
||||
}
|
||||
|
||||
ADC_reg->SMPR |= static_cast<uint32_t>(time); //Set sampling time
|
||||
|
||||
|
||||
for(int i = 0; i < numChannels; i++){
|
||||
if(!SHAL_WAIT_FOR_CONDITION_US(((ADC_reg->ISR & ADC_ISR_EOC) != 0),500)){ //Wait for conversion
|
||||
continue; //Failed
|
||||
}
|
||||
|
||||
result[i] = ADC_reg->DR;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user