OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2536|回复: 18

如果准确获取按键按下的时长

[复制链接]

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
发表于 2019-12-19 11:24:31 | 显示全部楼层 |阅读模式
1金钱
如果在每次按键按下时开始计时,可以获取按键按下时的总时长

最佳答案

查看完整内容[请看2#楼]

可以使用输入捕获功能,获取按键I/O口高/低电平持续时间,也就是按键按下的时长。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2018-11-30
在线时间
26 小时
发表于 2019-12-19 11:24:32 | 显示全部楼层
可以使用输入捕获功能,获取按键I/O口高/低电平持续时间,也就是按键按下的时长。
回复

使用道具 举报

6

主题

1127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1656
金钱
1656
注册时间
2019-8-15
在线时间
102 小时
发表于 2019-12-19 14:05:54 | 显示全部楼层
帮顶                                             
成功没有捷径
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-19 18:26:18 | 显示全部楼层
春晓LCX 发表于 2019-12-19 11:24
可以使用输入捕获功能,获取按键I/O口高/低电平持续时间,也就是按键按下的时长。

我想通过捕获定时器通道输出给电机的高电平时间也可以用输入捕获吗
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-19 18:45:39 | 显示全部楼层
本帖最后由 htao 于 2019-12-19 18:47 编辑

可以按键中断里获取上升沿下降沿的时间间隔判断,就不用再加定时器了。
比如高电平有效,那上升沿的时候取一下当前运行时间,再获取到下降沿时进行减法就行了
茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-19 19:45:25 | 显示全部楼层
htao 发表于 2019-12-19 18:45
可以按键中断里获取上升沿下降沿的时间间隔判断,就不用再加定时器了。
比如高电平有效,那上升沿的时候取 ...

感觉有点道理,可是如何获取运行时间呢?有相关资料可以参考一下吗
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-20 09:07:47 | 显示全部楼层
YANGSCAU 发表于 2019-12-19 19:45
感觉有点道理,可是如何获取运行时间呢?有相关资料可以参考一下吗

如果裸机跑,可以参考我分享的激光雷达的例程里面http://www.openedv.com/forum.php ... d=303978&extra=

在delay.c 文件里修改了delay_init初始化,开启了滴答时钟中断。
定义了一个全局变量my_system_time作为系统运行时间,在SysTick_Handler()中断累加变量,通过Get_system_time()获取运行时间。

如果是ucos系统,有个OSTimeGet(&err)函数,获取当前运行时间。其他系统也有类似函数。
茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-20 15:04:05 | 显示全部楼层
htao 发表于 2019-12-20 09:07
如果裸机跑,可以参考我分享的激光雷达的例程里面http://www.openedv.com/forum.php?mod=viewthread&tid= ...

谢谢大神!!!我想问一下Get_system_time()获取的运行时间是几点几分几秒这样形式的吗,我想通过获得IO口高低电平的时间差值然后转换成us要怎么实现呢?
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-20 16:30:34 | 显示全部楼层
本帖最后由 htao 于 2019-12-20 16:31 编辑
YANGSCAU 发表于 2019-12-20 15:04
谢谢大神!!!我想问一下Get_system_time()获取的运行时间是几点几分几秒这样形式的吗,我想通过获得I ...

获取的是代码运行时间 ms ,从代码开始运行计算, //2^64/1000/3600/24/365=584942417年会复位。

想要把ms换成us可以修改delay_init里面
SysTick->LOAD=fac_us*1000-1;                                                //每1/1000s中断一次         *1000

这句1000us进入一次中断,但是换成us进中断太频繁会有误差,建议还是ms级。
茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-20 19:18:00 | 显示全部楼层
htao 发表于 2019-12-20 16:30
获取的是代码运行时间 ms ,从代码开始运行计算, //2^64/1000/3600/24/365=584942417年会复位。

想要 ...

我写了一个函数 通过获取两次pwm端口的高低电平时的运行事件来获取pwm端口高电平的时间

可是很像有问题,可以麻烦您给我看看吗 其中pwm3就是对应的端口,pwm3_t是端口高低电平标志位(为了防止重复获取运行时间),在上升沿时获取一次运行时间然后下降沿获取一次时间,两次时间相间获得一次高电平的时间time11,time1为总的高电平时间。

u64 Get_time1(void)
{
        if(pwm3==1&&pwm3_t==0)
        {
                time1_start=Get_system_time();
                pwm3_t=1;               
        }
        else if(pwm3==0&&pwm3_t==1)
        {
                time1_over=Get_system_time();
                pwm3_t=0;
        }
        time11=time1_over-time1_start;
        time1 = time1 + time11;
        return time1;
}
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-21 08:59:26 | 显示全部楼层
YANGSCAU 发表于 2019-12-20 19:18
我写了一个函数 通过获取两次pwm端口的高低电平时的运行事件来获取pwm端口高电平的时间

可是很像有问 ...

现在是啥问题,Get_time1(void) 这个函数放在哪个地方运行,应该放在一个没有延时函数的地方,这样需要一直查询PWM3状态,有延时就会有影响。


建议还是用中断判断PWM3 的状态,获取上升沿  下降沿的时候获取时间,下降沿计算一下高电平的时间返回一下,不要在中断里面printf()!

茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-21 16:27:56 | 显示全部楼层
htao 发表于 2019-12-21 08:59
现在是啥问题,Get_time1(void) 这个函数放在哪个地方运行,应该放在一个没有延时函数的地方,这样需要一 ...

如果采用中断的方式这个应该怎么写呢

我基础不好,如果这个代码不多能不能麻烦您有空的时候帮我写一下呢。谢谢老哥!!!

就按照您的思路我觉得挺好的,只需要获得高电平持续的时间就可以了
回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-21 18:54:31 | 显示全部楼层
YANGSCAU 发表于 2019-12-21 16:27
如果采用中断的方式这个应该怎么写呢

我基础不好,如果这个代码不多能不能麻烦您有空的时候帮我写一下 ...

我发的工程里面这个路径,F103激光雷达\HARDWARE\EXTI 有个外部中断的c文件和 头文件,添加进去修改成要用的引脚,并且中断模式改成 上升下降都触发
  1. EXTI_InitStructure.EXTI_Trigger =  EXTI_Trigger_Rising_Falling
复制代码


然后再添加一个中断服务函数就行了,
  1. void EXTI9_5_IRQHandler(void)
  2. {
  3.         //高电平,表示刚刚是上升沿触发
  4.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8) == 1)
  5.         {
  6.                 //记录开始时间
  7.         }
  8.        
  9.         //低电平,表示刚刚是下降沿触发
  10.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8) == 0)
  11.         {
  12.                 //记录结束时间
  13.                
  14.                 //并且得到整体高电平时间
  15.         }

  16.         EXTI_ClearITPendingBit(EXTI_Line8);
  17. }
复制代码


我这个引脚是 PB8,芯片信号是103C8T6, 你修改引脚要对应好外部中断服务函数名,百度查一下。
茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-21 21:14:22 | 显示全部楼层
本帖最后由 YANGSCAU 于 2019-12-22 12:11 编辑

htao 发表于 2019-12-21 18:54
我发的工程里面这个路径,F103激光雷达\HARDWARE\EXTI 有个外部中断的c文件和 头文件,添加进去修改成要 ...
u64 time1=0;   //推杆1伸出总时间
u64 time11=0;  //推杆1每一次伸出的时间
u64 time1_start=0;   //pwm3为高电平时的系统运行时间
u64 time1_over=0;    //pwm3为低电平时的系统运行时间
u64 time2=0;   
u64 time22=0;
u64 time2_start=0;
u64 time2_over=0;

  1. void EXTIX_Init(void)
  2. {

  3.            EXTI_InitTypeDef EXTI_InitStructure;
  4.            NVIC_InitTypeDef NVIC_InitStructure;

  5.     pwm4_init();

  6.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //使能复用功能时钟


  7.    //GPIOB.8 pwm3          中断线以及中断初始化配置 上升沿下降沿都触发
  8.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource8);
  9.           EXTI_InitStructure.EXTI_Line=EXTI_Line8;
  10.           EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        
  11.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  12.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

  13.    //GPIOB.9 pwm4          中断线以及中断初始化配置  上升沿下降沿触发        
  14.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);
  15.           EXTI_InitStructure.EXTI_Line=EXTI_Line9;
  16.           EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;        
  17.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  18.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  19.           NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;                              //使能所在的外部中断通道
  20.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;        //抢占优先级2,
  21.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                                        //子优先级2
  22.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  23.           NVIC_Init(&NVIC_InitStructure);

  24. }
复制代码
  1. void EXTI9_5_IRQHandler(void)     //外部中断服务函数
  2. {
  3.   //高电平即为上升沿时纪录运行时间     
  4.         if(pwm3 == 1)
  5.   {
  6.                 time1_start=Get_system_time();
  7.   }
  8.   //低电平即为下降沿时纪录运行时间并获得整体高电平时间           
  9.   if(pwm3 == 0)
  10.   {
  11.                 time1_over=Get_system_time();
  12.                 time11=time1_over-time1_start;
  13.                 time1 = time1 + time11;    //总的高电平时间
  14.    }
  15.          
  16.          //高电平即为上升沿时纪录运行时间     
  17.         if(pwm4 == 1)
  18.   {
  19.                 time2_start=Get_system_time();
  20.   }
  21.   //低电平即为下降沿时纪录运行时间并获得整体高电平时间           
  22.   if(pwm4 == 0)
  23.   {
  24.                 time2_over=Get_system_time();
  25.                 time22=time2_over-time2_start;  
  26.                 time2 = time2 + time22;    //总的高电平时间
  27.    }
  28.    
  29.          EXTI_ClearITPendingBit(EXTI_Line8);
  30.          EXTI_ClearITPendingBit(EXTI_Line9);
  31. }

复制代码





回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-21 21:18:23 | 显示全部楼层
htao 发表于 2019-12-21 18:54
我发的工程里面这个路径,F103激光雷达\HARDWARE\EXTI 有个外部中断的c文件和 头文件,添加进去修改成要 ...

真的非常感谢!!!我按照你的思路把代码写了,可是还是不行

我的项目其中一个要求是获取电动推杆伸长的长度,也就是pwm的高电平时长,然后通过获取到的时长最后通过延时让电动推杆回到初始位置

可是现在问题是当我通过获取的时间让电动推杆回到初始位置时,电动推杆就动了一下就不动了,也不知道是不是我的代码有问题

回复

使用道具 举报

28

主题

294

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1790
金钱
1790
注册时间
2018-3-26
在线时间
294 小时
发表于 2019-12-22 15:27:05 | 显示全部楼层
YANGSCAU 发表于 2019-12-21 21:18
真的非常感谢!!!我按照你的思路把代码写了,可是还是不行

我的项目其中一个要求是获取电动推杆伸长 ...

获取PWM 的高电平时长吗?PWM 一直处于不同频率和不同占空比的环境吗?

如果是相同频率的PWM, 不就只获取占空比,和整段pwm输入时长,不就知道了高电平的时长了吗。
茵茵猪头
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-23 09:22:29 | 显示全部楼层
htao 发表于 2019-12-22 15:27
获取PWM 的高电平时长吗?PWM 一直处于不同频率和不同占空比的环境吗?

如果是相同频率的PWM, 不就只 ...

我是需要获得pwm输出高电平的时长,也就是电动推杆伸出时对应的pwm的时长
回复

使用道具 举报

0

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2018-11-30
在线时间
26 小时
发表于 2019-12-23 14:53:52 | 显示全部楼层
YANGSCAU 发表于 2019-12-19 18:26
我想通过捕获定时器通道输出给电机的高电平时间也可以用输入捕获吗

可以的,原子例程有相关程序
回复

使用道具 举报

3

主题

14

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2019-9-22
在线时间
14 小时
 楼主| 发表于 2019-12-27 20:35:43 | 显示全部楼层
春晓LCX 发表于 2019-12-23 14:53
可以的,原子例程有相关程序

那个例程是对输入信号进行捕获,可是我想对输出信号进行捕获可以做到吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-20 15:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表