打印
[STM8]

开启IWDG和AWU后程序进入HALT后通过外部中断唤醒

[复制链接]
5756|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
相耘|  楼主 | 2013-8-23 17:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 相耘 于 2013-8-24 10:48 编辑

开启IWDG和AWU后程序进入HALT后通过外部中断唤醒,但如果刚进HALT大约5秒内由外部唤醒,则正常,即程序会从while(1){}内部开始执行,也就是说在HALT后进AWU喂狗然后再HALT期间,主程序一直在while(){}内部等待外部中断唤醒,但如果进入HALT后大约超过5秒后由外部唤醒 ,则不正常,即程序会从Main(){}开始重新执行,即复位了。且程序在HALT->AWU喂狗->HALT的循环中并不稳定,会自动唤醒。我想可能是AWU中断服务程序有些问题,但尝试了一下,没有解决,看了看技术手册,没找到头绪,有木有了解或遇到过类似情况的朋友?一起讨论一下,:)谢谢!使用的是STM8S103。
#include "STM8S103F.h"

unsigned int num;
unsigned char Display_bat[]={0xff,0xf7,0xf3,0xf1,};
unsigned char Display_cig[]={0x1f,0x9f,0xdf,0xff,};


//                                             STM8S103F
//                 ------------------------
//        SW->PD4-| 1                   20 |-PD3->TIM2_CH2->PWM
//      AIN5->PD5-| 2                   19 |-PD2<-AIN3
//      AIN6->PD6-| 3                   18 |-PD1<->SWIM
//           NRST-| 4                   17 |-PC7->SMALLH
//      BIGH<-PA1-| 5                   16 |-PC6->SMALLM
//      BIGM<-PA2-| 6                   15 |-PC5->SMALLL
//            VSS-| 7                   14 |-PC4->NULL
//           VCAP-| 8                   13 |-PC3->NULL
//            VDD-| 9                   12 |-PB4<-CHARGE
//      BIGL<-PA3-| 10                  11 |-PB5->OPENLOAD
//                 ------------------------


void Init_GPIO(void)        
{
        PC_ODR = 0xff;                //设置PC口输出为高电平,
        PC_DDR = 0xff;                //设置PC口全为输出,置1为输出,置0为输入;
        PC_CR1 = 0xff;                //置1为推挽(输出时)或上拉(输入时)
                                                //置0为浮空
        PC_CR2 = 0x00;                //设置PC口为推挽输出,置1为中断,置0为非中断
        
        PA_ODR = 0xff;                //设置PC口输出为高电平,
        PA_DDR = 0xff;                //设置PC口全为输出,置1为输出,置0为输入;
        PA_CR1 = 0xff;                //置1为推挽(输出时)或上拉(输入时)
                                                //置0为浮空
        PA_CR2 = 0x00;                //设置PA口为推挽输出,置1为中断,置0为非中断
        
        PB_ODR = 0x00;                //设置PB输出端口为低电平
        PB_DDR = 0xef;                //设置PB4为输入,其余为输出
        PB_CR1 = 0x00;                //设置PB4为悬浮输入               
        PB_CR2 = 0x00;                //非中断
        
        PD_ODR = 0x00;                 //设置PD输出端口为低电平
        PD_DDR = 0xef;                //设置PD4为输入,其余为输出
        PD_CR1 = 0x10;                //设置PD4为上拉输入        
        PD_CR2 = 0x00;                //非中断
        
        CLK_ICKR |= 0X20;        //进入活跃停机模式关闭 MVR 以省电
        FLASH_CR1 |= 0X04;        //进入活跃停机模式关闭 FLASH 以省电  
}
void IWDG(void)
{
        IWDG_KR=0xcc;                //起动IWDG命令
        IWDG_KR=0x55;                //开起IWDG_PR和IWDG_RLR寄存器写功能
        IWDG_PR|=0x06;                //写入分频值256分频
        IWDG_RLR=0xff;                //128kHz时钟经过256分频再计250个时钟脉冲
        IWDG_KR=0xaa;                //喂狗同时也是封闭IWDG_PR和IWDG_RLR寄存器写功能
}
void IWDG_Refresh(void)
{
        IWDG_KR=0x55;                //开起IWDG_PR和IWDG_RLR寄存器写功能
        IWDG_KR=0xaa;                //喂狗同时也是封闭IWDG_PR和IWDG_RLR寄存器写功能
}
void Open_AWU(void)
{
        AWU_CSR = 0x01;
        AWU_APR = 0x2f;
        AWU_TBR = 0x0a;
        AWU_CSR |= 0x10;
}
void Init_TIM1(void)
{
        TIM1_IER = 0x00;                // interrupt disable
        TIM1_EGR = 0x01;                // enable generator
        TIM1_PSCRH = 0x00;                // 计数器时钟=主时钟/128=2MHZ/128
        TIM1_PSCRL = 0x00;                // 相当于计数器周期为64uS
        TIM1_ARRH = 0xff,                //
        TIM1_ARRL = 0xff;
        TIM1_CNTRH = 0xff;                //
        TIM1_CNTRL = 0xff;
                                                        // 定时周期=(ARR+1)*64=16320uS
        TIM1_CR1 = 0x01;                // b0 = 1,允许计数器工作
                                                        // b1 = 0,允许更新
                                                        // 设置控制器,启动定时器
        TIM1_IER = 0x01;                //interrupt enable
}
void Halt_Perproccess(void)
{
        _asm("sim");
        PA_ODR = 0xff;
        PC_ODR = 0xe0;
        
        PB_ODR = 0x00;                //设置PB输出端口为低电平
        PB_CR2 = 0x10;                //PB4中断
        PD_ODR = 0x00;                 //设置PD输出端口为低电平        
        PD_CR2 = 0x10;                //PD4中断        
        
        EXTI_CR1 = 0x84;        //设置PB口中断为上升沿触发,PD口为下降沿触发
        
        IWDG_Refresh();                //进停机模式前喂狗
       //TIM1_IER = 0x00;        //关闭定时器中断
        _asm("rim");
        _asm("halt");
}
/****************end****************/
void Halt_Mode(void)
{
        if(num==200)        //定时进入停机模式
        {
                num = 0;
                Halt_Perproccess();
        }
}
/****************TIM1_INT****************/

@far[url=home.php?mod=space&uid=422518]@interrupt[/url] void TIM1(void)        //定时器1
{
        TIM1_SR1 = 0x00;                        //clean timer status registor
        IWDG_Refresh();
        PC_ODR = Display_cig[1];         
//检测灯
        num++;
}
/****************end****************/
@far@interrupt void AWU(void)
{
        IWDG_Refresh();
        AWU_CSR |= 0x10;
        _asm("halt");
}
/****************EXTI1****************/
[url=home.php?mod=space&uid=1095855]@far[/url] @interrupt void EXTI1(void)        //PB口外部中断
{
        if(PB_IDR&0x10)
        {
                PB_CR2 = 0x00;
                PD_CR2 = 0x00;
        }
}
/****************end****************/
/****************EXTI3****************/
@far @interrupt void EXTI3(void)        //PD口外部中断
{
        if(!(PD_IDR&0x10))
        {
                PB_CR2 = 0x00;
                PD_CR2 = 0x00;
        }
}
/****************end****************/
/****************MAIN****************/
void main(void)
{
        _asm("sim");
        Init_GPIO();
        Init_TIM1();
        Open_AWU();
        IWDG();
        _asm("rim");
        PC_ODR = Display_cig[0];      //检测灯
        while(1)
        {
                IWDG_Refresh();
                PA_ODR = Display_bat[1];      //检测灯
                Halt_Mode();
        }
}

           
沙发
相耘|  楼主 | 2013-8-24 10:01 | 只看该作者
定时器中断程序名有乱码,正确应为@far @interrupt void TIM1(void),似乎用插入代码的方式遇到@字符时总会产生些乱码。

使用特权

评论回复
板凳
相耘|  楼主 | 2013-8-26 11:53 | 只看该作者
是太简单还是太复杂了!无人回应

使用特权

评论回复
地板
相耘|  楼主 | 2013-8-26 17:56 | 只看该作者
看来是没人回应了!

使用特权

评论回复
5
yuanquanquan| | 2013-8-26 18:28 | 只看该作者
表示没用过看门狗,帮卤煮顶一下。

使用特权

评论回复
6
chuangpu| | 2013-8-26 19:34 | 只看该作者
帮楼主顶一个   感觉这一块   自己不懂的太多了   还需要好好消化消化   楼主

使用特权

评论回复
7
nil_li| | 2013-8-29 15:27 | 只看该作者
不知道楼主可知道,看门狗不可关闭!所以,你的程序HALT之后,被看门狗复位了。看门狗最长的复位时间好像是2s,记不清楚了

使用特权

评论回复
8
相耘|  楼主 | 2013-8-31 10:06 | 只看该作者
nil_li 发表于 2013-8-29 15:27
不知道楼主可知道,看门狗不可关闭!所以,你的程序HALT之后,被看门狗复位了。看门狗最长的复位时间好像是 ...

看门狗的最长时间是1.02秒,我使用AWU唤醒的目的就是喂狗,
@far@interrupt void AWU(void)
{
        IWDG_Refresh();    //喂狗
        AWU_CSR |= 0x10; //清AWUF
        _asm("halt"); //再睡
}
但就是不按我的思路去运行,进HALT后->AWU唤醒->喂狗->再睡,在以上的过程中,主程序应该一直在while(1)处等待外部中断的唤醒,实际是5秒前由外部中断唤醒是对的,5秒之后再唤醒,程序就复位了,我通过检测灯可以看到,其实我贴的程序只是一个框架,实际产品的程序是含有ADC,PWM,外加一些LED动态显示等,这应该是一个小产品的程序的基本框架。这个程序开WWDG也正常,但开了IWDG后由于要自动喂狗所以加了AWU,结果就有点不对了,我估计还是AWU服务程序可能有点问题,但又说不上来具体在哪里。

使用特权

评论回复
9
相耘|  楼主 | 2013-9-5 11:32 | 只看该作者
本帖最后由 相耘 于 2013-9-5 11:33 编辑
[url=home.php?mod=space&uid=1095855]@far[/url] [url=home.php?mod=space&uid=422518]@interrupt[/url] void AWU(void)
{
        if(AWU_CSR&0x20)
                IWDG_Refresh();
        AWU_wakeup = 1;
}
void main(void)
{
        _asm("sim");
        Init_GPIO();
        Init_TIM1();
        CLK_Config();
        Flash_Init();
        Open_AWU();
        IWDG();
        _asm("rim");
        PC_ODR = Display_cig[0];
        while(1)
        {
                IWDG_Refresh();
                if(AWU_wakeup)
                {
                        AWU_wakeup = 0;
                        _asm("halt");
                }
                else
                {
                        主程序放在这里
                        PA_ODR = Display_bat[1];
                        Halt_Mode();
                }
        }
}
当AWU唤醒后只在AWU服务程序中恢复标志位然后回主程序中进HALT,用这样的方式就正常了,但感觉这样的话程序有点绕,问题是可以解决,但总觉得不舒服,不知哪位仁兄另有高见,请不吝赐教,

使用特权

评论回复
10
nil_li| | 2013-9-5 11:59 | 只看该作者
几点请注意:
1.看门狗是复位。
2.中断程序中HALT,应该要有问题的。
3.看门狗时间和唤醒时间
所以中断中无执行代码,只做标志是比较合理的做法。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
相耘 + 1 很给力!
11
相耘|  楼主 | 2013-9-24 18:11 | 只看该作者
nil_li 发表于 2013-9-5 11:59
几点请注意:
1.看门狗是复位。
2.中断程序中HALT,应该要有问题的。

不要在AWU中断服务程序中执行HALT是正确的,

使用特权

评论回复
12
hkcj| | 2013-9-24 19:04 | 只看该作者
不懂这一块   楼主   帮你顶一个   看看高手的见解  

使用特权

评论回复
13
pofu007| | 2013-9-26 15:39 | 只看该作者
IWDG在HALT时,仍然是工作的吧,HALT前是不是先把IWDG停掉。

使用特权

评论回复
14
相耘|  楼主 | 2013-10-15 14:04 | 只看该作者
pofu007 发表于 2013-9-26 15:39
IWDG在HALT时,仍然是工作的吧,HALT前是不是先把IWDG停掉。

STM8只要开启IWDG就不可被关闭,开WWDG可以关闭,
这个问题的解决办法是:不要在AWU服务程序中执行进HALT的指令。

使用特权

评论回复
15
l4157| | 2014-1-20 11:13 | 只看该作者
在AWU中断中用HALT相当于中断嵌套,AWU多了就溢出了,然后复位...

使用特权

评论回复
16
p422984186| | 2016-5-9 14:17 | 只看该作者
学习下

使用特权

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

本版积分规则

1

主题

11

帖子

0

粉丝