# 使用 STM32 测量频率和占空比的几种方法

4 篇文章 1 订阅

【教程】使用STM32测量频率和占空比的几种方法（申请置酷！）

PS: 由于我们当时的题目除了测量频率之外，更麻烦的是测量占空比。而这两个的测量方法联系比较紧密，所以也一并把测量占空比的方法写出来。因为时间有限，所以并不能把所有思路都一一测试，只是写在下面作为参考，敬请谅解。

1 ）测量脉冲信号频率 f_O ，频率范围为 10Hz 2MHz ，测量误差的绝对值不大于 0.1% 。（ 15 分）
2 ）测量脉冲信号占空比 D ，测量范围为 10 ％～ 90 ％，测量误差的绝对值不大于 2% 。（ 15 分）

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);
}

freq=Frequency*2.2118-47.05;

//定时器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);
}

1.           使用 2个通道，一个只测量上升沿，另一个只测量下降沿。这样可以减少切换触发边沿的延迟，缺点是多用了一个 IO口。
2.           使用寄存器，简化程序

/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;
}

【注意：这段程序无法工作，仅供参考！！！】

//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_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);
}

@xkwy 大神在回复中提出了几个改进意见，列出如下：
1. 可以设定仅有通道 2 进行下降沿捕获并触发中断，而通道 1 捕获上升沿不触发中断。在中断函数当中，一次读取 CCR1 CCR2 。这样可以节省大量时间。
2. 可以先进行一次测量，根据测量值改变预分频值 PSC ，从而提高精度
3. 间隔采样。例如每 100ms 采样 10ms.

//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);
}

1. 无法测量占空比，高频的占空比测量方法见下文。

2. 在频率较低的情况下，测量精度不如思路 3 （因为测量周期为 100ms ，此时如果脉冲周期是 200ms ……）。

3. 输入幅值必须超过 3V 。如果不够或者超出，需要加入前置放大器。

//ADC1-CH13-PC3
//DMA2-CH0-STREAM0
#define GPIO_PIN                 GPIO_Pin_3
#define GPIO_PORT                GPIOC
#define DMA_CHANNELx             DMA_Channel_0
#define DMA_STREAMx              DMA2_Stream0
{
DMA_InitTypeDef       DMA_InitStructure;
GPIO_InitTypeDef      GPIO_InitStructure;

/* Enable ADCx, DMA and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

/* DMA2 Stream0 channel2 configuration **************************************/
DMA_InitStructure.DMA_Channel = DMA_CHANNELx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
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);

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);

/* ADC3 regular channel7 configuration **************************************/

/* Enable DMA request after last transfer (Single-ADC mode) */

}

{
posicnt++;
}
duty=100*posicnt/(float)(ADC_POOLSIZE)+0.1f;//线性补偿

1. 精度低：实测 2MHz 下误差约 1.3% ，低频时无法统计（比如，频率 10Hz ，而 ADC 采样时间 50ms 。这时如果采样时间中刚好全是高电平，占空比为 1 ……）。

2. 内存占用大：数据池大小为 65536 ，占用了 64KB 内存

3. 有响应延迟：测量出来的是“平均占空比”而非“瞬时占空比”。由于我测试时使用的是波形发生器，输出波形相当稳定（ 1W+ 的价格毕竟是有它的道理的……），实际应用当中一般不能够达到这样的水平，势必带来响应延迟（准确说应该是采样系统积分惯性越大）。

4. 幅值过低（ 0.3V ）无法测量，过高则超过 ADC 允许最大值。所以必须视情况使用不同的前置放大器。

PWM 输入：全硬件完成， CPU 负载小，编写容易。缺点是不稳定，误差大。

ADC 采样频率测量法：难以测量频率，高频下对占空比、上升时间有可以接受的测量精度（ 2MHz 下约 1.3% ），低频下无法测量。幅值 0.3~3.3V ，加入前置放大则幅值随意。

12-07 1万+
02-03 7528
01-13 4万+
10-26 1万+
05-09 842
10-23 5014
04-02 2万+
04-26 1731

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

yyx112358

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。