add adc process
This commit is contained in:
parent
fc31db365d
commit
a4c3361300
4 changed files with 58 additions and 24 deletions
|
@ -17,7 +17,7 @@ DEL = rm -f
|
||||||
|
|
||||||
# zdrojaky
|
# zdrojaky
|
||||||
OBJS = main.o adcclass.o
|
OBJS = main.o adcclass.o
|
||||||
#OBJS += usartclass.o print.o
|
OBJS += usartclass.o print.o
|
||||||
|
|
||||||
include $(TARGET)/$(TOOL).mk
|
include $(TARGET)/$(TOOL).mk
|
||||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "oneway.h"
|
#include "oneway.h"
|
||||||
#include "adcclass.h"
|
#include "adcclass.h"
|
||||||
#include "gpio.h"
|
|
||||||
|
|
||||||
static GpioClass led (GPIOD, 4);
|
|
||||||
|
|
||||||
static AdcClass * pInstance = nullptr;
|
static AdcClass * pInstance = nullptr;
|
||||||
|
|
||||||
volatile unsigned gCount = 0u;
|
|
||||||
|
|
||||||
extern "C" void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt));
|
extern "C" void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt));
|
||||||
void DMA1_Channel1_IRQHandler( void ) {
|
void DMA1_Channel1_IRQHandler( void ) {
|
||||||
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
|
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
|
||||||
DMA1.INTFCR.R = state.R; // clear all
|
DMA1.INTFCR.R = state.R; // clear all
|
||||||
if (!pInstance) return;
|
if (!pInstance) return;
|
||||||
gCount += 1u;
|
|
||||||
const bool b = (gCount & 1u) == 0u;
|
|
||||||
led << b;
|
|
||||||
if (state.B.HTIF1 != RESET) pInstance->send (false);
|
if (state.B.HTIF1 != RESET) pInstance->send (false);
|
||||||
else if (state.B.TCIF1 != RESET) pInstance->send (true);
|
else if (state.B.TCIF1 != RESET) pInstance->send (true);
|
||||||
}
|
}
|
||||||
|
@ -47,12 +39,16 @@ static inline void Timer2Init (uint32_t us) noexcept {
|
||||||
TIM2.PSC.R = 47u; // 1 MHz Fs
|
TIM2.PSC.R = 47u; // 1 MHz Fs
|
||||||
TIM2.ATRLR.R = us - 1u;
|
TIM2.ATRLR.R = us - 1u;
|
||||||
// TRGO update for ADC
|
// TRGO update for ADC
|
||||||
TIM2.CTLR2.B.MMS = 2;
|
TIM2.CTLR2.B.MMS = 2u;
|
||||||
}
|
}
|
||||||
static inline void AdcCalibrate (void) noexcept {
|
static inline void AdcCalibrate (void) noexcept {
|
||||||
ADC1.RSQR3.B.SQ1 = 1u; // CH1
|
// RESET
|
||||||
|
RCC.APB2PRSTR.B.ADC1RST = SET;
|
||||||
|
RCC.APB2PRSTR.B.ADC1RST = RESET;
|
||||||
|
// set channels
|
||||||
|
ADC1.RSQR3.B.SQ1 = 2u; // CH2
|
||||||
ADC1.RSQR1.B.L = 0u; // 1 regular conversion
|
ADC1.RSQR1.B.L = 0u; // 1 regular conversion
|
||||||
ADC1.SAMPTR2_CHARGE2.B.SMP1_TKCG1 = 7u;
|
ADC1.SAMPTR2_CHARGE2.B.SMP2_TKCG2 = 7u;
|
||||||
ADC1.CTLR1.B.SCAN = SET;
|
ADC1.CTLR1.B.SCAN = SET;
|
||||||
|
|
||||||
ADC1.CTLR2.B.ADON = SET;
|
ADC1.CTLR2.B.ADON = SET;
|
||||||
|
@ -60,7 +56,6 @@ static inline void AdcCalibrate (void) noexcept {
|
||||||
while (ADC1.CTLR2.B.RSTCAL != RESET); // Wait until RSTCAL=0
|
while (ADC1.CTLR2.B.RSTCAL != RESET); // Wait until RSTCAL=0
|
||||||
ADC1.CTLR2.B.CAL = SET; // Launch the calibration by setting CAL
|
ADC1.CTLR2.B.CAL = SET; // Launch the calibration by setting CAL
|
||||||
while (ADC1.CTLR2.B.CAL != RESET); // Wait until CAL=0
|
while (ADC1.CTLR2.B.CAL != RESET); // Wait until CAL=0
|
||||||
ADC1.CTLR2.B.ADON = RESET;
|
|
||||||
}
|
}
|
||||||
typedef __SIZE_TYPE__ size_t;
|
typedef __SIZE_TYPE__ size_t;
|
||||||
static inline void Dma1Ch1Init (void * ptr) noexcept {
|
static inline void Dma1Ch1Init (void * ptr) noexcept {
|
||||||
|
@ -72,12 +67,14 @@ static inline void Dma1Ch1Init (void * ptr) noexcept {
|
||||||
DMA1.CNTR1 .R = FULL_LEN;
|
DMA1.CNTR1 .R = FULL_LEN;
|
||||||
// Configure increment, size, interrupts and circular mode
|
// Configure increment, size, interrupts and circular mode
|
||||||
DMA1.CFGR1.modify([] (DMA1_Type::CFGR1_DEF & r) -> auto {
|
DMA1.CFGR1.modify([] (DMA1_Type::CFGR1_DEF & r) -> auto {
|
||||||
r.B.MINC = SET;
|
r.B.PL = 3u; // highest priority
|
||||||
r.B.MSIZE = 1u;
|
r.B.MEM2MEM = RESET; // periferal -> memory
|
||||||
r.B.PSIZE = 1u;
|
r.B.MINC = SET; // memory increment
|
||||||
r.B.HTIE = SET;
|
r.B.MSIZE = 1u; // 16-bit
|
||||||
r.B.TCIE = SET;
|
r.B.PSIZE = 1u; // 16-bit
|
||||||
r.B.CIRC = SET;
|
r.B.HTIE = SET; // INT Enable HALF
|
||||||
|
r.B.TCIE = SET; // INT Enable FULL
|
||||||
|
r.B.CIRC = SET; // Circular MODE
|
||||||
// Enable DMA Channel 1
|
// Enable DMA Channel 1
|
||||||
r.B.EN = SET;
|
r.B.EN = SET;
|
||||||
return r.R;
|
return r.R;
|
||||||
|
@ -89,11 +86,10 @@ static inline void AdcPostInit (void) noexcept {
|
||||||
r.B.EXTTRIG = SET;
|
r.B.EXTTRIG = SET;
|
||||||
r.B.EXTSEL = 3u; // TRGO event of timer 2
|
r.B.EXTSEL = 3u; // TRGO event of timer 2
|
||||||
r.B.SWSTART = SET;
|
r.B.SWSTART = SET;
|
||||||
r.B.ADON = SET;
|
|
||||||
return r.R;
|
return r.R;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
AdcClass::AdcClass() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) {
|
AdcClass::AdcClass() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) {
|
||||||
pInstance = this;
|
pInstance = this;
|
||||||
EnableClock ();
|
EnableClock ();
|
||||||
|
|
38
adc/main.cpp
38
adc/main.cpp
|
@ -2,11 +2,49 @@
|
||||||
#include "usartclass.h"
|
#include "usartclass.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "adcclass.h"
|
#include "adcclass.h"
|
||||||
|
#include "oneway.h"
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
class Process : public OneWay {
|
||||||
|
GpioClass led;
|
||||||
|
UsartClass serial;
|
||||||
|
Print cout;
|
||||||
|
FIFO<uint16_t, 8> data;
|
||||||
|
int pass_cnt;
|
||||||
|
public:
|
||||||
|
explicit Process () noexcept : OneWay (),
|
||||||
|
led (GPIOD, 4), serial (115200u), cout (DEC), data(), pass_cnt (0) {
|
||||||
|
cout += serial;
|
||||||
|
}
|
||||||
|
unsigned Send (uint16_t * const ptr, const unsigned len) override {
|
||||||
|
unsigned sum = 0u;
|
||||||
|
for (unsigned n=0; n<len; n++) sum += ptr [n];
|
||||||
|
sum >>= 4;
|
||||||
|
data.Write (static_cast<uint16_t> (sum));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
void pass () {
|
||||||
|
uint16_t avg;
|
||||||
|
if (!data.Read (avg)) return;
|
||||||
|
cout << "pass: " << pass_cnt << ", avg = " << static_cast<int>(avg) << EOL;
|
||||||
|
pass_cnt += 1;
|
||||||
|
const bool b = pass_cnt & 1;
|
||||||
|
led << b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//////////////////////////////////////
|
||||||
|
/* Tohle DEMO je složitější. ADC má
|
||||||
|
* pevnou frekvenci vzorkování 1kHz,
|
||||||
|
* vzorky se průměrují v přerušení a
|
||||||
|
* vypisují (v jiném přerušení) na
|
||||||
|
* sériový port.
|
||||||
|
* */
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
static AdcClass adc;
|
static AdcClass adc;
|
||||||
|
static Process out;
|
||||||
int main () {
|
int main () {
|
||||||
|
adc.attach(out);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
out.pass();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct NVIC_Type {
|
||||||
IRER [((uint32_t)(IRQ) >> 5)] = (1 << ((uint32_t)(IRQ) & 0x1F));
|
IRER [((uint32_t)(IRQ) >> 5)] = (1 << ((uint32_t)(IRQ) & 0x1F));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
NVIC_Type & NVIC = * reinterpret_cast<NVIC_Type * const> (0xE000E000);
|
static NVIC_Type & NVIC = * reinterpret_cast<NVIC_Type * const> (0xE000E000);
|
||||||
struct SysTick_Type {
|
struct SysTick_Type {
|
||||||
union CTLR_DEF {
|
union CTLR_DEF {
|
||||||
struct {
|
struct {
|
||||||
|
@ -68,6 +68,6 @@ struct SysTick_Type {
|
||||||
NVIC.EnableIRQ (SysTicK_IRQn);
|
NVIC.EnableIRQ (SysTicK_IRQn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SysTick_Type & SysTick = * reinterpret_cast<SysTick_Type * const> (0xE000F000);
|
static SysTick_Type & SysTick = * reinterpret_cast<SysTick_Type * const> (0xE000F000);
|
||||||
|
|
||||||
#endif // SYSTEM_H
|
#endif // SYSTEM_H
|
||||||
|
|
Loading…
Reference in a new issue