小松鼠 发表于 2025-12-2 15:30:55

STC32G12K128省电模式唤醒

这段代码在main的主循环中一直进入省电模式,只有当P2.1上触发中断之后,中断会串口打印数据,随后退出省电模式,执行PD=1后面的代码,但是实际情况是中断触发之后,中断函数中的打印能有,但是while循环中的打印有时候有,有时候没有,请问这个是什么问题

神农鼎 发表于 2025-12-2 15:56:56


小松鼠 发表于 2025-12-2 16:05:06

神农鼎 发表于 2025-12-2 15:56

我看到了,STC32G12K128的普通IO口最好不要上升沿、下降沿中断,
但是有2个原因:
1.硬件已经设计好了,现在要唤醒的中断就在这个引脚上面;
2.从PD模式下面普通IO唤醒只能使用上升、下降沿中断,不能使用高低电平的中断吧

小松鼠 发表于 2025-12-2 16:06:22

神农鼎 发表于 2025-12-2 15:56


这个IO中断优先级会对唤醒有影响吗?需要额外配置下吗?

神农鼎 发表于 2025-12-2 16:31:40

可以改用:

STC32G8K64-LQFP48/32/TSSOP20
STC8H8K64U-LQFP64/48/32/TSSOP20






DebugLab 发表于 2025-12-2 18:13:52

我遇到过相同问题,因为串口还没发完就进入省电模式了,解决办法是等串口发送完毕再进入省电模式
因为printf只是装载数据到缓冲区,然后串口中断和硬件在“后台”发送
以下例程供参考,基于本人编写的“串口收发框架,带不断电下载功能”:
https://www.stcaimcu.com/thread-16321-1-1.html
关键代码:

逻辑:
整个数据包发送完毕后,发送长度变量会在串口中断内清零,printf后要等待该变量为0再进入省电模式
例程:
#include <AI8H.H>
#include <intrins.h>
#include <absacc.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>

#define                RXD                        P30
#define                TXD                        P31
#define                FOSC                24000000UL
#define                BAUD                9600UL                                                //波特率
#define                TMRF                200UL                                                //定时器频率
#define                BRT                        (0x10000-(FOSC/BAUD+2)/4)      //波特率发生器值
#define                TMR                        (0x10000-FOSC/TMRF/12)                //定时器值
#define                R_Buf_Len      64                                                      //Uart1接收缓存长度
#define                T_Buf_Len      64                                                      //Uart1发送缓存长度
#define                R                        0                                                      //485接收
#define                T                        1                                                      //485发送

unsigned char                RP;                                        //Uart1接收指针
unsigned char                TP;                                        //Uart1发送指针
unsigned char                Uart_R_Len;                        //Uart1接收长度
unsigned char                Uart_T_Len;                        //Uart1发送长度
unsigned char xdata      R_Buf;      //Uart1接收缓存
unsigned char xdata      T_Buf;      //Uart1发送缓存

char USER_STCISPCMD[]="@STCISP#";      //下载命令(用户自定义,可修改,必须和ISP软件中设置的一致)

void Delay_ms(unsigned char ms)
{
      unsigned int i;
      do
      {
                i=FOSC/10000;
                while(--i);      //10T per loop
      }
      while(--ms);
}

void UART_Send(unsigned int x)
{
      TP=0;
      Uart_T_Len=x;
      TI=1;
}

void Uart_Printf(unsigned char *v,...)
{
      va_list ap;
      va_start(ap,v);
      while(Uart_T_Len);
      UART_Send(vsprintf(T_Buf,v,ap));
      va_end(ap);
}

void UART_Return(unsigned char temp)
{
      memcpy(T_Buf,R_Buf,temp);
      UART_Send(temp);
}

void Init(void)
{
      P_SW2|=EAXFR;
      
      P0M1=0x00;      P0M0=0x00;      //设置IO模式
      P1M1=0x00;      P1M0=0x00;      //设置IO模式
      P2M1=0x00;      P2M0=0x00;      //设置IO模式
      P3M1=0x00;      P3M0=0x00;      //设置IO模式
      P4M1=0x00;      P4M0=0x00;      //设置IO模式
      P5M1=0x00;      P5M0=0x00;      //设置IO模式
      P6M1=0x00;      P6M0=0x00;      //设置IO模式
      P7M1=0x00;      P7M0=0x00;      //设置IO模式
      
      AUXR=0x40;                //设置定时器0时钟为12T模式,设置定时器1为1T模式,设置定时器1为波特率发生器
      TMOD=0x01;                //设置定时器0为16位不自动重装载模式,设置定时器1为16位自动重装载模式
      TH0=TMR>>8;                //设置定时器0初始值
      TL0=TMR;                //设置定时器0初始值
      TF0=0;                        //清除TF0中断标志位
      ET0=1;                        //启用定时器0中断
      
      SCON=0x50;                //设置UART1模式为8位数据可变波特率
      TH1=BRT>>8;                //设置UART1波特率
      TL1=BRT;                //设置UART1波特率
      TR1=1;                        //打开定时器1
      ES=1;                        //启用UART1中断
      
      EA=1;                        //启用总中断
}

void main(void)
{
      Init();
      
      Uart_Printf("Start\r\n");
      
      RSTCFG&=~0x40;
      RSTFLAG=0x14;
//      ELVD=1;
      
      Uart_Printf("RSTCFG= 0x%02bX\r\n",RSTCFG);
      Uart_Printf("RSTFLAG = 0x%02bX\r\n",RSTFLAG);
      Uart_Printf("IE      = 0x%02bX\r\n",IE);
      
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      P32=!P32;
      Delay_ms(250);
      Delay_ms(250);
      
      Uart_Printf("PD\r\n");
      while(Uart_T_Len);
      
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      PCON|=0x02;
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      
      while(1)
      {
                Uart_Printf("Running\r\n");
                Delay_ms(250);
                Delay_ms(250);
                Delay_ms(250);
                Delay_ms(250);
      }
}


void Uart_Start(void)
{
      TL0=0x00;
      TH0=0xEE;
      TR0=1;
}

void Uart_Stop(void)
{
      TR0=0;
      TL0=0x00;
      TH0=0xEE;
      RP=0;
      memset(R_Buf,0x00,sizeof R_Buf);
}

void TMR0_Isr(void) interrupt TMR0_VECTOR
{
      UART_Return(RP);      //超时原样返回
      Uart_Stop();
}

void UART1_Isr(void) interrupt UART1_VECTOR
{
      if(RI)
      {
                RI=0;
                Uart_Start();
                R_Buf=SBUF;
                if((RP==sizeof USER_STCISPCMD-2)&&(memcmp(R_Buf,USER_STCISPCMD,sizeof USER_STCISPCMD-1)==0))      //收到用户命令后复位到ISP区
                {
                        IAP_CONTR=0x60;
                }
                if(RP==R_Buf_Len-1)
                {
                        Uart_Stop();
                }
                else if(TR0)
                {
                        RP++;
                }
      }
      if(TI)
      {
                TI=0;
                if(TP==Uart_T_Len)
                {
//                        TR=R;      //485软件收发控制
                        TP=0;
                        Uart_T_Len=0;
                }
                if(Uart_T_Len!=0)
                {
//                        TR=T;      //485软件收发控制
                        SBUF=(T_Buf);
                        TP++;
                }
      }
}

void LVD_Isr(void) interrupt LVD_VECTOR
{
      RSTFLAG=0x10;
}

小松鼠 发表于 2025-12-3 09:03:14

DebugLab 发表于 2025-12-2 18:13
我遇到过相同问题,因为串口还没发完就进入省电模式了,解决办法是等串口发送完毕再进入省电模式
因为print ...

好的,我试一下,不过今天早上发现这套代码省电模式唤醒之后的串口打印又有了,昨天下午还是不行的,中断触发之后只有中断函数中的打印会触发,只是放了一个晚上,程序完全没动过{:yun:}
页: [1]
查看完整版本: STC32G12K128省电模式唤醒