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