新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32編程之用TIM定時器的輸入捕獲功能紅外遙控解碼

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

        作者: 時間:2016-11-18 來源:網絡 收藏
        1、主程序

        本文引用地址:http://www.104case.com/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顯示鍵值和連按的次數;
        同時串口也輸出同樣的數據。

        日期:2015年7月27日
        地點:湖北工業職業技術學院電子工程
        硬件連接:
        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) //紅外數據輸入腳

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

        extern u8 RmtCnt;//按鍵按下的次數

        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"

        //紅外遙控解碼驅動 代碼

        //紅外遙控初始化
        //設置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; //設定計數器自動重裝值 最大10ms溢出
        TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //預分頻器,1M的計數頻率,1us加1.
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模

        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根據指定的參數初始化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; //先占優先級0級
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

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


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

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

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

        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++; //按鍵次數增加1次
        RmtSta&=0XF0;//清空計時器
        }
        }else if(Dval>4200&&Dval<4700)//4500為標準值4.5ms
        {
        RmtSta|=1<<7;//標記成功接收到了引導碼
        RmtCnt=0;//清除按鍵次數計數器
        }
        }
        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))//按鍵數據錯誤/遙控已經沒有按下了
        {
        RmtSta&=~(1<<6);//清除接收到有效按鍵標識
        RmtCnt=0;//清除按鍵次數計數器
        }
        }
        return sta;
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 靖安县| 乌兰浩特市| 威宁| 中江县| 睢宁县| 呼和浩特市| 贵定县| 桐城市| 益阳市| 伊川县| 乐山市| 册亨县| 楚雄市| 新邵县| 麻城市| 丽水市| 奉贤区| 台湾省| 三亚市| 灯塔市| 志丹县| 五莲县| 文山县| 商水县| 会宁县| 铜梁县| 泰来县| 正安县| 铁力市| 海口市| 玛多县| 齐河县| 腾冲县| 特克斯县| 泰州市| 临澧县| 江口县| 彭州市| 渝中区| 阜阳市| 高尔夫|