本帖最后由 相耘 于 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();
- }
- }
|