[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[paparazzi-commits] [5683] Added STM32 ADC driver ( 4-channel injection
From: |
Tobias Fuchs |
Subject: |
[paparazzi-commits] [5683] Added STM32 ADC driver ( 4-channel injection triggered by timer 2 or 4). |
Date: |
Wed, 25 Aug 2010 23:32:27 +0000 |
Revision: 5683
http://svn.sv.gnu.org/viewvc/?view=rev&root=paparazzi&revision=5683
Author: fuchsto
Date: 2010-08-25 23:32:26 +0000 (Wed, 25 Aug 2010)
Log Message:
-----------
Added STM32 ADC driver (4-channel injection triggered by timer 2 or 4).
Modified Paths:
--------------
paparazzi3/trunk/conf/autopilot/lisa_test_progs.makefile
paparazzi3/trunk/sw/airborne/adc.h
paparazzi3/trunk/sw/airborne/lisa/test_csc_servo.c
paparazzi3/trunk/sw/airborne/stm32/adc_hw.c
Added Paths:
-----------
paparazzi3/trunk/sw/airborne/lisa/test_adc.c
Modified: paparazzi3/trunk/conf/autopilot/lisa_test_progs.makefile
===================================================================
--- paparazzi3/trunk/conf/autopilot/lisa_test_progs.makefile 2010-08-25
23:25:33 UTC (rev 5682)
+++ paparazzi3/trunk/conf/autopilot/lisa_test_progs.makefile 2010-08-25
23:32:26 UTC (rev 5683)
@@ -1276,37 +1276,58 @@
#
# test ADC
#
+# test_adc.ARCHDIR = $(ARCHI)
+# test_adc.TARGET = test_adc
+# test_adc.TARGETDIR = test_adc
+# test_adc.CFLAGS = -I$(ARCHI) -DPERIPHERALS_AUTO_INIT
+# test_adc.CFLAGS += -DBOARD_CONFIG=$(BOARD_CFG) -I$(SRC_BOOZ)
-I$(SRC_BOOZ_ARCH)
+# test_adc.srcs += $(SRC_LISA)/test/lisa_test_adc.c \
+# $(SRC_ARCH)/stm32_exceptions.c \
+# $(SRC_ARCH)/stm32_vector_table.c
+# test_adc.CFLAGS += -DUSE_LED
+# test_adc.srcs += $(SRC_ARCH)/led_hw.c
+# test_adc.CFLAGS += -DUSE_SYS_TIME -DSYS_TIME_LED=1
+# test_adc.CFLAGS += -DPERIODIC_TASK_PERIOD='SYS_TICS_OF_SEC((1./512.))'
-DTIME_LED=1
+# test_adc.srcs += sys_time.c $(SRC_ARCH)/sys_time_hw.c
+#
+# test_adc.CFLAGS += -DUSE_UART2 -DUART2_BAUD=B57600
+# test_adc.srcs += $(SRC_ARCH)/uart_hw.c
+#
+# test_adc.CFLAGS += -DDOWNLINK -DDOWNLINK_TRANSPORT=PprzTransport
-DDOWNLINK_DEVICE=Uart2
+# test_adc.srcs += downlink.c pprz_transport.c
+#
+# test_adc.srcs += $(SRC_ARCH)/adc_hw.c
+
+#
+# test adc
+#
test_adc.ARCHDIR = $(ARCHI)
test_adc.TARGET = test_adc
test_adc.TARGETDIR = test_adc
-test_adc.CFLAGS = -I$(ARCHI) -DPERIPHERALS_AUTO_INIT
-test_adc.CFLAGS += -DBOARD_CONFIG=$(BOARD_CFG) -I$(SRC_BOOZ) -I$(SRC_BOOZ_ARCH)
-test_adc.srcs += $(SRC_LISA)/test/lisa_test_adc.c \
- $(SRC_ARCH)/stm32_exceptions.c \
- $(SRC_ARCH)/stm32_vector_table.c
+test_adc.CFLAGS = -I$(SRC_LISA) -I$(ARCHI) -DPERIPHERALS_AUTO_INIT
+test_adc.CFLAGS += -DBOARD_CONFIG=$(BOARD_CFG)
+test_adc.srcs = $(SRC_ARCH)/adc_hw.c \
+ $(SRC_LISA)/test_adc.c \
+ $(SRC_ARCH)/stm32_exceptions.c \
+ $(SRC_ARCH)/stm32_vector_table.c
test_adc.CFLAGS += -DUSE_LED
test_adc.srcs += $(SRC_ARCH)/led_hw.c
test_adc.CFLAGS += -DUSE_SYS_TIME -DSYS_TIME_LED=1
-test_adc.CFLAGS += -DPERIODIC_TASK_PERIOD='SYS_TICS_OF_SEC((1./512.))'
-DTIME_LED=1
+test_adc.CFLAGS += -DPERIODIC_TASK_PERIOD='SYS_TICS_OF_SEC(1./512.)'
test_adc.srcs += sys_time.c $(SRC_ARCH)/sys_time_hw.c
test_adc.CFLAGS += -DUSE_UART2 -DUART2_BAUD=B57600
test_adc.srcs += $(SRC_ARCH)/uart_hw.c
+test_adc.CFLAGS += -DDATALINK=PPRZ -DPPRZ_UART=Uart2
test_adc.CFLAGS += -DDOWNLINK -DDOWNLINK_TRANSPORT=PprzTransport
-DDOWNLINK_DEVICE=Uart2
test_adc.srcs += downlink.c pprz_transport.c
-test_adc.srcs += $(SRC_ARCH)/adc_hw.c
+test_adc.CFLAGS += \
+ -DUSE_AD1 \
+ -DUSE_AD1_1
-
-
-
-
-
-
-
-
################################################################################
#
#
Modified: paparazzi3/trunk/sw/airborne/adc.h
===================================================================
--- paparazzi3/trunk/sw/airborne/adc.h 2010-08-25 23:25:33 UTC (rev 5682)
+++ paparazzi3/trunk/sw/airborne/adc.h 2010-08-25 23:32:26 UTC (rev 5683)
@@ -42,17 +42,32 @@
#define DEFAULT_AV_NB_SAMPLE 0x20
/**
+ Generic interface for all ADC hardware drivers, independent from
+ microcontroller architecture.
*/
-/** Data structure used to store samples */
+/**
+ Struct to collect samples from ADC and building an average
+ over MAX_AV_NB_SAMPLE values.
+ See @ref adc_buf_channel.
+*/
struct adc_buf {
- uint16_t sum;
- uint16_t values[MAX_AV_NB_SAMPLE];
- uint8_t head;
- uint8_t av_nb_sample;
+ uint16_t sum;
/* Sum of samples in buffer (avg = sum / av_nb_sample)
*/
+ uint16_t values[MAX_AV_NB_SAMPLE]; /* Buffer for sample values from ADC */
+ uint8_t head;
/* Position index of write head in buffer */
+ uint8_t av_nb_sample; /*
Number of samples to use in buffer (used for avg) */
};
-/** Registers a buffer to be used to store the specified converted channel */
+/**
+ Registers a buffer to be used to store the specified converted channel
+ Usage:
address@hidden
+ struct adc_buf channel_buf;
+ adc_buf_channel(1, &channel_buf, 12);
address@hidden
+ Registers channel_buf as buffer for ADC channel 1, with max index 12
+ (12 samples).
+*/
void adc_buf_channel(uint8_t adc_channel, struct adc_buf* s, uint8_t
av_nb_sample);
/** Starts conversions */
Added: paparazzi3/trunk/sw/airborne/lisa/test_adc.c
===================================================================
--- paparazzi3/trunk/sw/airborne/lisa/test_adc.c
(rev 0)
+++ paparazzi3/trunk/sw/airborne/lisa/test_adc.c 2010-08-25 23:32:26 UTC
(rev 5683)
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2009 Antoine Drouin <address@hidden>
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stm32/flash.h>
+#include <stm32/misc.h>
+
+#include BOARD_CONFIG
+#include "init_hw.h"
+#include "sys_time.h"
+#include "led.h"
+#include "adc.h"
+#include "adc_hw.h"
+#include "downlink.h"
+
+int main_periodic(void);
+static inline void main_init( void );
+static inline void main_periodic_task( void );
+static inline void main_event_task( void );
+
+static struct adc_buf adc0_buf;
+static struct adc_buf adc1_buf;
+static struct adc_buf adc2_buf;
+static struct adc_buf adc3_buf;
+
+extern uint8_t adc_new_data_trigger;
+
+static inline void main_init( void ) {
+ hw_init();
+ sys_time_init();
+ led_init();
+ adc_init();
+
+ adc_buf_channel(0, &adc0_buf, 3);
+ adc_buf_channel(1, &adc1_buf, 3);
+ adc_buf_channel(2, &adc2_buf, 3);
+ adc_buf_channel(3, &adc3_buf, 3);
+}
+
+int main( void ) {
+ main_init();
+
+ while(1) {
+ if (sys_time_periodic()) {
+ main_periodic_task();
+ DOWNLINK_SEND_ALIVE(DefaultChannel, 16, MD5SUM);
+ }
+
+ main_event_task();
+ }
+ return 0;
+}
+
+static inline void main_periodic_task( void ) {
+ LED_PERIODIC();
+}
+
+static inline void main_event_task( void ) {
+ uint8_t down = 123;
+
+ if (adc_new_data_trigger) {
+ DOWNLINK_SEND_PONG(DefaultChannel);
+ adc_new_data_trigger = 0;
+ LED_TOGGLE(7);
+// down = (((adc0_buf.values[0]) >> 4) & 0x00ff);
+ DOWNLINK_SEND_BOOZ_DEBUG_FOO(DefaultChannel, &down);
+ }
+}
+
Modified: paparazzi3/trunk/sw/airborne/lisa/test_csc_servo.c
===================================================================
--- paparazzi3/trunk/sw/airborne/lisa/test_csc_servo.c 2010-08-25 23:25:33 UTC
(rev 5682)
+++ paparazzi3/trunk/sw/airborne/lisa/test_csc_servo.c 2010-08-25 23:32:26 UTC
(rev 5683)
@@ -92,6 +92,7 @@
cscp_transmit(0, 0, (uint8_t *)servos, 8);
LED_PERIODIC();
+ DOWNLINK_SEND_ALIVE(DefaultChannel, 16, MD5SUM);
}
Modified: paparazzi3/trunk/sw/airborne/stm32/adc_hw.c
===================================================================
--- paparazzi3/trunk/sw/airborne/stm32/adc_hw.c 2010-08-25 23:25:33 UTC (rev
5682)
+++ paparazzi3/trunk/sw/airborne/stm32/adc_hw.c 2010-08-25 23:32:26 UTC (rev
5683)
@@ -1,79 +1,444 @@
+/*
+ * $Id: adc_hw.c 5313 2010-08-11 18:46:20Z flixr $
+ *
+ * Copyright (C) 2008 Pascal Brisset, Antoine Drouin
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/**
+ * Usage:
+ * Define flags for ADCs to use and their channels:
+ *
+ * -DUSE_AD1 -DUSE_AD1_1 -DUSE_AD1_3
+ *
+ * would enable ADC1 and it's channels 1 and 3.
+ *
+ *
+ *
+ *
+ *
+ */
+
#include "adc.h"
-
#include <stm32/rcc.h>
+#include <stm32/misc.h>
+#include <stm32/adc.h>
#include <stm32/gpio.h>
-#include <stm32/dma.h>
-#include <stm32/adc.h>
+#include <stm32/rcc.h>
+#include <stm32/tim.h>
+#include "led.h"
+#include BOARD_CONFIG
+void adc1_2_irq_handler(void);
-void adc_init( void ) {
+uint8_t adc_new_data_trigger;
- /* Configure pins as analog input*/
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
+/* Static functions */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
+static inline void adc_init_single(ADC_TypeDef * adc_t,
+ uint8_t chan1, uint8_t chan2,
+ uint8_t chan3, uint8_t chan4);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
+static inline void adc_push_sample(struct adc_buf * buf,
+ uint16_t sample);
+static inline void adc_init_rcc( void );
+static inline void adc_init_irq( void );
- /* ADC1 configuration
------------------------------------------------------*/
- ADC_InitTypeDef ADC_InitStructure;
- ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- ADC_InitStructure.ADC_NbrOfChannel = 1;
- ADC_Init(ADC1, &ADC_InitStructure);
+#ifdef USE_AD2
+#error NOT_IMPLEMENTED__currently_only_ADC1_is_supported
+#endif
+/*
+ Only 4 ADC channels may be enabled at the same time
+ on each ADC, as there are only 4 injection registers.
+*/
- /* Enable DMA1 clock */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
-
- /* DMA1 channel1 configuration
----------------------------------------------*/
- DMA_InitTypeDef DMA_InitStructure;
- DMA_DeInit(DMA1_Channel1);
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&coder_values;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_InitStructure.DMA_BufferSize = 1;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
-
- /* Enable DMA1 channel1 */
- DMA_Cmd(DMA1_Channel1, ENABLE);
-
- /* Enable ADC1 DMA */
- ADC_DMACmd(ADC1, ENABLE);
+// ADCx_GPIO_INIT
+// {{{
- /* Enable ADC1 */
- ADC_Cmd(ADC1, ENABLE);
-
- /* Enable ADC1 reset calibaration register */
- ADC_ResetCalibration(ADC1);
- /* Check the end of ADC1 reset calibration register */
- while(ADC_GetResetCalibrationStatus(ADC1));
-
- /* Start ADC1 calibaration */
- ADC_StartCalibration(ADC1);
- /* Check the end of ADC1 calibration */
- while(ADC_GetCalibrationStatus(ADC1));
-
- /* Start ADC1 Software Conversion */
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
+/*
+ GPIO mapping for ADC1 pins (PA.B, PB.1, PC.3, PC.5).
+ Can be changed by predefining ADC1_GPIO_INIT.
+*/
+#ifdef USE_AD1
+#ifndef ADC1_GPIO_INIT
+#define ADC1_GPIO_INIT(gpio) { \
+ (gpio).GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; \
+ (gpio).GPIO_Mode = GPIO_Mode_AIN; \
+ GPIO_Init(GPIOB, (&gpio)); \
+ (gpio).GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5; \
+ GPIO_Init(GPIOC, (&gpio)); \
+}
+#endif // ADC1_GPIO_INIT
+#endif // USE_AD1
+/*
+ GPIO mapping for ADC2 pins.
+ Can be changed by predefining ADC2_GPIO_INIT.
+*/
+#ifdef USE_AD2
+#ifndef ADC2_GPIO_INIT
+#define ADC2_GPIO_INIT(gpio) { }
+#endif // ADC2_GPIO_INIT
+#endif // USE_AD2
+
+// }}}
+
+/*
+ Currently, the enums adc1_channels and adc2_channels only
+ serve to resolve the number of channels on each ADC.
+*/
+
+// NB_ADCx_CHANNELS
+// {{{
+enum adc1_channels {
+#ifdef USE_AD1_1
+ ADC1_C1,
+#endif
+#ifdef USE_AD1_2
+ ADC1_C2,
+#endif
+#ifdef USE_AD1_3
+ ADC1_C3,
+#endif
+#ifdef USE_AD1_4
+ ADC1_C4,
+#endif
+ NB_ADC1_CHANNELS
+};
+
+enum adc2_channels {
+#ifdef USE_AD2_1
+ ADC2_C1,
+#endif
+#ifdef USE_AD2_2
+ ADC2_C2,
+#endif
+#ifdef USE_AD2_3
+ ADC2_C3,
+#endif
+#ifdef USE_AD2_4
+ ADC2_C4,
+#endif
+ NB_ADC2_CHANNELS
+};
+
+// }}}
+
+/*
+ Separate buffers for each ADC.
+ Every ADC has a list of buffers, one for each active
+ channel.
+*/
+
+#ifdef USE_AD1
+static struct adc_buf * adc1_buffers[NB_ADC1_CHANNELS];
+#endif
+#ifdef USE_AD2
+static struct adc_buf * adc2_buffers[NB_ADC2_CHANNELS];
+#endif
+
+/*
+ Static mapping from channel index to channel injection
+ index:
+*/
+
+/*
+ Maps integer value x to ADC_InjectedChannel_x,
+ so they can be iterated safely
+*/
+static uint8_t adc_injected_channels[4];
+/*
+ Maps integer value x to ADC_Channel_y, like
+
+ 0 --> ADC_Channel_5
+ 1 --> ADC_Channel_8
+ 2 --> ADC_Channel_13
+
+ so they can be iterated incrementally.
+*/
+static uint8_t adc_channel_map[4];
+
+/*
+ TODO: Extend interface to allow adressing a
+ specific ADC (at least ADC1 and ADC2)?
+*/
+void adc_buf_channel(uint8_t adc_channel,
+ struct adc_buf * s,
+ uint8_t av_nb_sample)
+{
+ adc1_buffers[adc_channel] = s;
+ s->av_nb_sample = av_nb_sample;
}
+// #define USE_AD_TIM4
+/* Configure and enable RCC for peripherals (ADC1, ADC2, Timer) */
+static inline void adc_init_rcc( void )
+{ // {{{
+#if defined (USE_AD1) || defined (USE_AD2)
+ TIM_TypeDef * timer;
+ uint32_t rcc_apb;
+#ifdef USE_AD_TIM4
+ timer = TIM4;
+ rcc_apb = RCC_APB1Periph_TIM4;
+#else
+ timer = TIM2;
+ rcc_apb = RCC_APB1Periph_TIM2;
+#endif
+
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+
+ RCC_ADCCLKConfig(RCC_PCLK2_Div2);
+ RCC_APB1PeriphClockCmd(rcc_apb, ENABLE);
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |
+ RCC_APB2Periph_GPIOC, ENABLE);
+#ifdef USE_AD1
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
+#endif
+#ifdef USE_AD2
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
+#endif
+
+ /* Time Base configuration */
+ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
+ TIM_TimeBaseStructure.TIM_Period = 0xFF;
+ TIM_TimeBaseStructure.TIM_Prescaler = 0x8;
+ TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+ TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
+ TIM_SelectOutputTrigger(timer, TIM_TRGOSource_Update);
+ TIM_Cmd(timer, ENABLE);
+
+#endif // defined (USE_AD1) || defined (USE_AD2)
+} // }}}
+
+/* Configure and enable ADC interrupt */
+static inline void adc_init_irq( void )
+{ // {{{
+ NVIC_InitTypeDef nvic;
+ nvic.NVIC_IRQChannel = ADC1_2_IRQn;
+ nvic.NVIC_IRQChannelPreemptionPriority = 0;
+ nvic.NVIC_IRQChannelSubPriority = 0;
+ nvic.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&nvic);
+} // }}}
+
+/*
+ Usage:
+
+ adc_init_single(ADC1, 1, 1, 0, 0);
+
+ ... would enable ADC1, enabling channels 1 and 2,
+ but not 3 and 4.
+*/
+static inline void adc_init_single(ADC_TypeDef * adc_t,
+ uint8_t chan1, uint8_t chan2,
+ uint8_t chan3, uint8_t chan4)
+{
+ GPIO_InitTypeDef gpio;
+ ADC_InitTypeDef adc;
+ uint8_t num_channels, rank;
+
+ // Paranoia, must be down for 2+ ADC clock cycles before calibration
+ ADC_Cmd(adc_t, DISABLE);
+
+ /* enable adc_t clock */
+ if (adc_t == ADC1) {
+#ifdef USE_AD1
+ num_channels = NB_ADC1_CHANNELS;
+ ADC1_GPIO_INIT(gpio);
+#endif
+ }
+ else if (adc_t == ADC2) {
+#ifdef USE_AD2
+ num_channels = NB_ADC2_CHANNELS;
+ ADC2_GPIO_INIT(gpio);
+#endif
+ }
+
+ /* Configure ADC */
+
+ adc.ADC_Mode = ADC_Mode_Independent;
+ adc.ADC_ScanConvMode = DISABLE;
+ adc.ADC_ContinuousConvMode = DISABLE;
+ adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
+ adc.ADC_DataAlign = ADC_DataAlign_Right;
+ adc.ADC_NbrOfChannel = 0; // No. of channels in regular mode
+ ADC_Init(adc_t, &adc);
+
+ ADC_InjectedSequencerLengthConfig(adc_t, num_channels);
+
+ rank = 1;
+ if (chan1) {
+ ADC_InjectedChannelConfig(adc_t, adc_channel_map[0], rank,
+ ADC_SampleTime_41Cycles5);
+ rank++;
+ }
+ if (chan2) {
+ ADC_InjectedChannelConfig(adc_t, adc_channel_map[1], rank,
+ ADC_SampleTime_41Cycles5);
+ rank++;
+ }
+ if (chan3) {
+ ADC_InjectedChannelConfig(adc_t, adc_channel_map[2], rank,
+ ADC_SampleTime_41Cycles5);
+ rank++;
+ }
+ if (chan4) {
+ ADC_InjectedChannelConfig(adc_t, adc_channel_map[3], rank,
+ ADC_SampleTime_41Cycles5);
+ }
+
+
+ ADC_ExternalTrigInjectedConvCmd(adc_t, ENABLE);
+#ifdef USE_AD_TIM4
+ ADC_ExternalTrigInjectedConvConfig(adc_t,
ADC_ExternalTrigInjecConv_T4_TRGO);
+#else
+ ADC_ExternalTrigInjectedConvConfig(adc_t,
ADC_ExternalTrigInjecConv_T2_TRGO);
+#endif
+
+ /* Enable ADC<X> JEOC interrupt */
+ ADC_ITConfig(adc_t, ADC_IT_JEOC, ENABLE);
+
+ /* Enable ADC<X> */
+ ADC_Cmd(adc_t, ENABLE);
+
+ /* Enable ADC<X> reset calibaration register */
+ ADC_ResetCalibration(adc_t);
+
+ /* Check the end of ADC<X> reset calibration */
+ while (ADC_GetResetCalibrationStatus(adc_t)) ;
+ /* Start ADC<X> calibaration */
+ ADC_StartCalibration(adc_t);
+ /* Check the end of ADC<X> calibration */
+ while (ADC_GetCalibrationStatus(adc_t)) ;
+
+} // adc_init_single
+
+void adc_init( void ) {
+
+ adc_injected_channels[0] = ADC_InjectedChannel_1;
+ adc_injected_channels[1] = ADC_InjectedChannel_2;
+ adc_injected_channels[2] = ADC_InjectedChannel_3;
+ adc_injected_channels[3] = ADC_InjectedChannel_4;
+ adc_channel_map[0] = ADC_Channel_8;
+ adc_channel_map[1] = ADC_Channel_9;
+ adc_channel_map[2] = ADC_Channel_13;
+ adc_channel_map[3] = ADC_Channel_15;
+ adc_new_data_trigger = 0;
+
+ adc_init_rcc();
+ adc_init_irq();
+
+// adc_init_single(ADCx, c1, c2, c3, c4)
+// {{{
+#ifdef USE_AD1
+ adc_init_single(ADC1,
+#ifdef USE_AD1_1
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD1_2
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD1_3
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD1_4
+ 1
+#else
+ 0
+#endif
+ );
+#endif // USE_AD1
+
+#ifdef USE_AD2
+ adc_init_single(ADC2,
+#ifdef USE_AD2_1
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD2_2
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD2_3
+ 1,
+#else
+ 0,
+#endif
+#ifdef USE_AD2_4
+ 1
+#else
+ 0
+#endif
+ );
+#endif // USE_AD2
+
+// }}}
+}
+
+static inline void adc_push_sample(struct adc_buf * buf, uint16_t value) {
+ uint8_t new_head = buf->head + 1;
+
+ if (new_head >= buf->av_nb_sample) { new_head = 0; }
+ buf->sum -= buf->values[new_head];
+ buf->values[new_head] = value;
+ buf->sum += value;
+ buf->head = new_head;
+}
+
+/**
+ * ADC1+2 interrupt hander
+ */
+void adc1_2_irq_handler(void)
+{
+ uint8_t channel = 0;
+
+ LED_TOGGLE(5);
+
+#ifdef USE_AD1
+ // Clear Injected End Of Conversion
+ ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
+ for(channel = 0; channel < NB_ADC1_CHANNELS; channel++) {
+ adc_push_sample(adc1_buffers[channel],
+ ADC_GetInjectedConversionValue(ADC1,
adc_injected_channels[channel]));
+ }
+ adc_new_data_trigger = 1;
+#endif
+#ifdef USE_AD2
+ // Clear Injected End Of Conversion
+ ADC_ClearITPendingBit(ADC2, ADC_IT_JEOC);
+ for(channel = 0; channel < NB_ADC2_CHANNELS; channel++) {
+ adc_push_sample(adc2_buffers[channel],
+ ADC_GetInjectedConversionValue(ADC2,
adc_injected_channels[channel]));
+ }
+ adc_new_data_trigger = 1;
+#endif
+}
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [paparazzi-commits] [5683] Added STM32 ADC driver ( 4-channel injection triggered by timer 2 or 4).,
Tobias Fuchs <=