輸入捕獲就是用定時(shí)器檢測引腳上的電平時(shí)間,可以檢測高電平時(shí)間和低電平時(shí)間,然后可以算引腳上信號的頻率和占空比。
基本思路就是利用定時(shí)器的輸入捕獲功能。
定時(shí)器捕獲到高電平或低電平就會進(jìn)入捕獲中斷
例如:
我們要捕獲高電平時(shí)間
0 設(shè)置定時(shí)器計(jì)數(shù)頻率和裝載值,一般設(shè)置1MHz,65535
1 設(shè)置定時(shí)器捕獲為高電平捕獲
2 進(jìn)入捕獲中斷后,獲取CNT計(jì)數(shù)值或CCRx值,定時(shí)器捕獲到電平后會把CNT的值保存到CCRx。
設(shè)置成低電平捕獲。
3 再次進(jìn)入捕獲中斷,獲取CNT計(jì)數(shù)值-上次的CNT值=總高電平時(shí)間。
設(shè)置成高電平捕獲。
4 重復(fù)2-3即可完成下一次捕獲。當(dāng)然還要考慮溢出的情況,代碼里有處理。
下面我寫的一個(gè)實(shí)例:
1 定時(shí)器1 PA8產(chǎn)生PWM信號,可改變占空比,檢測高電平時(shí)間
2 捕獲定時(shí)器是定時(shí)器2,初始化如上例。
3 仿真改變PA8占空比,查看捕獲出的高電平時(shí)間。
實(shí)測:
duty=1000就是高電平維持1000us,
捕獲時(shí)間也是對應(yīng)的1000us,一點(diǎn)誤差都沒有。
代碼如下:
//高電平標(biāo)志
u8 gao_flag=0;
//高電平時(shí)間
u32 gao_timer=0;
//捕獲成功標(biāo)志
u8 buhuo_flag=0;
//溢出次數(shù)
u8 yichu_c=0;
//定時(shí)器 5 中斷服務(wù)程序
extern "C" void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)//還未成功捕獲
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //這個(gè)是溢出中斷
{
//如果已經(jīng)得到高電平了,CNT溢出了
if(gao_flag==1)
{
yichu_c++; //溢出加1
}
}
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕獲 1 發(fā)生捕獲事件
{
if(0==gao_flag&&buhuo_flag==0) //說明之前沒有捕獲到高電平
{
gao_timer=TIM2->CCR1; //獲取高電平時(shí)間
yichu_c=0; //溢出清零
gao_flag=1; //高電平標(biāo)志
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //改成下降沿捕獲
}
//再一次進(jìn)入捕獲中斷說明是捕獲到下降沿了
else
{
if(buhuo_flag==0) //判斷是否捕獲成功了,如果捕獲成功了就不在捕獲了
{
gao_timer=TIM2->CCR1-gao_timer; //獲取捕獲到的高電平時(shí)間
gao_timer+=yichu_c*65536; //加上溢出時(shí)間
TIM2->CNT=0; //計(jì)數(shù)清零
gao_flag=0; //高電平標(biāo)志清零
buhuo_flag=1; //標(biāo)志捕獲成功了
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //改成上沿捕獲
}
}
}
}
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中斷標(biāo)志位
}
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStrue;
TIM_OCInitTypeDef TIM_OCInitStrue;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //使能TIM3和相關(guān)GPIO時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 使能GPIOB時(shí)鐘(LED在BP5引腳),使能AFIO時(shí)鐘(定時(shí)器3通道2需要重映射到BP5引腳)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_8; // TIM_CH2
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP; // 復(fù)用推挽
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz; //設(shè)置最大輸出速度
GPIO_Init(GPIOA,&GPIO_InitStrue); //GPIO端口初始化設(shè)置
//TIM1->CCMR1&=0xF7F7; //關(guān)閉事件更新值
//TIM1->CCMR1|=0x808; //開啟事件更新值
TIM_TimeBaseInitStrue.TIM_Period=50000; //設(shè)置自動重裝載值
TIM_TimeBaseInitStrue.TIM_Prescaler=71; //預(yù)分頻系數(shù)
TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //計(jì)數(shù)器向上溢出
TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //時(shí)鐘的分頻因子,起到了一點(diǎn)點(diǎn)的延時(shí)作用,一般設(shè)為TIM_CKD_DIV1
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrue); //TIM3初始化設(shè)置(設(shè)置PWM的周期)
TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM2; // PWM模式2:CNT>CCR時(shí)輸出有效
TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_Low;// 設(shè)置極性-有效為高電平
TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 輸出使能
TIM_OCInitStrue.TIM_Pulse=100;
TIM_OC1Init(TIM1,&TIM_OCInitStrue); //TIM3的通道2PWM 模式設(shè)置
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //使能預(yù)裝載寄存器
TIM_Cmd(TIM1,ENABLE); //使能TIM3
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM1->CCMR1&=0xF7F7; //關(guān)閉事件更新值
}
void capture_init(u16 arr,u16 psc)
{
TIM_OCInitTypeDef TIM2_OCInitStructure;
TIM_ICInitTypeDef TIM2_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能 TIM2 時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前設(shè)置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉
//初始化定時(shí)器 2 TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)定計(jì)數(shù)器自動重裝值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化 TIMx 的時(shí)間基數(shù)單位
//初始化 TIM2 輸入捕獲參數(shù)
TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //選擇輸入端 IC1 映射到 TI1 上
TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕獲
TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上
TIM2_ICInitStructure.TIM_ICPrescaler = TIM_CKD_DIV1; //配置輸入分頻,不分頻
TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置輸入濾波器 不濾波
TIM_ICInit(TIM2, &TIM2_ICInitStructure);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2 中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級 2 級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //從優(yōu)先級 0 級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化外設(shè) NVIC 寄存器
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM2,ENABLE ); //使能定時(shí)器3
}
u16 duty=1000;
int main(void)
{
serial_init(115200); //串口初始化為 9600
TIM1_PWM_Init(1000,71); //
PAout(1)=1;
capture_init(0XFFFF,72-1); //以 1Mhz 的頻率計(jì)數(shù)
printf("initrn");
while(1)
{
//測試位運(yùn)算和邏輯運(yùn)算的速度
PAout(1)=1;
TIM1->CCR1=duty;
delay_ms(10);
if(buhuo_flag==1)
{
printf("HIGH1:%d us rn",gao_timer); //打印總的高點(diǎn)平時(shí)間
buhuo_flag=0; //重新捕獲
}
PAout(1)=0;
delay_ms(10);
}
}
審核編輯:湯梓紅
-
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120230 -
電平
+關(guān)注
關(guān)注
5文章
360瀏覽量
39883 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3246瀏覽量
114715
發(fā)布評論請先 登錄
相關(guān)推薦
評論