如何在我的PIC16f877A项目中避免堆栈溢出,该项目具有浮点到字符串的转换?

如何在我的PIC16f877A项目中避免堆栈溢出,该项目具有浮点到字符串的转换?,c,stack-overflow,microcontroller,compiler-warnings,mplab,C,Stack Overflow,Microcontroller,Compiler Warnings,Mplab,我目前正在开发一个交通监控系统,该系统要求通过GSM/GPRS模块将地质坐标(以浮点形式)作为文本消息发送到字符串。我使用以下代码将这些浮点值转换为字符串,但在编译过程中,突然弹出“警告:(1393)检测到可能的硬件堆栈溢出;估计堆栈深度:10”。 我使用的是PIC16F877A,除了更换MCU,我还能做些什么来避免这种情况 void reverse(char *str, int len) { int i=0, j=len-1, temp; while (i<j) {

我目前正在开发一个交通监控系统,该系统要求通过GSM/GPRS模块将地质坐标(以浮点形式)作为文本消息发送到字符串。我使用以下代码将这些浮点值转换为字符串,但在编译过程中,突然弹出“警告:(1393)检测到可能的硬件堆栈溢出;估计堆栈深度:10”。 我使用的是PIC16F877A,除了更换MCU,我还能做些什么来避免这种情况

void reverse(char *str, int len)
{
int i=0, j=len-1, temp;
    while (i<j)
    {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
        i++; j--;
    }
}

int intToStr(int x, char str[], int d)
{
    int i = 0;
    while (x)
    {
        str[i++] = (x%10) + '0';
        x = x/10;
    }
    while (i < d)
        str[i++] = '0';

    reverse(str, i);
    str[i] = '\0';
    return i;
}

void ftoa(float n, char *res, int afterpoint)
{
    int ipart = (int)n;
    float fpart = n - (float)ipart;
    int i = intToStr(ipart, res, 0);
    if (afterpoint != 0)
    {
        res[i] = '.';
        fpart = fpart * pow(10, afterpoint);
        intToStr((int)fpart, res + i + 1, afterpoint);
    }
}
void反向(char*str,int len)
{
int i=0,j=len-1,温度;
而(i您可以使用内置的“sprintf”函数,类似这样的函数(pic16f1705可以编译,应该与您的pic相同):

查看XC8编译器的帮助文件,帮助->XC8工具链->MPLAB XC8编译器->库函数->sprintf

您也可以使用printf直接打印到USART1:

printf("my message to GSM transitter %f", myvalue); 

这是我用来在PICF16F877A中打印ADC值的代码和平

// CONFIG
#pragma config FOSC  = HS      // Oscillator Selection bits (HS oscillator)
#pragma config WDTE  = OFF     // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF    // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON    // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP   = OFF      // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD   = OFF      // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT   = OFF      // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP    = OFF       // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>
#include <pic16f877a.h>
#include <stdio.h>
#include <string.h>

#define _XTAL_FREQ 20000000

/////////////////////////Code to print debug print//////////////////////////////
//#define FREQ 8000000
#define FREQ _XTAL_FREQ
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)    //312500 spbrg=32
unsigned char data1;
char *str1;
void serial_init()
{
    SPBRG=spbrg_value;
    //SPBRG=31;
    //  TXSTAbits.TXEN = 1;
    //CSRC: Clock Source Select bit            0
    //TX9 : 9-bit Transmit Enable bit          0
    //TXEN: Transmit Enable                    0  
    //SYNC: EUSART Mode Select bit             0
    //SENDB: Send Break Character bit          0
    //BRGH: High Baud Rate Select bit          0
    //TRMT: Transmit Shift Register Status bit 1
    //TX9D: Ninth bit of Transmit Data         0
    TXSTA=0x20;

    //  RCSTAbits.SPEN = 1;
    //  RCSTAbits.CREN = 1;

    //bit 7 SPEN: Serial Port Enable bit        1
    //bit 6 RX9: 9-bit Receive Enable bit       0
    //bit 5 SREN: Single Receive Enable bit     0
    //bit 4 CREN: Continuous Receive Enable bit 1
    //bit 3 ADDEN: Address Detect Enable bit    0
    //bit 2 FERR: Framing Error bit             0
    //bit 1 OERR: Overrun Error bit             0
    //bit 0 RX9D: 9th bit of Received Data      0
    RCSTA=0x90;
    //Setting 
    TRISCbits.TRISC6=0;
    TRISCbits.TRISC7=1;
}
void tx(unsigned char temp)
{
    TXREG=temp;
    while(PIR1bits.TXIF == 0);
    while(TXSTAbits.TRMT == 0);

}

void tx_str(char *senpoint)
{
    str1=senpoint;
    while(*str1 != '\0')
    {
        tx(*str1);
        str1++;

    }
}

//In main function, you can write,

unsigned char ADCBuf[40]; 
void main()
{
  serial_init();
//  unsigned int a;
  TRISA = 0xFF;                 //Analog pins as Input
//  TRISB = 0x00;                 //Port B as Output
//  TRISC = 0x00;                 //Port C as Output
  ADC_Init();                   //Initialize ADC
  unsigned int a;
  float V;
  a = 10;
  unsigned char str_1[]="P";
   tx_str("ADC TEST \n\r");
  while(1)
  {

    a = ADC_Read(0);            //Read Analog Channel 
//    a = a + 1;            //Read Analog Channel 0
    sprintf(ADCBuf,"Adc Val = %d \n\r",a);
    tx_str(ADCBuf);
    __delay_ms(1000);            //Delay
    V = a*(5000.0/1023.0);
    sprintf(ADCBuf,"Voltage = %f \n\r",V);
    tx_str(ADCBuf);
    __delay_ms(1000);


  }                    
}
//配置
#pragma config FOSC=HS//振荡器选择位(HS振荡器)
#pragma config WDTE=OFF//看门狗定时器启用位(WDT禁用)
#pragma config PWRTE=OFF//通电定时器启用位(PWRT禁用)
#pragma config BOREN=ON//Brown out重置启用位(BOR禁用)
#pragma config LVP=OFF//低压(单电源)电路内串行编程启用位(RB3为数字I/O,MCLR上的高压必须用于编程)
#pragma config CPD=OFF//数据EEPROM存储器代码保护位(数据EEPROM代码保护关闭)
#pragma config WRT=OFF//Flash程序存储器写启用位(写保护关闭;所有程序存储器可由EECON控制写入)
#pragma config CP=OFF//闪存程序存储器代码保护位(代码保护关闭)
#包括
#包括
#包括
#包括
#定义频率20000000
/////////////////////////用于打印调试打印的代码//////////////////////////////
//#定义频率8000000
#定义频率
#定义波特率9600
#定义spbrg_值(((FREQ/64)/baud)-1)//312500 spbrg=32
无符号字符数据1;
char*str1;
void serial_init()
{
SPBRG=SPBRG_值;
//SPBRG=31;
//TXSTAbits.TXEN=1;
//时钟源选择位0
//TX9:9位传输启用位0
//TXEN:传输启用0
//同步:EUSART模式选择位0
//SENDB:发送中断字符位0
//BRGH:高波特率选择位0
//TRMT:传输移位寄存器状态位1
//TX9D:传输数据0的第九位
TXSTA=0x20;
//RCSTAbits.SPEN=1;
//RCSTAbits.CREN=1;
//位7 SPEN:串行端口启用位1
//位6 RX9:9位接收启用位0
//位5 SREN:单接收启用位0
//第4位CREN:连续接收启用第1位
//位3加法:地址检测启用位0
//位2 FERR:帧错误位0
//位1 OERR:溢出错误位0
//位0 RX9D:接收数据0的第9位
RCSTA=0x90;
//背景
TRISCbits.TRISC6=0;
TRISCbits.TRISC7=1;
}
void tx(无符号字符温度)
{
TXREG=温度;
而(PIR1bits.TXIF==0);
而(TXSTAbits.TRMT==0);
}
无效传输线(字符*senpoint)
{
str1=senpoint;
而(*str1!='\0')
{
tx(*str1);
str1++;
}
}
//在main函数中,您可以编写,
无符号字符ADCBuf[40];
void main()
{
串行_init();
//无符号整数a;
TRISA=0xFF;//模拟管脚作为输入
//TRISB=0x00;//端口B作为输出
//TRISC=0x00;//端口C作为输出
ADC_Init();//初始化ADC
无符号整数a;
浮动V;
a=10;
无符号字符str_1[]=“P”;
tx_str(“ADC测试\n\r”);
而(1)
{
a=ADC_Read(0);//读取模拟通道
//a=a+1;//读取模拟通道0
sprintf(ADCBuf,“Adc Val=%d\n\r”,a);
tx_str(ADCBuf);
__延迟_ms(1000);//延迟
V=a*(5000.0/1023.0);
sprintf(ADCBuf,“电压=%f\n\r”,V);
tx_str(ADCBuf);
__延迟μms(1000);
}                    
}

如果没有剩下的代码很难说,但你可能调用的太深了。那张图片只有8个堆栈级别。重新构造你的整个程序,使其调用的深度更小,不要使用任何递归,也不要从中断例程调用子例程(如果你使用的是中断).我们没有看到pow的调用要求,这可能是限制因素(如果是库函数)。否则,非常简单的
reverse
函数不能作为
intToStr
的一部分有什么原因吗?这将节省1个堆栈级别。但是您在显示的代码中没有10个堆栈深度:所以进一步提高效率。太好了!它实际上也与pic16f887a一起工作。非常感谢您的支持!
// CONFIG
#pragma config FOSC  = HS      // Oscillator Selection bits (HS oscillator)
#pragma config WDTE  = OFF     // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF    // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON    // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP   = OFF      // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD   = OFF      // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT   = OFF      // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP    = OFF       // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>
#include <pic16f877a.h>
#include <stdio.h>
#include <string.h>

#define _XTAL_FREQ 20000000

/////////////////////////Code to print debug print//////////////////////////////
//#define FREQ 8000000
#define FREQ _XTAL_FREQ
#define baud 9600
#define spbrg_value (((FREQ/64)/baud)-1)    //312500 spbrg=32
unsigned char data1;
char *str1;
void serial_init()
{
    SPBRG=spbrg_value;
    //SPBRG=31;
    //  TXSTAbits.TXEN = 1;
    //CSRC: Clock Source Select bit            0
    //TX9 : 9-bit Transmit Enable bit          0
    //TXEN: Transmit Enable                    0  
    //SYNC: EUSART Mode Select bit             0
    //SENDB: Send Break Character bit          0
    //BRGH: High Baud Rate Select bit          0
    //TRMT: Transmit Shift Register Status bit 1
    //TX9D: Ninth bit of Transmit Data         0
    TXSTA=0x20;

    //  RCSTAbits.SPEN = 1;
    //  RCSTAbits.CREN = 1;

    //bit 7 SPEN: Serial Port Enable bit        1
    //bit 6 RX9: 9-bit Receive Enable bit       0
    //bit 5 SREN: Single Receive Enable bit     0
    //bit 4 CREN: Continuous Receive Enable bit 1
    //bit 3 ADDEN: Address Detect Enable bit    0
    //bit 2 FERR: Framing Error bit             0
    //bit 1 OERR: Overrun Error bit             0
    //bit 0 RX9D: 9th bit of Received Data      0
    RCSTA=0x90;
    //Setting 
    TRISCbits.TRISC6=0;
    TRISCbits.TRISC7=1;
}
void tx(unsigned char temp)
{
    TXREG=temp;
    while(PIR1bits.TXIF == 0);
    while(TXSTAbits.TRMT == 0);

}

void tx_str(char *senpoint)
{
    str1=senpoint;
    while(*str1 != '\0')
    {
        tx(*str1);
        str1++;

    }
}

//In main function, you can write,

unsigned char ADCBuf[40]; 
void main()
{
  serial_init();
//  unsigned int a;
  TRISA = 0xFF;                 //Analog pins as Input
//  TRISB = 0x00;                 //Port B as Output
//  TRISC = 0x00;                 //Port C as Output
  ADC_Init();                   //Initialize ADC
  unsigned int a;
  float V;
  a = 10;
  unsigned char str_1[]="P";
   tx_str("ADC TEST \n\r");
  while(1)
  {

    a = ADC_Read(0);            //Read Analog Channel 
//    a = a + 1;            //Read Analog Channel 0
    sprintf(ADCBuf,"Adc Val = %d \n\r",a);
    tx_str(ADCBuf);
    __delay_ms(1000);            //Delay
    V = a*(5000.0/1023.0);
    sprintf(ADCBuf,"Voltage = %f \n\r",V);
    tx_str(ADCBuf);
    __delay_ms(1000);


  }                    
}