测量频率和占空比的几种方法
转: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;//线性补偿
测量频率和占空比的几种方法相关推荐
- 使用 STM32 测量频率和占空比的几种方法
以前在本科时写的教程文章,主要是把自己当时参赛的方法拿出来做了个总结. 想当年天天水论坛好为人师,现在已经全面转向计算机视觉方向了,颇为感慨.不过,自己的理性选择,个中得失早就意料之中.塞翁失马,焉知 ...
- Arduino产生PWM的3种方法
Arduino产生PWM的3种方法! PWM是个啥? 有人翻译成:脉冲宽度调制 PWM 是用占空比不同的方波 ...
- arduino利用三种方法产生pwm波使用l298n驱动12v小车电机(附电路连接图和pwm详解)
前段时间参加硕士复试,有一道题是pwm是什么,如何产生pwm,录取成功后接下来在这里写一下吧! 1.脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法,由于计算机不能输出模拟电压,只能输出0 ...
- spring boot项目 中止运行 最常用的几种方法
spring boot项目 中止运行 最常用的几种方法: 1. 调用接口,停止应用上下文 @RestController public class ShutdownController impleme ...
- 设置select下拉框不可修改的→“四”←种方法
设置select下拉框为不可修改的几种方法: 因为select的特殊性,导致它不能像input表单一样简单地设置一个readonly来限制修改,所以,我们需要进行别的操作! 1.为下拉框添加样式,可以 ...
- 用python下载文件的若干种方法汇总
压缩文件可以直接放到下载器里面下载的 you-get 连接 下载任意文件 重点 用python下载文件的若干种方法汇总 写文章 用python下载文件的若干种方法汇总 zhangqibot发表于Met ...
- Python两个字典键同值相加的几种方法
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/Jerry_1126/article/d ...
- VS中C#读取app.config数据库配置字符串的三种方法(转)
关于VS2008或VS2005中数据库配置字符串的三种取法 VS2008建立Form程序时,如果添加数据源会在配置文件 app.config中自动写入连接字符串,这个字符串将会在你利用DataSet, ...
- 在PHP中使用全局变量的几种方法
简介 即使开发一个新的大型PHP程序,你也不可避免的要使用到全局数据,因为有些数据是需要用到你的代码的不同部分的.一些常见的全局数据有:程序设定类.数据库连接类.用户资料等等.有很多方法能够使这些数据 ...
最新文章
- 微信小程序直播开启公测了,与平台直播有何不同?小程序直播如何搭建
- Oracle 11g Dataguard 物理备库配置(一)之Duplicate配置
- 分布式文件系统—HDFS—核心设计
- AJPFX关于构造器的总结
- 【C++基础】异常匹配与内建异常类
- Spring+SpringMVC+Mybatis 多数据源整合
- 企业微信怎么删除好友 企业微信如何删除成员
- MySQL ALTER命令
- kali linux虚拟机密码,[Linux]安装kali虚拟机后忘记root密码
- 概要设计说明书任务分配
- mysql中XtraBackup备份工作机制
- UE5 预览版载具模板工程车不能移动的问题
- 【路径规划】基于改进粒子群实现机器人栅格地图路径规划
- 2 简单使用原形工具Axure RP
- 【剑指 Offe】剑指 Offer 17. 打印从1到最大的n位数
- 计算机知识动画小学,电脑动画
- 整车nvh培训入门 仿真 ,基于Hyperworks 掌握思路 细节
- Liquibase中利用changelog增加表字段
- 总线(四)Modbus总线 协议
- Python 布尔类型 bool
热门文章
- 触发器(四、执行顺序控制)
- 计算机考研和就业pk,考研PK就业:提高自身竞争力比文凭更重要
- 3dvary灯光材质为什么不亮_3dmax灯光教程灯光打出来太假?不真实?杂点?曝光?原因都在这儿呢...
- 2018年天津大学夏令营机试第一题
- php开发俄罗斯方块,HTML5+JS实现俄罗斯方块原理及具体步骤_html5教程技巧
- Redis 内存分析神器
- (unity)新手接入Facebook登录,分享以及google登录,Android,IOS,OC接入篇
- 【Avro二】Avro RPC框架
- iOS WKWebView的使用以及遇到的问题
- 【Javaweb】TCP原理(三次握手四次挥手)