打印

关于红外线问题

[复制链接]
3115|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
youdaping777|  楼主 | 2013-8-23 21:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人用的是stm32f103rct6,管脚是gpio pc12接红外线,主要问题是捕获到红外线数据,也就是时序,捕获不到数据,解析不了数据,我用示波器测试红外线波形是正常的,硬件没问题,不知道什么原因。下面是程序,请大家帮忙看一下,程序是正点原子方案,看一下程序有什么问题:

#include "remote.h"
#include "delay.h"
#include "usart.h"                                                                  
//////////////////////////////////////////////////////////////////////////////////
u16  tmp = 0;

//红外遥控初始化
//设置IO以及定时器4的输入捕获
void Remote_Init(void)                              
{                                                                            
        RCC->APB1ENR|=1<<2;           //TIM4 时钟使能
        RCC->APB2ENR|=1<<4;            //使能PORTC时钟

        GPIOC->CRH&=0XFFF0FFFF;        //PC12 输入  
        GPIOC->CRH|=0X00080000;        //上拉输入     
        GPIOC->ODR|=1<<12;                //PC12 上拉
          
        TIM4->ARR=10000;                  //设定计数器自动重装值 最大10ms溢出  
        //TIM4->ARR=250-1;                  //设定计数器自动重装值 最大250us溢出
        TIM4->PSC=71;                          //预分频器,1M的计数频率,1us加1.         
        //TIM4->ARR=0xffff;                  //设定计数器自动重装值 最大10ms溢出  
        //TIM4->PSC=(72*2-1);                          //预分频器,1M的计数频率,1us加1.       

        TIM4->CCMR2|=1<<8;                //CC4S=01         选择输入端 IC4映射到TI4上
        TIM4->CCMR2|=3<<12;          //IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波
        //TIM4->CCMR2|=4<<12;          //IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波
        TIM4->CCMR2|=0<<10;          //IC4PS=00         配置输入分频,不分频

        TIM4->CCER|=0<<13;                 //CC4P=0        上升沿捕获
        //TIM4->CCER|=0x0002;               //下升沿捕获
        TIM4->CCER|=1<<12;                 //CC4E=1         允许捕获计数器的值到捕获寄存器中
        TIM4->DIER|=1<<4;           //允许CC4IE捕获中断                               
        TIM4->DIER|=1<<0;           //允许更新中断                               
        TIM4->CR1|=0x01;            //使能定时器4
          MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//抢占1,子优先级3,组2                                                                         
}

//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留       
//[4]:标记上升沿是否已经被捕获                                                                  
//[3:0]:溢出计时器
u8         RmtSta=0;                    
u16 Dval;                //下降沿时计数器的值
u32 RmtRec=0;        //红外接收到的数据                               
u8  RmtCnt=0;        //按键按下的次数
          
//定时器2中断服务程序         
void TIM4_IRQHandler(void)
{        
                         
        u16 tsr;
        tsr=TIM4->SR;
        tmp = tsr;
        //printf("tmp111... = %x\r\n",tmp);
        if(tsr&0x01)//溢出
        {
            //printf("tmp000\r\n");
                if(RmtSta&0x80)//上次有数据被接收到了
                {       
                    //printf("tmp111\r\n");
                        RmtSta&=~0X10;                                                //取消上升沿已经被捕获标记
                        if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
                        if((RmtSta&0X0F)<14)RmtSta++;
                        else
                        {
                                RmtSta&=~(1<<7);//清空引导标识
                                RmtSta&=0XF0;        //清空计数器       
                        }                                                                   
                }                                                            
        }
        if(tsr&0x10)//CC4IE中断
        {         
            //printf("tmp2222\r\n");
                if(RDATA)//上升沿捕获
                {
                    //printf("tmp3333\r\n");
                          TIM4->CCER|=1<<13;                                 //CC4P=1        设置为下降沿捕获
                        TIM4->CNT=0;                                        //清空定时器值
                        RmtSta|=0X10;                                        //标记上升沿已经被捕获
                }else //下降沿捕获
                {
                    //printf("tmp444\r\n");
                        Dval=TIM4->CCR4;                                //读取CCR1也可以清CC1IF标志位
                          TIM4->CCER&=~(1<<13);                        //CC4P=0        设置为上升沿捕获
                        if(RmtSta&0X10)                                        //完成一次高电平捕获
                        {
                            //printf("tmp5555\r\n");
                                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);
                }                                                                                                            
        }
        //printf("tmp666\r\n");
        TIM4->SR=0;//清除中断标志位             
}

//处理红外键盘
//返回值:
//         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;
}

//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组                   
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
{
        u32 temp,temp1;          
        temp1=(~NVIC_Group)&0x07;//取后三位
        temp1<<=8;
        temp=SCB->AIRCR;  //读取先前的设置
        temp&=0X0000F8FF; //清空先前分组
        temp|=0X05FA0000; //写入钥匙
        temp|=temp1;          
        SCB->AIRCR=temp;  //设置分组                                                        
}
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority       :响应优先级
//NVIC_Channel           :中断编号
//NVIC_Group             :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先          
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)         
{
        u32 temp;       
        u8 IPRADDR=NVIC_Channel/4;  //每组只能存4个,得到组地址
        u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
        IPROFFSET=IPROFFSET*8+4;    //得到偏移的确切位置
        MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
        temp=NVIC_PreemptionPriority<<(4-NVIC_Group);          
        temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
        temp&=0xf;//取低四位

        if(NVIC_Channel<32)NVIC->ISER[0]|=1<<NVIC_Channel;//使能中断位(要清除的话,相反操作就OK)
        else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   
        NVIC->IPR[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级和抢断优先级                                                           
}

//外部中断配置函数
//只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
//参数:
//GPIOx:0~6,代表GPIOA~G
//BITx:需要使能的位;
//TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发
//该函数一次只能配置1个IO口,多个IO口,需多次调用
//该函数会自动开启对应中断,以及屏蔽线               
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
{
        u8 EXTADDR;
        u8 EXTOFFSET;
        EXTADDR=BITx/4;//得到中断寄存器组的编号
        EXTOFFSET=(BITx%4)*4;
                                                  
        RCC->APB2ENR|=0x01;//使能io复用时钟

        AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);//清除原来设置!!!
        AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;//EXTI.BITx映射到GPIOx.BITx
       
        //自动设置
        EXTI->IMR|=1<<BITx;//  开启line BITx上的中断
        //EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
        if(TRIM&0x01)EXTI->FTSR|=1<<BITx;//line BITx上事件下降沿触发
        if(TRIM&0x02)EXTI->RTSR|=1<<BITx;//line BITx上事件上升降沿触发
}           
//不能在这里执行所有外设复位!否则至少引起串口不工作.                    
//把所有时钟寄存器复位                  
void MYRCC_DeInit(void)
{       
        RCC->APB1RSTR = 0x00000000;//复位结束                         
        RCC->APB2RSTR = 0x00000000;
          
          RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.          
          RCC->APB2ENR = 0x00000000; //外设时钟关闭.                          
          RCC->APB1ENR = 0x00000000;   
        RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                  
        RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]                                         
        RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
        RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
        RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
        RCC->CIR = 0x00000000;     //关闭所有中断                 
        //配置向量表                                  
#ifdef  VECT_TAB_RAM
        MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else   
        MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
}































沙发
youdaping777|  楼主 | 2013-8-26 08:43 | 只看该作者
兄弟们,帮忙呀

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

18

帖子

0

粉丝