stmhal: Add ADC function to read data at a given frequency.
Reads ADC values into a bytearray (or similar) at a fixed rate. Needs a better name and improved API. Also fix up DAC dma function (which also needs a better name and API).
This commit is contained in:
parent
e95da5b784
commit
4d7f4eb6a9
32
stmhal/adc.c
32
stmhal/adc.c
@ -11,6 +11,7 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
#include "build/pins.h"
|
#include "build/pins.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
// Usage Model:
|
// Usage Model:
|
||||||
//
|
//
|
||||||
@ -162,8 +163,39 @@ STATIC mp_obj_t adc_read(mp_obj_t self_in) {
|
|||||||
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
|
||||||
|
|
||||||
|
STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) {
|
||||||
|
pyb_obj_adc_t *self = self_in;
|
||||||
|
|
||||||
|
buffer_info_t bufinfo;
|
||||||
|
mp_get_buffer_raise(buf_in, &bufinfo);
|
||||||
|
|
||||||
|
// Init TIM6 at the required frequency (in Hz)
|
||||||
|
timer_tim6_init(mp_obj_get_int(freq_in));
|
||||||
|
|
||||||
|
// Start timer
|
||||||
|
HAL_TIM_Base_Start(&TIM6_Handle);
|
||||||
|
|
||||||
|
// This uses the timer in polling mode to do the sampling
|
||||||
|
// TODO use DMA
|
||||||
|
for (uint i = 0; i < bufinfo.len; i++) {
|
||||||
|
// Wait for the timer to trigger
|
||||||
|
while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) {
|
||||||
|
}
|
||||||
|
__HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE);
|
||||||
|
((byte*)bufinfo.buf)[i] = adc_read_channel(&self->handle) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop timer
|
||||||
|
HAL_TIM_Base_Stop(&TIM6_Handle);
|
||||||
|
|
||||||
|
return mp_obj_new_int(bufinfo.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_obj, adc_read_timed);
|
||||||
|
|
||||||
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
|
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj},
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj},
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_read_timed), (mp_obj_t)&adc_read_timed_obj},
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
|
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
|
||||||
|
42
stmhal/dac.c
42
stmhal/dac.c
@ -10,9 +10,9 @@
|
|||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "obj.h"
|
#include "obj.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "dac.h"
|
#include "dac.h"
|
||||||
|
|
||||||
TIM_HandleTypeDef TIM6_Handle;
|
|
||||||
STATIC DAC_HandleTypeDef DAC_Handle;
|
STATIC DAC_HandleTypeDef DAC_Handle;
|
||||||
|
|
||||||
void dac_init(void) {
|
void dac_init(void) {
|
||||||
@ -22,19 +22,8 @@ void dac_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void TIM6_Config(uint freq) {
|
STATIC void TIM6_Config(uint freq) {
|
||||||
// TIM6 clock enable
|
// Init TIM6 at the required frequency (in Hz)
|
||||||
__TIM6_CLK_ENABLE();
|
timer_tim6_init(freq);
|
||||||
|
|
||||||
// Compute the prescaler value so TIM6 triggers at freq-Hz
|
|
||||||
uint16_t period = (uint16_t) ((SystemCoreClock / 2) / freq) - 1;
|
|
||||||
|
|
||||||
// time base clock configuration
|
|
||||||
TIM6_Handle.Instance = TIM6;
|
|
||||||
TIM6_Handle.Init.Period = period;
|
|
||||||
TIM6_Handle.Init.Prescaler = 0; // timer runs at SystemCoreClock / 2
|
|
||||||
TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6
|
|
||||||
TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6
|
|
||||||
HAL_TIM_Base_Init(&TIM6_Handle);
|
|
||||||
|
|
||||||
// TIM6 TRGO selection
|
// TIM6 TRGO selection
|
||||||
TIM_MasterConfigTypeDef config;
|
TIM_MasterConfigTypeDef config;
|
||||||
@ -203,17 +192,14 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|||||||
DAC_Init(self->dac_channel, &DAC_InitStructure);
|
DAC_Init(self->dac_channel, &DAC_InitStructure);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (self->state != 3) {
|
|
||||||
DAC_ChannelConfTypeDef config;
|
|
||||||
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
|
|
||||||
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
|
|
||||||
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
|
|
||||||
self->state = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DMA1_Stream[67] channel7 configuration
|
// DMA1_Stream[67] channel7 configuration
|
||||||
DMA_HandleTypeDef DMA_Handle;
|
DMA_HandleTypeDef DMA_Handle;
|
||||||
DMA_Handle.Instance = self->dma_stream;
|
DMA_Handle.Instance = self->dma_stream;
|
||||||
|
|
||||||
|
// Need to deinit DMA first
|
||||||
|
DMA_Handle.State = HAL_DMA_STATE_READY;
|
||||||
|
HAL_DMA_DeInit(&DMA_Handle);
|
||||||
|
|
||||||
DMA_Handle.Init.Channel = DMA_CHANNEL_7;
|
DMA_Handle.Init.Channel = DMA_CHANNEL_7;
|
||||||
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||||
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
|
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||||
@ -231,6 +217,18 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
|||||||
|
|
||||||
__HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
|
__HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
|
||||||
|
|
||||||
|
DAC_Handle.Instance = DAC;
|
||||||
|
DAC_Handle.State = HAL_DAC_STATE_RESET;
|
||||||
|
HAL_DAC_Init(&DAC_Handle);
|
||||||
|
|
||||||
|
if (self->state != 3) {
|
||||||
|
DAC_ChannelConfTypeDef config;
|
||||||
|
config.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
|
||||||
|
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
|
||||||
|
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
|
||||||
|
self->state = 3;
|
||||||
|
}
|
||||||
|
|
||||||
HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R);
|
HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -97,6 +97,7 @@ Q(filtered_xyz)
|
|||||||
// for ADC object
|
// for ADC object
|
||||||
Q(ADC)
|
Q(ADC)
|
||||||
Q(ADC_all)
|
Q(ADC_all)
|
||||||
|
Q(read_timed)
|
||||||
Q(read_channel)
|
Q(read_channel)
|
||||||
Q(read_core_temp)
|
Q(read_core_temp)
|
||||||
Q(read_core_vbat)
|
Q(read_core_vbat)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
TIM_HandleTypeDef TIM3_Handle;
|
TIM_HandleTypeDef TIM3_Handle;
|
||||||
TIM_HandleTypeDef TIM5_Handle;
|
TIM_HandleTypeDef TIM5_Handle;
|
||||||
|
TIM_HandleTypeDef TIM6_Handle;
|
||||||
|
|
||||||
// TIM3 is set-up for the USB CDC interface
|
// TIM3 is set-up for the USB CDC interface
|
||||||
void timer_tim3_init(void) {
|
void timer_tim3_init(void) {
|
||||||
@ -57,6 +58,7 @@ void timer_tim3_deinit(void) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TIM5 is set-up for the servo controller
|
// TIM5 is set-up for the servo controller
|
||||||
|
// This function inits but does not start the timer
|
||||||
void timer_tim5_init(void) {
|
void timer_tim5_init(void) {
|
||||||
// TIM5 clock enable
|
// TIM5 clock enable
|
||||||
__TIM5_CLK_ENABLE();
|
__TIM5_CLK_ENABLE();
|
||||||
@ -74,6 +76,31 @@ void timer_tim5_init(void) {
|
|||||||
HAL_TIM_PWM_Init(&TIM5_Handle);
|
HAL_TIM_PWM_Init(&TIM5_Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init TIM6 with a counter-overflow at the given frequency (given in Hz)
|
||||||
|
// TIM6 is used by the DAC and ADC for auto sampling at a given frequency
|
||||||
|
// This function inits but does not start the timer
|
||||||
|
void timer_tim6_init(uint freq) {
|
||||||
|
// TIM6 clock enable
|
||||||
|
__TIM6_CLK_ENABLE();
|
||||||
|
|
||||||
|
// Timer runs at SystemCoreClock / 2
|
||||||
|
// Compute the prescaler value so TIM6 triggers at freq-Hz
|
||||||
|
uint32_t period = (SystemCoreClock / 2) / freq;
|
||||||
|
uint32_t prescaler = 1;
|
||||||
|
while (period > 0xffff) {
|
||||||
|
period >>= 1;
|
||||||
|
prescaler <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time base clock configuration
|
||||||
|
TIM6_Handle.Instance = TIM6;
|
||||||
|
TIM6_Handle.Init.Period = period - 1;
|
||||||
|
TIM6_Handle.Init.Prescaler = prescaler - 1;
|
||||||
|
TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6
|
||||||
|
TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6
|
||||||
|
HAL_TIM_Base_Init(&TIM6_Handle);
|
||||||
|
}
|
||||||
|
|
||||||
// Interrupt dispatch
|
// Interrupt dispatch
|
||||||
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
|
||||||
if (htim == &TIM3_Handle) {
|
if (htim == &TIM3_Handle) {
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
extern TIM_HandleTypeDef TIM3_Handle;
|
extern TIM_HandleTypeDef TIM3_Handle;
|
||||||
extern TIM_HandleTypeDef TIM5_Handle;
|
extern TIM_HandleTypeDef TIM5_Handle;
|
||||||
|
extern TIM_HandleTypeDef TIM6_Handle;
|
||||||
|
|
||||||
void timer_tim3_init(void);
|
void timer_tim3_init(void);
|
||||||
void timer_tim5_init(void);
|
void timer_tim5_init(void);
|
||||||
|
void timer_tim6_init(uint freq);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user