4

I am currently working on a traffic monitoring system that require Geological coordinates (that are as float) to be sent a string via a GSM/GPRS module as a text message. I used the following code to convert these float values to strings but in compilation "warning: (1393) possible hardware stack overflow detected; estimated stack depth: 10" happens to pop up. I'm using PIC 16f877A and what can I do to avoid this other than changing the 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);
    }
}
Plouff
  • 3,290
  • 2
  • 27
  • 45
TheShark
  • 420
  • 3
  • 6
  • 17
  • Hard to tell without the rest of the code but you're probably calling too deep. That pic only has 8 stacklevels. Re-structure your entire program to call less deep, don't use any recursion and don't call subroutines from a interrupt routine (if you're using interrupts). – Unimportant Mar 27 '16 at 18:05
  • We don't see `pow`'s calling requirements, which might be the limiting factor (if it's a library function). Otherwise is there any reason why the very simple `reverse` function can't be part of `intToStr`? That would save 1 stack level. But you don't have 10 stack depth in the code shown: so make it more efficient further down. – Weather Vane Mar 27 '16 at 18:50

2 Answers2

1

you may use built in "sprintf" function, something like this (compiles ok with pic16f1705 and should be same with yours pic):

char array[64];
float myvalue=2.0f;
sprintf(array, "%f", myvalue);

look at help file for XC8 compiler, help->XC8 Toolchain->MPLAB XC8 Compiler-> library functions->sprintf

Also you may print directly to USART1 using printf:

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

Here is peace of code where which I used for printing ADC values in PICF16F877A

// 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);


  }                    
}