出于节约成本又想快速上手的角度出发选择了这款单片机进行开发。但是stm32f030这款单片机的网上资源比其他系列少了很多,输入捕获采集的例程更是极少。楼主使用PB1口进行捕获采集计算频率时发现无法进入捕获中断,经过学习其他历程发现输入捕获时io口初始化很重要,io口需要设置为复用推挽输出才能触发捕获中断(请原谅楼主第一次用捕获中断)。最后实测频率1-1000hz的信号源输出误差在1%以下。部分代码分享如下,后续会上传整个工程方便大家利用。
1.复用功能映射
GPIO_PinAFConfig(GPIOB, GPIO_Pin_1, GPIO_AF_0);//配置PB1为TIM14_CH1
2.IO口初始化
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空状态
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //复用推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
3.定时器初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);//使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
/* 时基配置 */
TIM_TimeBaseStructure.TIM_Period = (0XFFFF) ; //设置计数器
TIM_TimeBaseStructure.TIM_Prescaler = (48-1); //设置预分频的值48,1Mhz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//通道2
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//上升沿捕获
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//映射到TI1上
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置输入分频,不分频TIM_ICPSC_DIV1
TIM_ICInitStruct.TIM_ICFilter = 0;//配置输入滤波器,不滤波
TIM_ICInit(TIM14, &TIM_ICInitStruct);
/* 使能TIM3全局中断*/
NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn ;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM14,TIM_IT_Update,ENABLE);//允许更新中断
TIM_ITConfig(TIM14,TIM_IT_CC1,ENABLE);//允许捕获比较2中断
TIM_ClearITPendingBit(TIM14, TIM_IT_Update);//清除更新中断
TIM_ClearITPendingBit(TIM14, TIM_IT_CC1);//清除捕获中断
TIM_Cmd(TIM14, ENABLE);
4.溢出中断调用函数
void time14_updata_irq(void)//定时器更新中断(计数溢出)中断处理回调函数
{
if((TIM14_CH1_STA&0X80)==0)//还未成功捕获
{
if(TIM14_CH1_STA&0X40)//已经捕获到高电平了
{
if((TIM14_CH1_STA&0X3F)==0X3F)//高电平太长了
{
TIM14_CH1_STA|=0X80; //标记成功捕获了一次
TIM14_CH1_VAL=0XFFFF;
}
else
{
TIM14_CH1_STA++;
}
}
}
}
5.捕获中断调用函数
void TIM14_CH1_CaptureCallback(void)//捕获中断发生时执行
{
if((TIM14_CH1_STA&0X80)==0)//还未成功捕获
{
if(TIM14_CH1_STA&0X40) //捕获到一个下降沿
{
TIM14_CH1_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM14_CH1_VAL=TIM_GetCapture1(TIM14);//获取当前的捕获值.
TIM_OC1NPolarityConfig(TIM14,TIM_ICPolarity_Rising);//配置TIM5通道1上升沿捕获
}
else //还未开始,第一次捕获上升沿
{
TIM14_CH1_STA=0; //清空
TIM14_CH1_VAL=0;
TIM14_CH1_STA|=0X40; //标记捕获到了上升沿
TIM_Cmd(TIM14, DISABLE);//关闭定时器5
TIM_SetCounter(TIM14,0);//清零计数
TIM_OC1NPolarityConfig(TIM14,TIM_ICPolarity_Falling);//定时器5通道1设置为下降沿捕获
TIM_Cmd(TIM14, ENABLE);//使能定时器5
}
}
6.计算频率
if(TIM14_CH1_STA&0X80) //成功捕获到了一次高电平
{
temp=TIM14_CH1_STA&0X3F;
temp*=0XFFFF; //溢出时间总和
temp+=TIM14_CH1_VAL; //得到总的高电平时间
sys_state.sys_temp = temp;
sys_state.frequency = (float)(1000000 / (float)sys_state.sys_temp);
TIM14_CH1_STA=0; //开启下一次捕获
}