你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
yang19961122 提问时间:2018-6-10 21:19 /
这是课程作业……是个小白几乎什么都不懂
要自己写一个红外遥控器实验。
原本采用的是输入捕获的方法

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

举报

4个回答
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_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef  TIM_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_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef  TIM_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捕获中断
}

//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留       
//[4]:标记上升沿是否已经被捕获                                                                  
//[3:0]:溢出计时器
u8         RmtSta=0;          
u16 Dval;
u16 Dval3;    //上升沿时计数器的值
u16 Dval4;                //下降沿时计数器的值
u32 RmtRec=0;        //红外接收到的数据                               
u8  RmtCnt=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官方很多代码可参考:
InputCapture.rar (12.78 KB, 下载次数: 52)

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

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

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版