yang19961122 发表于 2018-6-10 21:19:35

用两个定时器测量脉冲宽度

这是课程作业……是个小白几乎什么都不懂
要自己写一个红外遥控器实验。
原本采用的是输入捕获的方法

现在我想了两种方法
一种是通过外部中断测量 先把外部中断设置为上升沿触发,然后记录下定时器的时间,再设置为下降沿触发,记录下定时器时间,两者之差就是脉冲宽度。然后再套用原本的方法就ok
一种是用两个定时器,一个是上升沿触发,一个是下降沿触发,测出脉冲宽度再套用原本的方法。
结果这两种我都搞不成……
希望各位高手看一下 到底哪里有问题 代码是没有错误,但没法像标准库里那样按键有反应

yang19961122 发表于 2018-6-10 21:22:05

void Remote_Init(void)                              
{
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能PORTB时钟

       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                               //PB9 输入
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;                 //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_9);        //初始化GPIOB.9
       

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//先占优先级1级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器       
       
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//TIM4中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//先占优先级1级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;//从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器       
       
       
       
}

void TIM3_Configuration(void)
{
        TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
        TIM_ICInitTypeDefTIM_ICInitStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);        //TIM3 时钟使能
        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(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx

TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;// 选择输入端 IC3映射到TI3上
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;//IC3F=0011 配置输入滤波器 8个定时器时钟周期滤波
TIM_ICInit(TIM3, &TIM_ICInitStructure);//初始化定时器输入捕获通道
TIM_Cmd(TIM3,ENABLE );         //使能定时器3
        TIM_ITConfig( TIM3,TIM_IT_Update|TIM_IT_CC3,ENABLE);//允许更新中断 ,允许CC3IE捕获中断
}
void TIM4_Configuration(void)
{
        TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
        TIM_ICInitTypeDefTIM_ICInitStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);        //TIM4 时钟使能
        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(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx

TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;// 选择输入端 IC4映射到TI4上
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;        //下降沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;       //配置输入分频,不分频
TIM_ICInitStructure.TIM_ICFilter = 0x03;//IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波
TIM_ICInit(TIM4, &TIM_ICInitStructure);//初始化定时器输入捕获通道
TIM_Cmd(TIM4,ENABLE );         //使能定时器4
        TIM_ITConfig( TIM4,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断 ,允许CC4IE捕获中断
}

//遥控器接收状态
//:收到了引导码标志
//:得到了一个按键的所有信息
//:保留       
//:标记上升沿是否已经被捕获                                                                  
//:溢出计时器
u8         RmtSta=0;          
u16 Dval;
u16 Dval3;    //上升沿时计数器的值
u16 Dval4;                //下降沿时计数器的值
u32 RmtRec=0;        //红外接收到的数据                             
u8RmtCnt=0;        //按键按下的次数       


//定时器3中断服务程序       
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_CC3)!=RESET)
        {
                if(RDATA)//上升沿捕获
                {
                        RmtSta|=0X10;                                                        //标记上升沿已经被捕获
                        Dval3=TIM_GetCapture3(TIM3);                                        //读取CCR3也可以清CC3IF标志位
                  TIM_SetCounter(TIM3,0);                                                        //清空定时器值
                }
        }
                TIM_ClearITPendingBit(TIM3,TIM_IT_Update|TIM_IT_CC3);
}

//定时器4中断服务程序       
void TIM4_IRQHandler(void)
{                          
        if(TIM_GetITStatus(TIM4,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(TIM4,TIM_IT_CC4)!=RESET)
        {          
                if(!RDATA)//下降沿捕获
                {
                        Dval4=TIM_GetCapture4(TIM4);                                        //读取CCR4也可以清CC4IF标志位
                        Dval=Dval4-Dval3;
                        TIM_SetCounter(TIM4,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_ClearITPendingBit(TIM4,TIM_IT_Update|TIM_IT_CC4);                 
}

wenyangzeng 发表于 2018-6-11 09:36:13

本帖最后由 wenyangzeng 于 2018-6-11 09:42 编辑

用一个定时器测量脉冲上下沿就够了。ST官方很多代码可参考:

yang19961122 发表于 2018-6-11 14:44:35

wenyangzeng 发表于 2018-6-11 09:36
用一个定时器测量脉冲上下沿就够了。ST官方很多代码可参考:

谢谢了
我有正点原子的代码的
就是需要把代码改编一下所以才想了那两种方法
只是我水平太低了只能拿正点原子的改一下顺序、函数这种
改完了发现无法实现才提问的

yueming40889243 发表于 2019-6-17 17:25:30

yang19961122 发表于 2018-6-11 14:44
谢谢了
我有正点原子的代码的
就是需要把代码改编一下所以才想了那两种方法


你现在完成了吗? 我现在准备用一个基本的定时器来测脉宽 需要探讨一下方便吗 我的QQ 408892434
页: [1]
查看完整版本: 用两个定时器测量脉冲宽度