#include "capture.h"
/**********超声波引脚及定时器5初始化(中断函数)**************/
/**PA0,通过输入捕获,获取输入信号的脉冲宽度(高电平持续时间)****/
void CAPTURE_Init(void)
{
GPIO_InitTypeDef GPIO_IniStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
/****************电机引脚初始化**************/
//(ECHO回响信号输入脚)
GPIO_IniStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_IniStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOC,&GPIO_IniStructure);
//(Trig)输入触发信号脚,持续给10us以上高电平
GPIO_IniStructure.GPIO_Pin= GPIO_Pin_4;
GPIO_IniStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_IniStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_IniStructure);
GPIO_ResetBits(GPIOC,GPIO_Pin_4);
GPIO_ResetBits(GPIOC,GPIO_Pin_5);
/************到这**************/
/****************定时器5初始化*****************/
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitStructure.TIM_Period =5000;//自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler =0;//预分频值
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);//T5,向上计数一次1us,总的计数溢出时间65536us
TIM_Cmd(TIM5,ENABLE);//使能定时器,开始工作
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//输入通道选择
TIM_ICInitStructure.TIM_ICFilter = 0;//固定采样频率采样一次,不起到消除杂波的作用
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//通道上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//CC1通道被配置为输入, IC1映射在TI1上
TIM_ICInitStructure.TIM_ICPrescaler= TIM_ICPSC_DIV1;//一次上升沿(下降沿)即触发捕获
TIM_PrescalerConfig(TIM5,719,TIM_PSCReloadMode_Immediate);//?????72MHz/(719+1)=100000
TIM_ARRPreloadConfig(TIM5, DISABLE);//??
TIM_ICInit(TIM5,&TIM_ICInitStructure);
TIM_ITConfig(TIM5,TIM_IT_CC1|TIM_IT_Update,ENABLE);//中触发类型:更新(溢出)、捕获/比较
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);//开中断,设置中断触发类型
}
//2个全局变量
u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
//定时器5中断服务程序
/***********************************************************************
IC通道初始化设置为上升沿触发捕获,设置捕获值为0,设置计数器值也为0 ,IC通道极性选择为下降沿
下一次下降沿触发捕获,将计数器的值赋给捕获值。
但要注意一个问题:单次高电平持续时间可能超过一次溢出时间,所以要考虑定时器溢出次数!!
中断函数作用:模拟一个软件8位寄存器,低6位存储溢出次数。
bit7 bit6 bit5-0
捕获标志 捕获高电平标志 捕获高电平后定时器溢出次数
************************************************************************/
//定时器5中断服务程序
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{ //最大测量范围4m对应Echo输入23.53ms的高电平,单次TIM溢出需要65.536ms
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
{
if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM5CH1_CAPTURE_STA|=0X80;//强制标记成功捕获了一次
TIM5CH1_CAPTURE_VAL=0XFFFF;
}else TIM5CH1_CAPTURE_STA++;
}
}
if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
{
if(TIM5CH1_CAPTURE_STA&0X40)//前一次捕获了上升沿,此次捕获到一个下降沿
{
TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM5CH1_CAPTURE_STA=0; //清空
TIM5CH1_CAPTURE_VAL=0;
TIM_SetCounter(TIM5,0);//定时器从0开始重新计数
TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
}
#include "ultrasonic.h"
#include "delay.h"
#include "capture.h"
#include "math.h"
/***********此为超声波算法****************/
#define module_interval 25
//extern u8 TIM5CH1_CAPTURE_STA;
//extern u16 TIM4CH1_CAPTURE_VAL;
int overcount=0;
int Get_distance(void)
{
int distance=0,sum_distance=0;
u16 TIM=0;
u8 i=0;
while(i!=5)
{
GPIO_SetBits(GPIOC,GPIO_Pin_4);
delay_us(20);
GPIO_ResetBits(GPIOC,GPIO_Pin_4);
TIM_Cmd(TIM5, ENABLE);
while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) && overcount==0);
TIM5->CNT=0;
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) && overcount==0);
TIM_Cmd(TIM5, DISABLE);
i++;
if(overcount!=0)
{
overcount=0;
return 0.0;
}
TIM=TIM_GetCounter(TIM5);
distance=(int)sqrt((TIM/10.0*17)*(TIM/10.0*17)-module_interval*module_interval/4.0)+12.0; //12.0?????//?????????????
sum_distance=sum_distance+distance;
}
distance=sum_distance/5;
return distance;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
我全部定时器都用光了,都可以在一个工程里使用,是不是哪里配置出问题了,比如TIM4捕获管脚IO初始化不对,TIM5漏掉什么关键性配置等等,仔细检查一下
一周热门 更多>