Low Layer Driver을 사용한 ADC
들어오는 ADC 값의 움직임을 크게 주기 위해 샘플링 주기를 짧게 가져왔습니다.(LL_ADC_SAMPLINGTIME_2CYCLES_5)
int main(void)
{
uint32_t nBuf[128];
uint8_t i;
/* Configure the system clock to 80 MHz */
SystemClock_LLConfig();
/* ADC Configuration */
ADC_Configuration();
while(1){
GetADC1(chBuf);
for(i = 0; i< 11; i++){
UART1_printf("ADC0 =%02X \r\n", chBuf[i]);
}
}
}
#include "math.h"
#include "usr_adc.h"
#include "usr_usart.h"
#include "stm32l4xx_ll_dma.h"
#include "stm32l4xx_ll_adc.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_gpio.h"
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Variables for ADC conversion data */
__IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* ADC group regular conversion data */
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void ADC_Configuration(void)
{
ADCDMA_Init(eADCIntDisable);
ADC_Init(eADCIntDisable);
Activate_ADC();
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void ADCDMA_Init(const ADCEnableState a_chInt)
{
/*## Configuration of DMA ##################################################*/
/* Enable the peripheral clock of DMA */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/* Configure the DMA transfer */
/* - DMA transfer in circular mode to match with ADC configuration: */
/* DMA unlimited requests. */
/* - DMA transfer from ADC without address increment. */
/* - DMA transfer to memory with address increment. */
/* - DMA transfer from ADC by half-word to match with ADC configuration: */
/* ADC resolution 12 bits. */
/* - DMA transfer to memory by half-word to match with ADC conversion data */
/* buffer variable type: half-word. */
LL_DMA_ConfigTransfer(DMA1,
LL_DMA_CHANNEL_1,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
LL_DMA_MODE_CIRCULAR |
LL_DMA_PERIPH_NOINCREMENT |
LL_DMA_MEMORY_INCREMENT |
LL_DMA_PDATAALIGN_HALFWORD |
LL_DMA_MDATAALIGN_HALFWORD |
LL_DMA_PRIORITY_HIGH );
/* Select ADC as DMA transfer request */
LL_DMA_SetPeriphRequest(DMA1,
LL_DMA_CHANNEL_1,
LL_DMA_REQUEST_0);
/* Set DMA transfer addresses of source and destination */
LL_DMA_ConfigAddresses(DMA1,
LL_DMA_CHANNEL_1,
LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA),
(uint32_t)&aADCxConvertedData,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
/* Set DMA transfer size */
LL_DMA_SetDataLength(DMA1,
LL_DMA_CHANNEL_1,
ADC_CONVERTED_DATA_BUFFER_SIZE);
/*## Activation of DMA #####################################################*/
/* Enable the DMA transfer */
LL_DMA_EnableChannel(DMA1,
LL_DMA_CHANNEL_1);
if(a_chInt == eADCIntEnable){
/* Enable DMA transfer interruption: transfer complete */
LL_DMA_EnableIT_TC(DMA1,
LL_DMA_CHANNEL_1);
/* Enable DMA transfer interruption: transfer error */
LL_DMA_EnableIT_TE(DMA1,
LL_DMA_CHANNEL_1);
/*## Configuration of NVIC #################################################*/
/* Configure NVIC to enable DMA interruptions */
NVIC_SetPriority(DMA1_Channel1_IRQn, 1); /* DMA IRQ lower priority than ADC IRQ */
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
}
/*******************************************************************************
* Function Name :
* Parameters :
* Return : None
* Description :
*******************************************************************************/
void ADC_Init(const ADCEnableState a_chInt)
{
__IO uint32_t wait_loop_index = 0;
/*## Configuration of GPIO used by ADC channels ############################*/
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
/* Configure GPIO in analog mode to be used as ADC input */
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_1, LL_GPIO_MODE_ANALOG);//ADC_IN1
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_2, LL_GPIO_MODE_ANALOG);//ADC_IN2
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_3, LL_GPIO_MODE_ANALOG);//ADC_IN3
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_ANALOG);//ADC_IN4
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_ANALOG);//ADC_IN5
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_ANALOG);//ADC_IN6
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_ANALOG);//ADC_IN7
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_0, LL_GPIO_MODE_ANALOG);//ADC_IN8
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_1, LL_GPIO_MODE_ANALOG);//ADC_IN9
/*## Configuration of ADC ##################################################*/
/* Enable ADC clock (core clock) */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
if(__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE() == 0)
{
/* Set ADC clock (conversion clock) common to several ADC instances */
LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_SYNC_PCLK_DIV2);
/* Set ADC measurement path to internal channels */
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), (LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_TEMPSENSOR));
/* Delay for ADC temperature sensor stabilization time. */
wait_loop_index = ((LL_ADC_DELAY_TEMPSENSOR_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
/* Set ADC multimode configuration */
// LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_INDEPENDENT);
/* Set ADC multimode DMA transfer */
// LL_ADC_SetMultiDMATransfer(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_REG_DMA_EACH_ADC);
/* Set ADC multimode: delay between 2 sampling phases */
// LL_ADC_SetMultiTwoSamplingDelay(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE);
}
/*## Configuration of ADC hierarchical scope: ADC instance #################*/
if (LL_ADC_IsEnabled(ADC1) == 0)
{
/* Note: Call of the functions below are commented because they are */
/* useless in this example: */
/* setting corresponding to default configuration from reset state. */
/* Set ADC data resolution */
// LL_ADC_SetResolution(ADC1, LL_ADC_RESOLUTION_12B);
/* Set ADC conversion data alignment */
// LL_ADC_SetResolution(ADC1, LL_ADC_DATA_ALIGN_RIGHT);
/* Set ADC low power mode */
// LL_ADC_SetLowPowerMode(ADC1, LL_ADC_LP_MODE_NONE);
/* Set ADC selected offset number: channel and offset level */
// LL_ADC_SetOffset(ADC1, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_9, 0x000);
}
/*## Configuration of ADC hierarchical scope: ADC group regular ############*/
if ((LL_ADC_IsEnabled(ADC1) == 0) ||
(LL_ADC_REG_IsConversionOngoing(ADC1) == 0) )
{
/* Set ADC group regular trigger source */
LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE);
/* Set ADC group regular trigger polarity */
// LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_RISING);
/* Set ADC group regular continuous mode */
LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_SINGLE);
// LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_CONTINUOUS);
/* Set ADC group regular conversion data transfer */
// LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);
LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
/* Set ADC group regular overrun behavior */
LL_ADC_REG_SetOverrun(ADC1, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
/* Set ADC group regular sequencer length and scan direction */
// LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_DISABLE);
LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS);
/* Set ADC group regular sequencer discontinuous mode */
// LL_ADC_REG_SetSequencerDiscont(ADC1, LL_ADC_REG_SEQ_DISCONT_DISABLE);
/* Set ADC group regular sequence: channel on the selected sequence rank. */
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_6);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_7);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_8);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_9);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_10);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_6, LL_ADC_CHANNEL_11);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_7, LL_ADC_CHANNEL_12);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_8, LL_ADC_CHANNEL_15);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_9, LL_ADC_CHANNEL_16);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_10, LL_ADC_CHANNEL_VREFINT);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_11, LL_ADC_CHANNEL_TEMPSENSOR);
}
/*## Configuration of ADC hierarchical scope: ADC group injected ###########*/
if ((LL_ADC_IsEnabled(ADC1) == 0) ||
(LL_ADC_INJ_IsConversionOngoing(ADC1) == 0) )
{
/* Note: Call of the functions below are commented because they are */
/* useless in this example: */
/* setting corresponding to default configuration from reset state. */
/* Set ADC group injected trigger source */
// LL_ADC_INJ_SetTriggerSource(ADC1, LL_ADC_INJ_TRIG_SOFTWARE);
/* Set ADC group injected trigger polarity */
// LL_ADC_INJ_SetTriggerEdge(ADC1, LL_ADC_INJ_TRIG_EXT_RISING);
/* Set ADC group injected conversion trigger */
// LL_ADC_INJ_SetTrigAuto(ADC1, LL_ADC_INJ_TRIG_INDEPENDENT);
/* Set ADC group injected contexts queue mode */
/* Note: If ADC group injected contexts queue are enabled, configure */
/* contexts using function "LL_ADC_INJ_ConfigQueueContext()". */
// LL_ADC_INJ_SetQueueMode(ADC1, LL_ADC_INJ_QUEUE_DISABLE);
/* Set ADC group injected sequencer */
/* Note: On this STM32 serie, ADC group injected sequencer is */
/* fully configurable: sequencer length and each rank */
/* affectation to a channel are configurable. */
/* Refer to description of function */
/* "LL_ADC_INJ_SetSequencerLength()". */
/* Set ADC group injected sequencer length and scan direction */
// LL_ADC_INJ_SetSequencerLength(ADC1, LL_ADC_INJ_SEQ_SCAN_DISABLE);
/* Set ADC group injected sequencer discontinuous mode */
// LL_ADC_INJ_SetSequencerDiscont(ADC1, LL_ADC_INJ_SEQ_DISCONT_DISABLE);
/* Set ADC group injected sequence: channel on the selected sequence rank. */
// LL_ADC_INJ_SetSequencerRanks(ADC1, LL_ADC_INJ_RANK_1, LL_ADC_CHANNEL_9);
}
/*## Configuration of ADC hierarchical scope: channels #####################*/
if ((LL_ADC_IsEnabled(ADC1) == 0) ||
((LL_ADC_REG_IsConversionOngoing(ADC1) == 0) &&
(LL_ADC_INJ_IsConversionOngoing(ADC1) == 0) ) )
{
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_10, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_11, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_16, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_2CYCLES_5);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_2CYCLES_5);
}
/*## Configuration of ADC transversal scope: analog watchdog ###############*/
/* Set ADC analog watchdog channels to be monitored */
// LL_ADC_SetAnalogWDMonitChannels(ADC1, LL_ADC_AWD1, LL_ADC_AWD_DISABLE);
/* Set ADC analog watchdog thresholds */
// LL_ADC_ConfigAnalogWDThresholds(ADC1, LL_ADC_AWD1, 0xFFF, 0x000);
/*## Configuration of ADC transversal scope: oversampling ##################*/
/* Set ADC oversampling scope */
// LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
/* Set ADC oversampling parameters */
// LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_2, LL_ADC_OVS_SHIFT_NONE);
/*## Configuration of ADC transversal scope: oversampling ##################*/
/*## Configuration of ADC interruptions ####################################*/
/* Enable interruption ADC group regular overrun */
if(a_chInt == eADCIntEnable){
/*## Configuration of NVIC #################################################*/
/* Configure NVIC to enable ADC1 interruptions */
NVIC_SetPriority(ADC1_2_IRQn, 0); /* ADC IRQ greater priority than DMA IRQ */
NVIC_EnableIRQ(ADC1_2_IRQn);
LL_ADC_EnableIT_EOS(ADC1);
LL_ADC_EnableIT_OVR(ADC1);
}
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void ConversionStartPoll_ADC_GrpRegular(void)
{
#if (USE_TIMEOUT == 1)
uint32_t Timeout = 0; /* Variable used for timeout management */
#endif /* USE_TIMEOUT */
if ((LL_ADC_IsEnabled(ADC1) == 1) &&
(LL_ADC_IsDisableOngoing(ADC1) == 0) &&
(LL_ADC_REG_IsConversionOngoing(ADC1) == 0) )
{
LL_ADC_REG_StartConversion(ADC1);
}
else
{
/* Error: ADC conversion start could not be performed */
}
#if (USE_TIMEOUT == 1)
Timeout = ADC_UNITARY_CONVERSION_TIMEOUT_MS;
#endif /* USE_TIMEOUT */
while (LL_ADC_IsActiveFlag_EOC(ADC1) == 0)
{
#if (USE_TIMEOUT == 1)
/* Check Systick counter flag to decrement the time-out value */
if (LL_SYSTICK_IsActiveCounterFlag())
{
if(Timeout-- == 0)
{
}
}
#endif /* USE_TIMEOUT */
}
LL_ADC_ClearFlag_EOC(ADC1);
}
/*******************************************************************************
* Function Name :
* Description :
* Parameters :
* Return :
* Description :
*******************************************************************************/
int32_t GetADC1(uint16_t *chpADC)
{
uint8_t ADCLoop;
if ((LL_ADC_IsEnabled(ADC1) == 1) &&
(LL_ADC_IsDisableOngoing(ADC1) == 0) &&
(LL_ADC_REG_IsConversionOngoing(ADC1) == 0) )
{
LL_ADC_REG_StartConversion(ADC1);
}
else
{
/* Error: ADC conversion start could not be performed */
UART1_printf("Error\r\n");
}
for(ADCLoop = 0; ADCLoop < ADC_CONVERTED_DATA_BUFFER_SIZE; ADCLoop++){
chpADC[ADCLoop] = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, aADCxConvertedData[ADCLoop], LL_ADC_RESOLUTION_12B);
}
return __LL_ADC_CALC_TEMPERATURE(VDDA_APPLI, aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE - 1], LL_ADC_RESOLUTION_12B);
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void AdcGrpRegularOverrunError_Callback(void)
{
/* Disable ADC group regular overrun interruption */
LL_ADC_DisableIT_OVR(ADC1);
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void AdcGrpRegularSequenceConvComplete_Callback(void)
{
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void AdcDmaTransferError_Callback(void)
{
}
/*******************************************************************************
* Function Name :
* Parameters : None
* Return : None
* Description :
*******************************************************************************/
void AdcDmaTransferComplete_Callback(void)
{
}
'초보의 아웅다웅 설계하기 > STM32' 카테고리의 다른 글
STM32L432 Read Protection 버그인가? (0) | 2018.06.28 |
---|---|
STM32L4xx에서 Brownout, ReadOut Protection 설정 (0) | 2018.06.26 |
WWDG에서 Watchdog 발생시 클리어 처리 (0) | 2018.05.17 |
변수 선언시 __IO의 사용 (0) | 2018.04.21 |
ST에서 지원하는 Low Layer 드라이버 (0) | 2018.04.20 |