新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32編程之用TIM定時器的輸入捕獲功能紅外遙控解碼

STM32編程之用TIM定時器的輸入捕獲功能紅外遙控解碼

作者: 時間:2016-11-18 來源:網(wǎng)絡(luò) 收藏
1、主程序

本文引用地址:http://m.butianyuan.cn/article/201611/315581.htm

#include "sys.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "delay.h"
#include "remote.h"
#include "stm32f10x_tim.h"
/*
程序功能:用STM32的定時器輸入捕獲功能進行紅外解碼。
當按下紅外遙控器的按鍵時,LCD顯示鍵值和連按的次數(shù);
同時串口也輸出同樣的數(shù)據(jù)。

日期:2015年7月27日
地點:湖北工業(yè)職業(yè)技術(shù)學(xué)院電子工程
硬件連接:
PA1---TIM5_CH2;
*/


int main(void)
{
u8 i=0;
delay_init();
NVIC_Configuration();
uart_init(9600);
LED_Init();
LCD_Init();
Remote_Init();
LCD_Clear(RED);
POINT_COLOR=BLUE;
LCD_ShowString(30,60,200,16,16,"IRD TEST!");
LCD_ShowString(30,80,200,16,16,"PLEASE PRESS!");
LCD_ShowString(30,100,200,16,16,"KEYNUM IS : ");
LCD_ShowString(30,120,200,16,16,"KEYCOUNT IS : ");

while(1)
{
if(Remote_Scan()!=0)
{
LCD_ShowNum(118,100,Remote_Scan(),4,16);
LCD_ShowNum(134,120,RmtCnt,4,16);
printf("press keynum:%d n",Remote_Scan());
printf("press keycount:%d n",RmtCnt);

}
delay_ms(10);
i++;
if(i>25)
{i=0;LED0=~LED0;}
}
}

2、頭文件:

#ifndef __RED_H
#define __RED_H
#include "sys.h"


#define RDATA PAin(1) //紅外數(shù)據(jù)輸入腳

//紅外遙控識別碼(ID),每款遙控器的該值基本都不一樣,但也有一樣的.
//我們選用的遙控器識別碼為0
#define REMOTE_ID 0

extern u8 RmtCnt;//按鍵按下的次數(shù)

void Remote_Init(void); //紅外傳感器接收頭引腳初始化
u8 Remote_Scan(void);
#endif

3、源文件

#include "remote.h"
#include "delay.h"
#include "usart.h"
#include "stm32f10x_conf.h"
#include "stm32f10x_tim.h"

//紅外遙控解碼驅(qū)動 代碼

//紅外遙控初始化
//設(shè)置IO以及定時器4的輸入捕獲
void Remote_Init(void)
{

GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PORTB時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//TIM5 時鐘使能

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //PA1 輸入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //上拉輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1);//初始化GPIOA1


TIM_TimeBaseStructure.TIM_Period = 10000; //設(shè)定計數(shù)器自動重裝值 最大10ms溢出
TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //預(yù)分頻器,1M的計數(shù)頻率,1us加1.
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數(shù)模

TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx

TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; // 選擇輸入端 IC2映射到TI5上
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 = 0x03;//IC4F=0011 配置輸入濾波器 8個定時器時鐘周期濾波
TIM_ICInit(TIM5, &TIM_ICInitStructure);//初始化定時器輸入捕獲通道

TIM_Cmd(TIM5,ENABLE ); //使能定時器5


NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM5中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占優(yōu)先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器

TIM_ITConfig( TIM5,TIM_IT_Update|TIM_IT_CC2,ENABLE);//允許更新中斷 ,允許CC2IE捕獲中斷
}


//遙控器接收狀態(tài)
//[7]:收到了引導(dǎo)碼標志
//[6]:得到了一個按鍵的所有信息
//[5]:保留
//[4]:標記上升沿是否已經(jīng)被捕獲
//[3:0]:溢出計時器
u8 RmtSta=0;
u16 Dval;//下降沿時計數(shù)器的值
u32 RmtRec=0;//紅外接收到的數(shù)據(jù)
u8 RmtCnt=0;//按鍵按下的次數(shù)
//定時器5中斷服務(wù)程序
void TIM5_IRQHandler(void)
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET)
{
if(RmtSta&0x80)//上次有數(shù)據(jù)被接收到了
{
RmtSta&=~0X10;//取消上升沿已經(jīng)被捕獲標記
if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//標記已經(jīng)完成一次按鍵的鍵值信息采集
if((RmtSta&0X0F)<14)RmtSta++;
else
{
RmtSta&=~(1<<7);//清空引導(dǎo)標識
RmtSta&=0XF0;//清空計數(shù)器
}
}
}
if(TIM_GetITStatus(TIM5,TIM_IT_CC2)!=RESET)
{
if(RDATA)//上升沿捕獲
{

TIM_OC2PolarityConfig(TIM5,TIM_ICPolarity_Falling);//CC1P=1 設(shè)置為下降沿捕獲
TIM_SetCounter(TIM5,0); //清空定時器值
RmtSta|=0X10;//標記上升沿已經(jīng)被捕獲
}else //下降沿捕獲
{
Dval=TIM_GetCapture2(TIM5);//讀取CCR1也可以清CC1IF標志位
TIM_OC2PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC4P=0設(shè)置為上升沿捕獲

if(RmtSta&0X10)//完成一次高電平捕獲
{
if(RmtSta&0X80)//接收到了引導(dǎo)碼
{

if(Dval>300&&Dval<800)//560為標準值,560us
{
RmtRec<<=1;//左移一位.
RmtRec|=0;//接收到0
}else if(Dval>1400&&Dval<1800)//1680為標準值,1680us
{
RmtRec<<=1;//左移一位.
RmtRec|=1;//接收到1
}else if(Dval>2200&&Dval<2600)//得到按鍵鍵值增加的信息 2500為標準值2.5ms
{
RmtCnt++; //按鍵次數(shù)增加1次
RmtSta&=0XF0;//清空計時器
}
}else if(Dval>4200&&Dval<4700)//4500為標準值4.5ms
{
RmtSta|=1<<7;//標記成功接收到了引導(dǎo)碼
RmtCnt=0;//清除按鍵次數(shù)計數(shù)器
}
}
RmtSta&=~(1<<4);
}
}
TIM_ClearFlag(TIM5,TIM_IT_Update|TIM_IT_CC2);
}

//處理紅外鍵盤
//返回值:
// 0,沒有任何按鍵按下
//其他,按下的按鍵鍵值.
u8 Remote_Scan(void)
{
u8 sta=0;
u8 t1,t2;
if(RmtSta&(1<<6))//得到一個按鍵的所有信息了
{
t1=RmtRec>>24;//得到地址碼
t2=(RmtRec>>16)&0xff;//得到地址反碼
if((t1==(u8)~t2)&&t1==REMOTE_ID)//檢驗遙控識別碼(ID)及地址
{
t1=RmtRec>>8;
t2=RmtRec;
if(t1==(u8)~t2)sta=t1;//鍵值正確
}
if((sta==0)||((RmtSta&0X80)==0))//按鍵數(shù)據(jù)錯誤/遙控已經(jīng)沒有按下了
{
RmtSta&=~(1<<6);//清除接收到有效按鍵標識
RmtCnt=0;//清除按鍵次數(shù)計數(shù)器
}
}
return sta;
}



評論


技術(shù)專區(qū)

關(guān)閉