#include "adc.h" /* 數據定義 */ u8 UpdataTIM = 0; //更新TIM2定時器標志 u16 CurrentFreq = 500;//默認市電頻率,單位為0.1hz ADBASE_TYPE uAD_Buff_A[ADC_CHANNEL]; //ADC采集緩存A ADBASE_TYPE uAD_Buff_B[ADC_CHANNEL]; //ADC采集緩存B //考慮到可能出現的數據處理時間較長的問題,臨時添加緩存 //u16 uAD_IN_BUFF[ADC_BUFFSIZE][ADC_CHANNEL]; ADBASE_TYPE *CurrentBuffPtr = NULL; //當前緩存指針 /* * Function : static void ADCInit_GPIO(void) * Description : ADCGPIO初始化 * Arguments : 無 * Returns : 無 * Other : */ static void ADCInit_GPIO(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF時鍾 //ADC通道初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8| \ GPIO_Pin_9|GPIO_Pin_10; //PF3,PF4,PF5,PF6,PF7,PF8,PF9,PF10 ADC通道 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; //模擬輸入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不帶上下拉 GPIO_Init(GPIOF, &GPIO_InitStructure); //初始化 } /* * Function : static void ADCInit_ADC(void) * Description : ADC模式初始化 * Arguments : 無 * Returns : 無 * Other : */ static void ADCInit_ADC(void) { ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能ADC3時鍾 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE); //ADC3復位 RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE); //復位結束 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//獨立模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //兩個采樣階段之間的延遲5個時鍾(三重模式或雙重模式下使用) ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能(對於多個ADC模式) ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//預分頻4分頻。ADCCLK=PCLK2/4=84/4=21Mhz,ADC時鍾最好不要超過36Mhz ADC_CommonInit(&ADC_CommonInitStructure);//初始化 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE;//掃描模式(多通道ADC采集要用掃描模式) ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//關閉連續轉換 // ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //軟件觸發 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; //上升沿觸發 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO; //定時器事件2觸發ADC ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右對齊 ADC_InitStructure.ADC_NbrOfConversion = ADC_CHANNEL; //8個轉換在規則序列中 ADC_Init(ADC3, &ADC_InitStructure);//ADC初始化 //連續模式下,通道的配置 ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 1, ADC_SampleTime_15Cycles); //PF3,VIN1,通道9,UA,rank=1,表示連續轉換中第一個轉換的通道,采樣時間15個周期(如果數據不穩定可以延時采樣時間) ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 2, ADC_SampleTime_15Cycles); //PF4,VIN2,通道14,UB ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 3, ADC_SampleTime_15Cycles); //PF5,VIN3,通道15,AC220 ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 4, ADC_SampleTime_15Cycles); //PF6,VIN4,通道4,I0 ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 5, ADC_SampleTime_15Cycles); //PF7,VIN5,通道5,IA ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 6, ADC_SampleTime_15Cycles); //PF8,VIN6,通道6,IB ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 7, ADC_SampleTime_15Cycles); //PF9,VIN7,通道7,IC ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 8, ADC_SampleTime_15Cycles); //PF10,VIN8,通道8,暫時未接入信號 ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); //連續使能DMA ADC_DMACmd(ADC3, ENABLE); //使能ADC_DMA ADC_Cmd(ADC3, ENABLE);//開啟AD轉換器 } /* * Function : static void ADCInit_DMA(void) * Description : ADC使能DMA模式 * Arguments : 無 * Returns : 無 * Other : */ static void ADCInit_DMA(void) { DMA_InitTypeDef DMA_InitStructure; //時鍾 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //DMA設置 DMA_InitStructure.DMA_Channel = DMA_Channel_2; //選擇通道號 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC3->DR); //外圍設備地址,ADC_DR_DATA規則數據寄存器 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(u16 *)uAD_Buff_A; //DMA存儲器地址,自己設置的緩存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //傳輸方向,外設->存儲器 DMA_InitStructure.DMA_BufferSize = ADC_BUFFSIZE * ADC_CHANNEL; //DMA緩存大小,數據傳輸量32*8 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設是否為增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存儲器是否為增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外設數據長度半個字(16位) DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存儲器數據長度半字(16位) DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA模式,普通模式、循環模式,還有雙緩沖模式,需要特殊設置 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA優先級,高優先級 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不使用FIFO DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //FIFO閾值 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存儲器突發,單次傳輸 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外設突發,單次傳輸 DMA_Init(DMA2_Stream0, &DMA_InitStructure); //初始化DMA2_Stream0,對應為ADC3 //雙緩沖模式設置 DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)(u16 *)(uAD_Buff_B),DMA_Memory_0); //DMA_Memory_0首先被傳輸 DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE); //設置DMA中斷 DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC); //清除中斷標志 DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); //傳輸完成中斷 DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA } /* * Function : void ADCInit_Timer(void) * Description : ADC觸發定時器的設置 * Arguments : 無 * Returns : 無 * Other : */ void ADCInit_Timer(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //時鍾 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //失能定時器 TIM_Cmd(TIM2, DISABLE); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //初始化定時器 //定時器設置,T=(84 * 625) / 84M = 625us = 20ms/32,50Hz信號,每周期采樣32個點,采樣頻率1600 TIM_TimeBaseStructure.TIM_Prescaler = 84-1; //分頻系數,TIM2時鍾在分頻系數不為1時,時鍾是APB1時鍾的兩倍84M TIM_TimeBaseStructure.TIM_Period = 312500/CurrentFreq - 1; //周期值1M/32=31250,CurrentFreq單位為0.1hz,因此需擴大10倍 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //時鍾分頻因子 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ; //向上計數模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定時器2 //使能定時器中斷 TIM_ARRPreloadConfig(TIM2, ENABLE); //允許TIM2定時重載 TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //選擇TIM2的UPDATA事件更新為觸發源 // TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //配置TIM2中斷類型 //使能TIM2 TIM_Cmd(TIM2, ENABLE); DebugLog("Enable TIM2, Set frequency is %d.", CurrentFreq); } /* * Function : void ADCInit_Nvic(void) * Description : 中斷初始化 * Arguments : 無 * Returns : 無 * Other : */ static void ADCInit_Nvic(void) { NVIC_InitTypeDef NVIC_InitStructure; //定時器中斷設置 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //定時器TIM2中斷通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //搶占優先級0 NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //子優先級1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化NVIC寄存器 //DMA中斷設置 NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn; //DMA2_Stream0中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //搶占優先級1 NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //子優先級1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化NVIC寄存器 } /* * Function : void ADCInit(void) * Description : ADC初始化函 * Arguments : 無 * Returns : 無 * Other : */ void ADCInit(void) { ADCInit_GPIO(); ADCInit_DMA(); ADCInit_ADC(); ADCInit_Nvic(); DebugLog("ADC Init is finish."); } /* * Function : void TIM2_IRQHandler(void) * Description : TIM2中斷觸發函數 * Arguments : 無 * Returns : 無 * Other : */ void TIM2_IRQHandler(void) { OSIntEnter(); //進入中斷 if(TIM_GetITStatus(TIM2, TIM_IT_Update)) //判斷發生update事件中斷 { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除update事件中斷標志 // ADC_SoftwareStartConv(ADC1); } OSIntExit(); //退出中斷 } /* * Function : void DMA2_Stream0_IRQHandler(void) * Description : DMA2_Stream0中斷 * Arguments : 無 * Returns : 無 * Other : */ void DMA2_Stream0_IRQHandler(void) { u16 period = 0; OSIntEnter(); //進入中斷 if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0)) //判斷DMA傳輸完成中斷 { DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); // DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA,連續模式下不需要該使能 //數據轉移程序 if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_Memory_0) { CurrentBuffPtr = uAD_Buff_A; } else { CurrentBuffPtr = uAD_Buff_B; } //遙測任務等待該信號量 OSSemPost(SemAD); //判斷是否更新TIM2 if(UpdataTIM) { period = 312500/CurrentFreq - 1; //計算采樣頻率1M/32=31250;32為采樣點數,31250/freq=采樣周期 TIM_ARRPreloadConfig(TIM2, DISABLE); //關閉TIM2定時重載 TIM2->ARR = period ; //更新定時器周期 TIM_ARRPreloadConfig(TIM2, ENABLE); //打開TIM2定時重載 } } OSIntExit(); //退出中斷 }
另外還是雙緩存機制,代碼已經注釋的很清楚了,以后有問題了可以再回過頭來看看。
