打印
[STM8]

按键外部中断唤醒halt模式,偶尔会刚唤醒又进入停机,或者刚停机有自己唤醒了

[复制链接]
6047|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
arthurly|  楼主 | 2012-12-8 11:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用的是stm8s103f3p6芯片,
外部按键并上拉电阻,用的是PD5口,设置PD5为浮空输入。
内部用了定时器4,手册显示定时器4功耗最低,16分频,系统时钟是HSI默认8分频2M,定时器16分频就是125k,做了1ms中断,定时器工作正常。

外部中断相应后查看是刚唤醒还是要执行停机操作,因为我是一个按键控制开关机的,开机后控制电机和指示灯

停机功耗30ua,

在不断开关过程中,偶尔会出现刚唤醒就又停机了,或者刚执行停机就自己又醒来了,我在外部中断程序中去了按键抖动了,不知道问题在哪里,请大侠们指点,下面是我的代码

/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: GPIO_Init                                                    */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize GPIOs.                                            */
/* IN:           None.                                                        */
/* OUT:          None.                                                        */
/* -------------------------------------------------------------------------- */
void GPIO_Init(void)
{
                PA_DDR        =        0xff;        //all output
                PA_CR1        = 0x00;//OD
                PA_CR2        = 0X00;//disable interrupt
               
                PB_DDR        =        0xff;//all output
                PB_CR1        = 0X00;//OD
                PB_CR2        = 0X00;//disable interrupt
               
                PC_DDR        =        0xff;
                PC_CR1        = MOTOR_IO;//motor PP
                PC_CR2        = 0X00;
               
                PD_DDR =         0xff & ~KEY;                                                       
    PD_CR1 = 0;       
    PD_CR2  = 1 << 5;//key2 enable ex interrupt

                PA_ODR = 0x00;
                PB_ODR = power_IO;//power is high
                PC_ODR = LED_BIT0 | LED_BIT1;
                PD_ODR = KEY;
}
/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: CLK_Init                                                     */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the clock source                                  */
/* -------------------------------------------------------------------------- */
void CLK_Init(void)
{
    /* Configure HSI prescaler*/
        CLK_PCKENR1 = 1 << 4;//除了timer4,其他外设时钟全部关闭
        CLK_PCKENR2 = 0x00;
       
        CLK_CKDIVR = 0x018;          /* 默认选项,内部RC16M,8分频*/

    /* Configure CPU clock prescaler */
    //CLK_CKDIVR |= 0x01;           /* 001: fCPU=fMASTER/2. */
}
/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: TIM_Init                                                     */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the TIM4.                                    */
/* -------------------------------------------------------------------------- */
void TIM4_Init(void)
{
    TIM4_ARR   = 125;//1ms   125*8=1000

    TIM4_PSCR   = 0x04;            /*16分频,125K  计数加一=8us */
    TIM4_IER        |= 0x01;        //enable
                TIM4_CR1   |= 0x01;        //开始计数

}

//主函数
void main(void)
{
        uchar key,i;
        unsigned char *state;
        //设置一个存储地址
        state = (unsigned char *)0x4000;
        CLK_Init();                //初始化时钟
        GPIO_Init();        //初始化io
        TIM4_Init();                //初始化定时器2
        //EXTI_CR1 = 0x80; //外部中断只在下降沿触发
        _asm("rim");
        if(system_state == 0)//通电默认停机状态
        {
                LED0_OFF;//关闭所有设备
                LED1_OFF;
                MOTOR_OFF;
                MOTOR_POWER_OFF;
                _asm("halt");        //进入停机
        }
        while (1)
        {}
/*******************D口外部中断*******************************/
@far @interrupt void EXTI3_Interrupt(void)
{
        uint i = 50000;
        while((PD_IDR & (1 << 5)) == 0);//等待按键抬起
        while(i--);//延时50ms去抖动
        if(system_state == 0)//刚唤醒
        {
                system_state = 1;//将系统状态位标志位run
                MOTOR_POWER_ON;
                MOTOR_ON;
                LED0_ON;//默认高速
                LED1_OFF;
                halt_bit = 0;
        }
        else//执行停机操作
        {
                LED0_OFF;//关闭所有设备
                LED1_OFF;
                MOTOR_OFF;
                MOTOR_POWER_OFF;
                //halt_bit = 1; //标记准备停机,在中断外执行
                system_state = 0;                //将系统状态位标志位halt
                _asm("halt");
        }
        return;
}
/*******************定时器4中断 1ms*******************************/
@far @interrupt void TIM4_Interrupt (void)
{
    TIM4_SR=0x00;//清除中断标志位
}
沙发
arthurly|  楼主 | 2012-12-8 19:43 | 只看该作者
本帖最后由 arthurly 于 2014-7-3 11:55 编辑

:)

使用特权

评论回复
板凳
arthurly|  楼主 | 2012-12-8 21:17 | 只看该作者

使用特权

评论回复
地板
arthurly|  楼主 | 2012-12-10 10:51 | 只看该作者
坛子里的大侠都哪儿去了,最后自己解决了,分享给大家。
按键两端接1uF的电容就没有问题了,
原因是只要一点干扰波动就会响应外部中断,也太灵敏了,我用示波器看那个拨动也就0.1V

最后停机功耗35uA 一节锂电池

使用特权

评论回复
5
IJK| | 2012-12-10 13:51 | 只看该作者
按键两端接1uF的电容,或许大了点,接0.1uF的电容感觉就差不多了。

另外,还可以、应该在软件上进行去抖。

使用特权

评论回复
6
hanyz123| | 2013-1-7 11:38 | 只看该作者
留下自己的脚印,感谢楼主的代码分享。学习下

使用特权

评论回复
7
huangjinyuan06| | 2013-6-5 20:39 | 只看该作者
同样的问题,学习了,谢谢

使用特权

评论回复
8
wuxing1106| | 2015-3-16 16:06 | 只看该作者
我碰见过按键消抖消不掉,并个222就全解决了

使用特权

评论回复
9
RF、龙龙| | 2016-4-11 17:24 | 只看该作者
楼主的问题早解决了吧

使用特权

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

本版积分规则

2

主题

10

帖子

1

粉丝