基于消息循环的定时器

概述

    Android定时器实现一般来说, 包括以下两种:

  • java.util.Timer
  • android.app.AlarmManager

    除此之外, 其实还有一种方式可以实现定时器的效果, 即利用消息循环的Handler来实现.


定时器

众所周知, Handler 可以发送延迟 Message/Runnable, 那么就可以利用其对应接口 handleMessage() / run() 来反复发送延迟消息, 既可实现定时器效果. 一旦不再定时操作了, 调用 Handler.remove**() 就可以清除消息队列中的消息, 也就取消了定时操作.

值得注意的是, 整个定时器操作都是基于消息循环的, 如UI线程的消息循环.

/** package + import */

/** Timer */
public abstract class LiteTimer {
    private static final MSG_TIMER = 0x01;
    private final Handler mHandler;
    /*private*/ long mDelayedMillis = 2000;

    public LiteTimer () {
        mHandler = new TimerHanlder(this);
    }

    public void setDelayedMillis(long val) {
        mDelayedMillis = val;
    }

    public void start() {
        mHandler.sendEmptyMessageDelayed(MSG_TIMER, mDelayedMillis);
    }

    public void stop() {
        mHandler.removeMessages(MSG_TIMER);
    }

    protected abstract boolean onTime();

    private static class TimerHandler {
        private WeakReference<LiteTimer> mRef;

        TimerHandler(LiteTimer timer) {
            mRef = new WeakReference<LiteTimer>();
        }

        @Override
        public void handleMessage(Message msg) {
            LiteTimer timer = mRef.get();
            if (timer != null) {
                if (timer.onTime()) {
                    sendEmptyMessageDelayed(MSG_TIMER, timer.mDelayedMillis);
                }
            }
        }
    }
    
}




转载于:https://my.oschina.net/erehmii/blog/180124

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32定时器1控制舵机的示例代码: ``` #include "stm32f10x.h" #define SERVO_PIN GPIO_Pin_8 #define SERVO_PORT GPIOA void TIM1_UP_IRQHandler(void) { if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM1, TIM_IT_Update); GPIO_SetBits(SERVO_PORT, SERVO_PIN); TIM_SetCompare1(TIM1, 2000); // 2ms } } void TIM1_CC_IRQHandler(void) { if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); GPIO_ResetBits(SERVO_PORT, SERVO_PIN); TIM_SetCompare1(TIM1, 18000); // 18ms } } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); GPIO_InitStructure.GPIO_Pin = SERVO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SERVO_PORT, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = 20000; // 20ms TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1500; // 1.5ms TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_Cmd(TIM1, ENABLE); TIM_ITConfig(TIM1, TIM_IT_Update | TIM_IT_CC1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); while (1) { } } ``` 在这个示例代码中,我们使用了定时器1来产生20ms的PWM信号来控制舵机。我们设置了定时器1的计数范围为20000,预分频系数为72-1,这样定时器1的计数频率就是1MHz。然后我们设置了比较器1的输出模式为PWM1模式,并设置了一个初始占空比为1.5ms,这样舵机就会旋转到中间位置。接着我们开启了定时器1,并配置了定时器1的更新中断和比较器1的捕获/比较中断。在定时器1的更新中断中,我们将舵机控制引脚置高,并设置比较器1的计数值为2000,这样舵机就会旋转到最左边的位置。在比较器1的捕获/比较中断中,我们将舵机控制引脚置低,并设置比较器1的计数值为18000,这样舵机就会旋转到最右边的位置。在主函数中,我们一直循环等待中断的发生。 需要注意的是,这个示例代码中的占空比和计数值是根据我们使用的舵机来确定的,如果使用不同型号的舵机,需要根据舵机的规格来计算出正确的占空比和计数值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值