我遇到过相同问题,因为串口还没发完就进入省电模式了,解决办法是等串口发送完毕再进入省电模式
因为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[R_Buf_Len]; //Uart1接收缓存
- unsigned char xdata T_Buf[T_Buf_Len]; //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[RP]=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]);
- TP++;
- }
- }
- }
-
- void LVD_Isr(void) interrupt LVD_VECTOR
- {
- RSTFLAG=0x10;
- }
复制代码
|