001.
/*
002.
003.
FILE: adc3d.c
004.
MODULE: SDADC interface three channel syncro
005.
TARGET: STM32F373
006.
Start at 18.03.2015 13:36
007.
008.
Written by Vlad Zaritsky. 2015
009.
010.
*/
011.
012.
#include "header.h"
013.
014.
#define ADC3D_ST_OFF 50
015.
#define ADC3D_ST_READY 55
016.
017.
#define ADC3D_RAW_LEN 128
018.
019.
// variables --------------------------------------------------------
020.
021.
__no_init uint8_t adc3d_state;
022.
__no_init uint32_t adc3d_timer;
023.
024.
__no_init uint16_t adc3d_adc_index;
025.
026.
__no_init int16_t adc3d_raw_x[ ADC3D_RAW_LEN ];
027.
__no_init int16_t adc3d_raw_y[ ADC3D_RAW_LEN ];
028.
__no_init int16_t adc3d_raw_z[ ADC3D_RAW_LEN ];
029.
030.
// init procedure ---------------------------------------------------
031.
032.
void
adc3d_init(
void
)
033.
{
034.
SDADC_InitTypeDef sdadcini;
035.
SDADC_AINStructTypeDef analogini;
036.
GPIO_InitTypeDef gpioini;
037.
038.
// SDADC step by step initialization as desribed in :
039.
// STM32F37x Standard Peripherals Library Drivers
040.
041.
// * @file stm32f37x_sdadc.c
042.
// * @author MCD Application Team
043.
// * @version V1.0.0
044.
// * @date 20-September-2012
045.
046.
// See section ##### How to use this driver #####
047.
048.
// (1) Enable the SDADC analog interface by calling
049.
// PWR_SDADCAnalogCmd(PWR_SDADCAnalog_x, Enable);
050.
051.
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR, ENABLE );
052.
053.
PWR_SDADCAnalogCmd( PWR_SDADCAnalog_1, ENABLE );
054.
PWR_SDADCAnalogCmd( PWR_SDADCAnalog_2, ENABLE );
055.
PWR_SDADCAnalogCmd( PWR_SDADCAnalog_3, ENABLE );
056.
057.
// (2) Enable the SDADC APB clock to get write access to SDADC registers using
058.
// RCC_APB1PeriphClockCmd() function
059.
// e.g. To enable access to SDADC1 registers use
060.
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_SDADC1, ENABLE); * really? do not trust them. the SDADCx use APB2 *
061.
062.
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR, ENABLE );
063.
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SDADC1 | RCC_APB2Periph_SDADC2 |
064.
RCC_APB2Periph_SDADC3, ENABLE );
065.
066.
// SDADC_Cmd( SDADC1, DISABLE );
067.
// SDADC_Cmd( SDADC2, DISABLE );
068.
// SDADC_Cmd( SDADC3, DISABLE );
069.
070.
// (3) The SDADCs are clocked by APB1.
071.
// In order to get the SDADC running at the typical frequency (6 MHz
072.
// in fast mode), use SDADC prescaler by calling RCC_SDADCCLKConfig() function
073.
// e.g. if APB1 is clocked at 72MHz, to get the SDADC running at 6MHz
074.
// configure the SDADC prescaler at 12 by calling
075.
// RCC_SDADCCLKConfig(RCC_SDADCCLK_SYSCLK_Div12);
076.
077.
// RCC_SDADCCLKConfig( RCC_SDADCCLK_SYSCLK_Div48 ); //1.5MHz @ 72MHz
078.
079.
// Set the SDADC divider: The SDADC should run @6MHz
080.
RCC_SDADCCLKConfig( RCC_SDADCCLK_SYSCLK_Div12 );
081.
082.
//GPIO pin preset
083.
GPIO_StructInit( &gpioini );
084.
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOE, ENABLE );
085.
086.
gpioini.GPIO_Mode = GPIO_Mode_AN;
087.
gpioini.GPIO_PuPd = GPIO_PuPd_NOPULL;
088.
gpioini.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_15;
089.
GPIO_Init( GPIOB, &gpioini );
090.
091.
gpioini.GPIO_Pin = GPIO_Pin_8;
092.
GPIO_Init( GPIOE, &gpioini );
093.
094.
// (4) If required, perform the following configurations:
095.
// (4.1) Select the reference voltage using SDADC_VREFSelect() function
096.
097.
// SDADC_VREFSelect( SDADC_VREF_VDDA ); // Select VDDA as reference
098.
// SDADC_VREFSelect( SDADC_VREF_Ext );
099.
100.
// (4.2) Enable the power-down and standby modes using SDADC_PowerDownCmd()
101.
// and SDADC_StandbyCmd() functions respectively
102.
// (4.3) Enable the slow clock mode (SDADC running at 1.5 MHz) using
103.
// RCC_SDADCCLKConfig() and SDADC_SlowClockCmd() function
104.
// -@@- These configurations are allowed only when the SDADC is disabled.
105.
106.
//ADC slow @ 1.5MHz
107.
// SDADC_SlowClockCmd( SDADC1, ENABLE );
108.
// SDADC_SlowClockCmd( SDADC2, ENABLE );
109.
// SDADC_SlowClockCmd( SDADC3, ENABLE );
110.
111.
// (5) Enable the SDADC peripheral using SDADC_Cmd() function.
112.
113.
SDADC_Cmd( SDADC1, ENABLE );
114.
SDADC_Cmd( SDADC2, ENABLE );
115.
SDADC_Cmd( SDADC3, ENABLE );
116.
117.
while
( SDADC_GetFlagStatus( SDADC1, SDADC_FLAG_STABIP ) == SET );
118.
while
( SDADC_GetFlagStatus( SDADC2, SDADC_FLAG_STABIP ) == SET );
119.
while
( SDADC_GetFlagStatus( SDADC3, SDADC_FLAG_STABIP ) == SET );
120.
121.
//wait 5ms
122.
adc3d_timer = 320000L;
123.
while
(adc3d_timer > 0L) { asm(
"nop"
); adc3d_timer--; }
124.
125.
// (6) Enter initialization mode using SDADC_InitModeCmd() function
126.
// then wait for INITRDY flag to be set to confirm that the SDADC
127.
// is in initialization mode.
128.
129.
// Initialization begins
130.
SDADC_InitModeCmd( SDADC1, ENABLE );
131.
SDADC_InitModeCmd( SDADC2, ENABLE );
132.
SDADC_InitModeCmd( SDADC3, ENABLE );
133.
134.
while
( SDADC_GetFlagStatus( SDADC1, SDADC_FLAG_INITRDY ) == RESET );
135.
while
( SDADC_GetFlagStatus( SDADC2, SDADC_FLAG_INITRDY ) == RESET );
136.
while
( SDADC_GetFlagStatus( SDADC3, SDADC_FLAG_INITRDY ) == RESET );
137.
138.
// (7) Configure the analog inputs: gain, single ended mode, offset value and
139.
// commmon mode using SDADC_AINInit().
140.
// There are three possible configuration: SDADC_Conf_0, SDADC_Conf_1 and SDADC_Conf_2
141.
142.
//Preset SDADC_Conf_x profile
143.
SDADC_AINStructInit( &analogini );
144.
analogini.SDADC_CommonMode = SDADC_CommonMode_VSSA;
145.
analogini.SDADC_Gain = SDADC_Gain_1;
146.
analogini.SDADC_Offset = 0;
147.
analogini.SDADC_InputMode = SDADC_InputMode_SEZeroReference;
148.
149.
// Configuration
150.
SDADC_AINInit( SDADC1, SDADC_Conf_0, &analogini );
151.
SDADC_AINInit( SDADC2, SDADC_Conf_1, &analogini );
152.
SDADC_AINInit( SDADC3, SDADC_Conf_2, &analogini );
153.
154.
// (8) Associate the selected configuration to the channel using SDADC_ChannelConfig()
155.
156.
SDADC_ChannelConfig( SDADC1, SDADC_Channel_4, SDADC_Conf_0 );
//SDADC1.4 x
157.
SDADC_ChannelConfig( SDADC2, SDADC_Channel_8, SDADC_Conf_1 );
//SDADC2.8 y
158.
SDADC_ChannelConfig( SDADC3, SDADC_Channel_7, SDADC_Conf_2 );
//SDADC3.7 z
159.
160.
// (9) For Regular channels group configuration
161.
// (9.1) use SDADC_Init() function to select the SDADC channel to be used
162.
// for regular conversion, the continuous mode...
163.
// -@@- Only software trigger or synchro with SDADC1 are possible
164.
// for regular conversion
165.
166.
sdadcini.SDADC_Channel = SDADC_Channel_4 ;
167.
sdadcini.SDADC_ContinuousConvMode = ENABLE;
168.
sdadcini.SDADC_FastConversionMode = DISABLE;
169.
SDADC_Init( SDADC1, &sdadcini );
170.
171.
sdadcini.SDADC_Channel = SDADC_Channel_8 ;
172.
SDADC_Init( SDADC2, &sdadcini );
173.
174.
sdadcini.SDADC_Channel = SDADC_Channel_7 ;
175.
SDADC_Init( SDADC3, &sdadcini );
176.
177.
SDADC_RegularSynchroSDADC1( SDADC2, ENABLE );
178.
SDADC_RegularSynchroSDADC1( SDADC3, ENABLE );
179.
180.
// Injected conversion synchronously with SDADC1 (not used here)
181.
// SDADC_InjectedSynchroSDADC1( SDADC2, ENABLE );
182.
// SDADC_InjectedSynchroSDADC1( SDADC3, ENABLE );
183.
184.
// (10) For Injected channels group configuration
185.
// (10.1) Select the SDADC channel to be used for injected conversion
186.
// using SDADC_InjectedChannelSelect()
187.
188.
// Injected cahnnels not used here
189.
// SDADC_InjectedChannelSelect( SDADC1, SDADC_Channel_4 ); //SDADC1.4 x
190.
// SDADC_InjectedChannelSelect( SDADC2, SDADC_Channel_8 ); //SDADC2.8 y
191.
// SDADC_InjectedChannelSelect( SDADC3, SDADC_Channel_7 ); //SDADC3.7 z
192.
193.
// (11) Exit initialization mode using SDADC_InitModeCmd() function
194.
195.
// Initialization ends
196.
SDADC_InitModeCmd( SDADC1, DISABLE );
197.
SDADC_InitModeCmd( SDADC2, DISABLE );
198.
SDADC_InitModeCmd( SDADC3, DISABLE );
199.
200.
while
( SDADC_GetFlagStatus( SDADC1, SDADC_FLAG_INITRDY ) == SET );
201.
while
( SDADC_GetFlagStatus( SDADC2, SDADC_FLAG_INITRDY ) == SET );
202.
while
( SDADC_GetFlagStatus( SDADC3, SDADC_FLAG_INITRDY ) == SET );
203.
204.
//Calibration
205.
SDADC_CalibrationSequenceConfig( SDADC1, SDADC_CalibrationSequence_1 );
206.
SDADC_StartCalibration( SDADC1 );
207.
while
( SDADC_GetFlagStatus( SDADC1, SDADC_FLAG_EOCAL ) == RESET );
208.
209.
SDADC_CalibrationSequenceConfig( SDADC2, SDADC_CalibrationSequence_1 );
210.
SDADC_StartCalibration( SDADC2 );
211.
while
( SDADC_GetFlagStatus( SDADC2, SDADC_FLAG_EOCAL ) == RESET );
212.
213.
SDADC_CalibrationSequenceConfig( SDADC3, SDADC_CalibrationSequence_1 );
214.
SDADC_StartCalibration( SDADC3 );
215.
while
( SDADC_GetFlagStatus( SDADC3, SDADC_FLAG_EOCAL ) == RESET );
216.
217.
adc3d_adc_index = 0;
218.
adc3d_state = ADC3D_ST_READY;
219.
adc3d_timer = 0L;
220.
}
221.
222.
// timer event or direct main loop call -----------------------------
223.
224.
void
adc3d_timer_event(
void
)
225.
{
226.
adc3d_timer++;
227.
if
( adc3d_timer > 30000L )
228.
{
229.
#ifdef __debug__
230.
USART1_puts(
"\r\n.SDADC TIMEOUT"
);
231.
#endif
232.
233.
adc3d_timer = 0L;
234.
adc3d_adc_start();
235.
}
236.
//is conversion end?
237.
else
if
( SDADC_GetFlagStatus( SDADC1, SDADC_FLAG_REOC ) &&
238.
SDADC_GetFlagStatus( SDADC2, SDADC_FLAG_REOC ) &&
239.
SDADC_GetFlagStatus( SDADC3, SDADC_FLAG_REOC ) )
240.
{
241.
adc3d_raw_x[ adc3d_adc_index ] = SDADC_GetConversionValue( SDADC1 );
242.
adc3d_raw_y[ adc3d_adc_index ] = SDADC_GetConversionValue( SDADC2 );
243.
adc3d_raw_z[ adc3d_adc_index ] = SDADC_GetConversionValue( SDADC3 );
244.
245.
adc3d_adc_index++;
246.
247.
//loop when array is full
248.
if
( adc3d_adc_index >= ADC3D_RAW_LEN )
249.
{
250.
adc3d_adc_index = 0;
251.
adc3d_adc_process();
252.
}
253.
254.
//to restart conversion
255.
adc3d_timer = 0L;
256.
adc3d_adc_start();
257.
}
258.
}
259.
260.
// Start the three channel synchronous conversion
261.
262.
void
adc3d_adc_start(
void
)
263.
{
264.
// Launches injected conversion synchronously with SDADC1 (not used)
265.
// SDADC_SoftwareStartInjectedConv( SDADC1 );
266.
267.
// Launches regular conversion synchronously with SDADC1
268.
SDADC_SoftwareStartConv( SDADC1 );
269.
}
270.
271.
// ADC data process - simple mean
272.
273.
void
adc3d_adc_process(
void
)
274.
{
275.
uint16_t i;
276.
float
summx, summy, summz;
277.
278.
//swap X-Y axis and reverse Z orientation divide by 2
279.
for
( i=0, summx=0.0, summy=0.0, summz=0.0; i < ADC3D_RAW_LEN; i++ )
280.
{
281.
summx += (
float
)(adc3d_raw_x[i]);
282.
summy += (
float
)(adc3d_raw_y[i]);
283.
summz += (
float
)(adc3d_raw_z[i]);
284.
}
285.
adc3d_out_x = (summx / ADC3D_RAW_LEN);
286.
adc3d_out_y = (summy / ADC3D_RAW_LEN);
287.
adc3d_out_z = (summz / ADC3D_RAW_LEN);
288.
}
289.
290.
// -- unused code rejected --
291.
292.
/* eof */