stm32 多通道ADC+DMA採集
阿新 • • 發佈:2019-01-25
/*******************************************************************
** Variables Definitions **
*******************************************************************/
__IO uint16_t ADC_DMAValue[20][2];
GPIO_InitTypeDef GPIO_Init_ADC;
ADC_InitTypeDef ADC1_InitStructure; //ADC初始化結構體宣告
DMA_InitTypeDef DMA1_InitStructure; //DMA初始化結構體宣告
NVIC_InitTypeDef NVIC_DMA1Structure;
/*******************************
函式名稱:ADC_DMA_config
函式功能:ADC1與DMA1的聯合初始化
函式引數:uint32_t addr DMA1記憶體儲存地址
函式返回值:無
*********************************/
void ADC1_DMA1_config(uint32_t addr)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC時鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); //使能GPIOC時鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE); //使能GPIOC時鐘
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA時鐘
RCC_ADCCLKConfig(RCC_ADCCLK_PCLK2_Div4); //ADC時鐘頻率 48/4=12MHZ ,不可以大於14MHZ
GPIO_Init_ADC.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0; //管腳PB1 PB0
GPIO_Init_ADC.GPIO_Mode = GPIO_Mode_AN; //模擬輸入模式
GPIO_Init_ADC.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init_ADC.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_Init_ADC); //GPIOB初始化
/********************* ADC1初始化 ******************************/
ADC_DeInit(ADC1);
ADC1_InitStructure.ADC_Mode = ADC_Mode_Independent; //獨立的轉換模式
ADC1_InitStructure.ADC_ScanConvMode = ENABLE; //開啟掃描模式
ADC1_InitStructure.ADC_ContinuousConvMode = ENABLE; //開啟連續轉換模式
ADC1_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ADC外部開關,關閉狀態
ADC1_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //對齊方式,ADC為12位中,右對齊方式
ADC1_InitStructure.ADC_NbrOfChannel =2; //開啟通道數,2個
ADC_Init(ADC1, &ADC1_InitStructure);
// ADC_ExternalTrigConvCmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5); //ADC通道組, 第8個通道 取樣順序1,轉換時間 239.5個週期
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5); //ADC通道組, 第9個通道 取樣順序2,轉換時間
ADC_DMACmd(ADC1, ENABLE); //使能ADC與DMA的傳輸
ADC_Cmd(ADC1, ENABLE); //開啟ADC1
Delay_US(20);
ADC_ResetCalibration(ADC1); //重新校準
while(ADC_GetResetCalibrationStatus(ADC1)); //等待重新校準完成
ADC_StartCalibration(ADC1); //開始校準
while(ADC_GetCalibrationStatus(ADC1)); //等待校準完成
/****************** DMA1初始化 *******************/
DMA_DeInit(DMA1_Channel1); //開啟DMA1的第一通道
DMA1_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)&ADC1->DR; //DMA對應的外設基地址
DMA1_InitStructure.DMA_MemoryBaseAddr =addr; //記憶體儲存基地址
DMA1_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的轉換模式為SRC模式,由外設搬移到記憶體
DMA1_InitStructure.DMA_BufferSize =40; //DMA快取大小,20個
DMA1_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址遞增
DMA1_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //記憶體地址遞增
DMA1_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定義外設資料寬度
DMA1_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移資料尺寸
DMA1_InitStructure.DMA_Mode = DMA_Mode_Circular; //轉換模式,迴圈快取模式。
DMA1_InitStructure.DMA_Priority = DMA_Priority_High; //DMA優先順序高
DMA1_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用
DMA_Init(DMA1_Channel1, &DMA1_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); //DMA傳送中斷使能
NVIC_DMA1Structure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_DMA1Structure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_DMA1Structure.NVIC_IRQChannelSubPriority = 1;
NVIC_DMA1Structure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_DMA1Structure); // Enable the DMA Interrupt
}
/***********************************************************
函式名稱: Get_Adc
函式功能: 等待ADC1轉換完成
入口引數: void
出口引數: void
***********************************************************/
void Get_Adc()
{
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1, ADC_SampleTime_239Cycles5); //ADC通道組, 第8個通道 取樣順序1,轉換時間 239.5個週期
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2, ADC_SampleTime_239Cycles5); //ADC通道組, 第9個通道 取樣順序2,轉換時間
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //軟體規則組通道轉換使能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); //等待轉換結束
}
void bubbleSort(uint8_t column) //氣泡排序演算法,從大到小進行排序
{
int i,j;
int flag = 1;
for(i=0;i<N&&flag;i++)
{
for(j=0;j<N-1-i;j++)
{
flag = 0;
if(ADC_DMAValue[j][column]>ADC_DMAValue[j+1][column])
{
uint16_t temp = ADC_DMAValue[j][column];
ADC_DMAValue[j][column] = ADC_DMAValue[j+1][column];
ADC_DMAValue[j+1][column] = temp;
flag = 1;
}
}
}
}
void filter() //均值濾波處理函式
{
for(count=4;count<N-4;count++) //去掉較大的四個值和較小的四個值,再取其餘值的平均值
{
ADC_Value1+=ADC_DMAValue[count][0];
ADC_Value2+=ADC_DMAValue[count][1];
}
ADC_Value1=ADC_Value1/(N-8);
ADC_Value2=ADC_Value2/(N-8);
RxCounter=7;
}
該程式由本樓主自己編寫,完成除錯,只要適當呼叫程式即可正常使用,有問題可評論,一起探討。。。