转:https://blog.csdn.net/yyx112358/article/details/78414594
想当年天天水论坛好为人师,现在已经全面转向计算机视觉方向了,颇为感慨。不过,自己的理性选择,个中得失早就意料之中。塞翁失马,焉知非福?
原文链接:http://www.openedv.com/forum.php?mod=viewthread&tid=82594&extra=
【教程】使用STM32测量频率和占空比的几种方法(申请置酷!)
-
void Tim2_PWMIC_Init(void)
-
{
-
GPIO_InitTypeDef GPIO_InitStructure;
-
NVIC_InitTypeDef NVIC_InitStructure;
-
TIM_ICInitTypeDef TIM_ICInitStructure;
-
/* TIM4 clock enable */
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
-
-
/* GPIOB clock enable */
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
-
-
/* TIM4 chennel2 configuration : PB.07 */
-
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
-
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
-
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
-
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
-
GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-
/* Connect TIM pin to AF2 */
-
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);
-
-
/* Enable the TIM4 global Interrupt */
-
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
0;
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0;
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-
NVIC_Init(&NVIC_InitStructure);
-
-
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
-
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
-
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
-
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
-
TIM_ICInitStructure.TIM_ICFilter =
0x0;
-
-
TIM_PWMIConfig(TIM4, &TIM_ICInitStructure);
-
-
/* Select the TIM4 Input Trigger: TI2FP2 */
-
TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
-
-
/* Select the slave Mode: Reset Mode */
-
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
-
TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);
-
-
/* TIM enable counter */
-
TIM_Cmd(TIM4, ENABLE);
-
-
/* Enable the CC2 Interrupt Request */
-
TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
-
-
}
-
//中断程序:
-
void TIM4_IRQHandler(void)
-
{
-
/* Clear TIM4 Capture compare interrupt pending bit */
-
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1|TIM_IT_CC2);
-
-
/* Get the Input Capture value */
-
IC2Value = TIM_GetCapture2(TIM4);
//周期
-
-
if (IC2Value !=
0)
-
{
-
highval[filter_cnt]=TIM_GetCapture1(TIM4);
//高电平周期
-
waveval[filter_cnt]=IC2Value;
-
filter_cnt++;
-
if(filter_cnt>=FILTER_NUM)
-
filter_cnt=
0;
-
}
-
else
-
{
-
DutyCycle =
0;
-
Frequency =
0;
-
}
-
}
-
//主循环:
-
while (
1)
-
{
-
uint32_t highsum=
0,wavesum=
0,dutysum=
0,freqsum=
0;
-
LCD_Clear(
0);
-
for(i=
0;i<FILTER_NUM;i++)
-
{
-
highsum+=highval[i];
-
wavesum+=waveval;
-
}
-
[/i] delay_ms(
1);
-
DutyCycle=highsum*
1000/wavesum;
-
Frequency=(SystemCoreClock/
2*
1000/wavesum);
-
freq=Frequency*
2.2118
-47.05;
//线性补偿
-
sprintf(str,
"DUTY:%3d\nFREQ:%.3f KHZ\n",DutyCycle,freq/
1000);
-
-
LCD_ShowString(
0,
200,str);
-
delay_ms(
100);
-
}
-
//定时器5通道1输入捕获配置
-
//arr:自动重装值(TIM2,TIM5是32位的!!)
-
//psc:时钟预分频数
-
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
-
{
-
GPIO_InitTypeDef GPIO_InitStructure;
-
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
NVIC_InitTypeDef NVIC_InitStructure;
-
-
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
//TIM5时钟使能
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//使能PORTA时钟
-
-
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
//GPIOA0
-
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//复用功能
-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
//速度100MHz
-
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//推挽复用输出
-
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
//下拉
-
GPIO_Init(GPIOA,&GPIO_InitStructure);
//初始化PA0
-
-
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);
//PA0复用位定时器5
-
-
-
TIM_TimeBaseStructure.TIM_Prescaler=psc;
//定时器分频
-
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//向上计数模式
-
TIM_TimeBaseStructure.TIM_Period=arr;
//自动重装载值
-
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
-
-
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
-
-
-
//初始化TIM5输入捕获参数
-
TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1;
//CC1S=01 选择输入端 IC1映射到TI1上
-
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
//上升沿捕获
-
TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
//映射到TI1上
-
TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//配置输入分频,不分频
-
TIM5_ICInitStructure.TIM_ICFilter =
0x00;
//IC1F=0000 配置输入滤波器 不滤波
-
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
-
-
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
//允许更新中断 ,允许CC1IE捕获中断
-
-
TIM_Cmd(TIM5,ENABLE );
//使能定时器5
-
-
-
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=
2;
//抢占优先级
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0;
//子优先级
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//IRQ通道使能
-
NVIC_Init(&NVIC_InitStructure);
//根据指定的参数初始化VIC寄存器、
-
-
-
}
-
//捕获状态(对于32位定时器来说,1us计数器加1,溢出时间:4294秒)
-
//定时器5中断服务程序
-
void TIM5_IRQHandler(void)
-
{
-
-
if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)
//捕获1发生捕获事件
-
{
-
if(edge==RESET)
//上升沿
-
{
-
rising=TIM5->CCR1-rising_last;
-
rising_last=TIM5->CCR1;
-
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);
//CC1P=0 设置为上升沿捕获
-
edge=SET;
-
}
-
else
-
{
-
falling=TIM5->CCR1-rising_last;
-
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);
//CC1P=0 设置为上升沿捕获
-
edge=RESET;
-
}
-
}
-
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);
//清除中断标志位
-
}
-
主程序:
-
while (
1)
-
{
-
uint32_t highsum=
0,wavesum=
0,dutysum=
0,freqsum=
0;
-
LCD_Clear(
0);
-
-
delay_ms(
1);
-
-
sprintf(str,
"rise:%3d\nfall:%d\nfall-rise:%d",rising,falling,falling-rising);
-
LCD_ShowString(
0,
100,str);
-
sprintf(str,
"Freq:%.2f Hz\nDuty:%.3f\n",
90000000.0/rising,(
float)falling/(
float)rising);
//频率、占空比
-
LCD_ShowString(
0,
200,str);
-
delay_ms(
100);
-
}
注意的是,中断程序当中的变量rising,last因为多次修改的缘故,与名称本身含义有所区别,示意如下:
-
/TIM2_CH1->PA5
-
//TIM2_CH2->PB3
-
void TIM2_CH1_Cap_Init(u32 arr,u16 psc)
-
{
-
GPIO_InitTypeDef GPIO_InitStructure;
-
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
NVIC_InitTypeDef NVIC_InitStructure;
-
TIM_ICInitTypeDef TIM_ICInitStructure;
-
-
TIM_DeInit(TIM2);
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//TIM2时钟使能
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB, ENABLE);
//使能PORTA时钟
-
-
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//GPIOA0
-
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//复用功能
-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
//速度100MHz
-
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//推挽复用输出
-
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
//下拉
-
GPIO_Init(GPIOA,&GPIO_InitStructure);
//初始化PA0
-
-
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//GPIOA0
-
GPIO_Init(GPIOB,&GPIO_InitStructure);
//初始化PA0
-
-
GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM2);
//PA0复用位定时器5
-
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_TIM2);
//PA0复用位定时器5
-
-
TIM_TimeBaseStructure.TIM_Prescaler=psc;
//定时器分频
-
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//向上计数模式
-
TIM_TimeBaseStructure.TIM_Period=arr;
//自动重装载值
-
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
-
-
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
-
//初始化TIM2输入捕获参数
-
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
//CC1S=01 选择输入端 IC1映射到TI1上
-
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
//上升沿捕获
-
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
//映射到TI1上
-
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//配置输入分频,不分频
-
TIM_ICInitStructure.TIM_ICFilter =
0x00;
//IC1F=0000 配置输入滤波器 不滤波
-
TIM_ICInit(TIM2, &TIM_ICInitStructure);
-
-
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
//CC1S=01 选择输入端 IC1映射到TI1上
-
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
//上升沿捕获
-
-
TIM_ICInit(TIM2, &TIM_ICInitStructure);
-
-
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2,ENABLE);
//允许更新中断 ,允许CC1IE捕获中断
-
// TIM2_CH1_Cap_DMAInit();
-
TIM_Cmd(TIM2,ENABLE );
//使能定时器5
-
-
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=
0;
//抢占优先级3
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0;
//子优先级3
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//IRQ通道使能
-
NVIC_Init(&NVIC_InitStructure);
//根据指定的参数初始化VIC寄存器、
-
-
}
-
//定时器2中断服务程序(对于32位定时器来说,1us计数器加1,溢出时间:4294秒)
-
void TIM2_IRQHandler(void)
-
{
-
if(TIM2->SR&TIM_FLAG_CC1)
//TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
-
{
-
rising=TIM2->CCR1-rising_last;
-
rising_last=TIM2->CCR1;
-
return;
-
}
-
if(TIM2->SR&TIM_FLAG_CC2)
//TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
-
{
-
falling=TIM2->CCR2-rising_last;
-
return;
-
}
-
TIM2->SR=
0;
-
}
这样,最高频率能够达到约1.1MHz,是一个不小的进步。但是,其根本问题——中断太频繁——仍然存在。
解决思路也是存在的。本质上,我们实际上只需要读取CCR1和CCR2寄存器。而在内存复制过程中,面对大数据量的转移时,我们会想到什么?显然,我们很容易想到——利用DMA。所以,我们使用输入捕获事件触发DMA来搬运寄存器而非触发中断即可,然后将这些数据存放在一个数组当中并循环刷新。这样,我们可以随时来查看数据并计算出频率。
这一方法我曾经尝试过,没有调出来,因为,有一个更好的方法存在。但是理论上这是没有问题的,以供参考我列出如下。
【注意:这段程序无法工作,仅供参考!!!】
-
//TIM2_CH1->DMA1_CHANNEL3_STREAM5
-
u32 val[FILTER_NUM]={
0};
-
void TIM2_CH1_Cap_DMAInit(void)
-
{
-
NVIC_InitTypeDef NVIC_InitStructure;
-
DMA_InitTypeDef DMA_InitStructure;
-
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
//DMA1时钟使能
-
-
DMA_DeInit(DMA1_Stream5);
-
-
while (DMA_GetCmdStatus(DMA1_Stream5) != DISABLE){}
//等待DMA可配置
-
-
/* 配置 DMA Stream */
-
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
//通道选择
-
DMA_InitStructure.DMA_PeripheralBaseAddr = (
uint32_t)&(TIM5->CCR1);
//DMA外设地址
-
DMA_InitStructure.DMA_Memory0BaseAddr = (
uint32_t)val;
//DMA 存储器0地址
-
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
//存储器到外设模式
-
DMA_InitStructure.DMA_BufferSize = FILTER_NUM;
//数据传输量
-
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//外设非增量模式
-
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//存储器增量模式
-
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
//外设数据长度:8位
-
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
//存储器数据长度:8位
-
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// 使用普通模式
-
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
//中等优先级
-
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
-
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
-
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
//存储器突发单次传输
-
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//外设突发单次传输
-
DMA_Init(DMA1_Stream5, &DMA_InitStructure);
//初始化DMA Stream
-
-
TIM_DMAConfig(TIM5,TIM_DMABase_CCR1,TIM_DMABurstLength_16Bytes);
-
TIM_DMACmd(TIM5,TIM_DMA_CC1,ENABLE);
-
//如果需要DMA中断则如下面所示
-
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
//使能TIM中断
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
0x02;
//抢占优先级
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0x02;
//子优先级
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//使能中断
-
NVIC_Init(&NVIC_InitStructure);
-
DMA_ITConfig(DMA1_Stream5,DMA_IT_TC,ENABLE);
-
//开启DMA传输
-
DMA_Cmd(DMA1_Stream5, ENABLE);
-
}
-
void DMA1_Stream5_IRQHandler(void)
-
{
-
DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_TCIF5);
-
}
因此,高频时仍然推荐以下方法。
思路四:使用外部时钟计数器
这种方法是我这几天回答问题时推荐的方法。思路是配置两个定时器,定时器a设置为外部时钟计数器模式,定时器b设置为定时器(比如50ms溢出一次,也可以用软件定时器),然后定时器b中断函数中统计定时器a在这段时间内的增量,简单计算即可。
代码:
-
//TIM7->100ms
-
//TIM2_CH2->PB3
-
void TIM_Cnt_Init(void)
-
{
-
GPIO_InitTypeDef GPIO_InitStructure;
-
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
-
NVIC_InitTypeDef NVIC_InitStructure;
-
-
TIM_DeInit(TIM2);
-
TIM_DeInit(TIM7);
-
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM7,ENABLE);
//TIM2时钟使能
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//使能PORTA时钟
-
//IO
-
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//GPIOA0
-
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//复用功能
-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
//速度100MHz
-
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//推挽复用输出
-
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
//下拉
-
GPIO_Init(GPIOB,&GPIO_InitStructure);
//初始化PA0
-
-
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_TIM2);
//PA0复用位定时器5
-
//TIM2配置
-
TIM_TimeBaseStructure.TIM_Prescaler=
0;
//定时器分频
-
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//向上计数模式
-
TIM_TimeBaseStructure.TIM_Period=
0xFFFFFFFF;
//自动重装载值
-
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
-
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
-
-
TIM_TIxExternalClockConfig(TIM2,TIM_TIxExternalCLK1Source_TI2,TIM_ICPolarity_Rising,
0);
//外部时钟源
-
//TIM7 100ms
-
TIM_TimeBaseStructure.TIM_Prescaler=
18000
-1;
//定时器分频
-
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//向上计数模式
-
TIM_TimeBaseStructure.TIM_Period=
1000
-1;
//自动重装载值
-
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
-
TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
-
//中断
-
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=
0;
//抢占优先级3
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0;
//子优先级3
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//IRQ通道使能
-
NVIC_Init(&NVIC_InitStructure);
//根据指定的参数初始化VIC寄存器、
-
TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
//允许更新中断 ,允许CC1IE捕获中断
-
-
TIM_Cmd(TIM7,ENABLE );
//使能定时器5
-
TIM_Cmd(TIM2,ENABLE );
//使能定时器5
-
}
-
u32 TIM7_LastCnt;
-
//频率为TIM_ExtCntFreq
-
void TIM7_IRQHandler(void)
-
{
-
char str[
32];
-
TIM_ExtCntFreq=(TIM2->CNT-TIM7_LastCnt)*(
1/SAMPLE_PERIOD);
// SAMPLE_PERIOD为采样周期0.1s
-
sprintf(str,
"%3.3f",TIM_ExtCntFreq/
1000.0);
//必须加这一句,莫明其妙
-
TIM7_LastCnt=TIM2->CNT;
-
TIM_ClearITPendingBit(TIM7,TIM_IT_Update);
-
}
当采样数n趋于无穷时,事件A的概率即趋近于统计的频率。所以,当采样数越大,则采样到的高电平占样本总数的频率即趋近于概率——占空比!
-
//ADC1-CH13-PC3
-
//DMA2-CH0-STREAM0
-
#define ADCx ADC1
-
#define ADC_CHANNEL ADC_Channel_13
-
#define ADCx_CLK RCC_APB2Periph_ADC1
-
#define ADCx_CHANNEL_GPIO_CLK RCC_AHB1Periph_GPIOC
-
#define GPIO_PIN GPIO_Pin_3
-
#define GPIO_PORT GPIOC
-
#define DMA_CHANNELx DMA_Channel_0
-
#define DMA_STREAMx DMA2_Stream0
-
#define ADCx_DR_ADDRESS ((uint32_t)&(ADCx->DR))//((uint32_t)0x4001224C)
-
void ADC_DMAInit(void)
-
{
-
ADC_InitTypeDef ADC_InitStructure;
-
ADC_CommonInitTypeDef ADC_CommonInitStructure;
-
DMA_InitTypeDef DMA_InitStructure;
-
GPIO_InitTypeDef GPIO_InitStructure;
-
-
/* Enable ADCx, DMA and GPIO clocks ****************************************/
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
-
RCC_AHB1PeriphClockCmd(ADCx_CHANNEL_GPIO_CLK, ENABLE);
-
RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
-
-
-
/* DMA2 Stream0 channel2 configuration **************************************/
-
DMA_InitStructure.DMA_Channel = DMA_CHANNELx;
-
DMA_InitStructure.DMA_PeripheralBaseAddr = (
uint32_t)ADCx_DR_ADDRESS;
-
DMA_InitStructure.DMA_Memory0BaseAddr = (
uint32_t)&(ADC_DATAPOOL[
0]);
-
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
-
DMA_InitStructure.DMA_BufferSize = ADC_POOLSIZE;
-
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
-
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
-
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
-
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
-
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
-
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
-
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
-
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
-
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
-
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
-
DMA_Init(DMA_STREAMx, &DMA_InitStructure);
-
DMA_Cmd(DMA_STREAMx, ENABLE);
-
-
/* Configure ADC3 Channel7 pin as analog input ******************************/
-
GPIO_InitStructure.GPIO_Pin = GPIO_PIN;
-
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
-
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
-
GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
-
-
/* ADC Common Init **********************************************************/
-
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
-
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
-
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
-
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
-
ADC_CommonInit(&ADC_CommonInitStructure);
-
-
/* ADC3 Init ****************************************************************/
-
ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
-
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
-
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
-
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
-
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
-
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
-
ADC_InitStructure.ADC_NbrOfConversion =
1;
-
ADC_Init(ADCx, &ADC_InitStructure);
-
-
/* ADC3 regular channel7 configuration **************************************/
-
ADC_RegularChannelConfig(ADCx, ADC_CHANNEL,
1, ADC_SampleTime_480Cycles);
-
-
/* Enable DMA request after last transfer (Single-ADC mode) */
-
ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE);
-
-
/* Enable ADC3 DMA */
-
ADC_DMACmd(ADCx, ENABLE);
-
-
/* Enable ADC3 */
-
ADC_Cmd(ADCx, ENABLE);
-
}
-
主程序:
-
for(j=
0;j<ADC_POOLSIZE;j++)
-
{
-
if(ADC_DATAPOOL[j]>
0x01)
-
posicnt++;
-
}
-
duty=
100*posicnt/(
float)(ADC_POOLSIZE)+
0.1f;
//线性补偿