设计了一种通过软件触发,循环采集的ADC驱动程序
#include "stdbool.h"
#include "string.h"
#include "stm32f0xx_ll_bus.h"
#include "stm32f0xx_ll_gpio.h"
#include "stm32f0xx_ll_adc.h"
#include "stm32f0xx_ll_dma.h"
typedef struct ADC_GPIO_tag
{uint32_t rcu_GPIO;GPIO_TypeDef * PORT_GPIO;uint32_t PIN_GPIO;uint32_t ADCchannel;uint32_t DMAchannel;
}ADC_GPIO_t;
#define DMA_PERI_ADDR (uint32_t)&(ADC1->DR)
#define DMA_MEM_ADDR (uint32_t)&ADC_Buffer
#define ADC_SAMPLE_INTERVAL LL_ADC_SAMPLINGTIME_239CYCLES_5
#define ADC_CHANNEL_NUM 1
#define ADC_BUFF_SIZE 200
static uint16_t ADC_Buffer[ADC_CHANNEL_NUM][ADC_BUFF_SIZE];
static ADC_GPIO_t ADC_GPIO[ADC_CHANNEL_NUM] =
{{LL_AHB1_GRP1_PERIPH_GPIOA, GPIOA, LL_GPIO_PIN_6,LL_ADC_CHANNEL_6,LL_DMA_CHANNEL_1,},
};
void ADC_Init(void)
{LL_DMA_InitTypeDef init_struct;LL_ADC_InitTypeDef adc_init_struct;LL_ADC_REG_InitTypeDef regular_init_struct;LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_ADC1);for(int i = 0; i<ADC_CHANNEL_NUM; i++){LL_AHB1_GRP1_EnableClock(ADC_GPIO[i].rcu_GPIO);LL_GPIO_SetPinMode(ADC_GPIO[i].PORT_GPIO,ADC_GPIO[i].PIN_GPIO,LL_GPIO_MODE_ANALOG);}memset(&init_struct,0,sizeof(init_struct));init_struct.Direction=LL_DMA_DIRECTION_PERIPH_TO_MEMORY;init_struct.MemoryOrM2MDstAddress= DMA_MEM_ADDR;init_struct.MemoryOrM2MDstIncMode=LL_DMA_MEMORY_INCREMENT;init_struct.MemoryOrM2MDstDataSize=LL_DMA_MDATAALIGN_HALFWORD;init_struct.NbData=ADC_BUFF_SIZE*ADC_CHANNEL_NUM;init_struct.PeriphOrM2MSrcAddress=DMA_PERI_ADDR;init_struct.PeriphOrM2MSrcIncMode=LL_DMA_PERIPH_NOINCREMENT;init_struct.PeriphOrM2MSrcDataSize=LL_DMA_PDATAALIGN_HALFWORD;init_struct.Priority=LL_DMA_PRIORITY_HIGH;for(int i = 0;i<ADC_CHANNEL_NUM;i++){LL_DMA_DeInit(DMA1,ADC_GPIO[i].DMAchannel);LL_DMA_Init(DMA1,ADC_GPIO[i].DMAchannel,&init_struct);LL_DMA_SetMode(DMA1,ADC_GPIO[i].DMAchannel,LL_DMA_MODE_CIRCULAR);LL_DMA_EnableChannel(DMA1,ADC_GPIO[i].DMAchannel);}LL_ADC_DeInit(ADC1);adc_init_struct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;adc_init_struct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;adc_init_struct.Resolution = LL_ADC_RESOLUTION_12B;adc_init_struct.LowPowerMode = LL_ADC_LP_MODE_NONE;LL_ADC_Init(ADC1,&adc_init_struct);regular_init_struct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;regular_init_struct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED;regular_init_struct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;regular_init_struct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;regular_init_struct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;LL_ADC_REG_Init(ADC1,®ular_init_struct);LL_ADC_REG_SetSequencerScanDirection(ADC1,LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);for(int i = 0;i<ADC_CHANNEL_NUM;i++){LL_ADC_REG_SetSequencerChannels(ADC1,ADC_GPIO[i].ADCchannel);}LL_ADC_SetSamplingTimeCommonChannels(ADC1,ADC_SAMPLE_INTERVAL);LL_ADC_StartCalibration(ADC1);while(LL_ADC_IsCalibrationOnGoing(ADC1)==true);LL_ADC_Enable(ADC1);while(!LL_ADC_IsEnabled(ADC1));LL_ADC_REG_StartConversion(ADC1);}
void ADC_CopyBuf(uint32_t ch, uint32_t count,uint16_t *pBuf)
{uint32_t i;assert(pBuf != NULL);assert(ch < ADC_CHANNEL_NUM);if(count == 0){count = 1;}if(count > ADC_BUFF_SIZE){count = ADC_BUFF_SIZE;}for(i=ADC_BUFF_SIZE;i>ADC_BUFF_SIZE-count;i--){pBuf[i] = ADC_Buffer[ch][i];}}