CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

optimize code, to free memory (Solved)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guido_Batan



Joined: 20 May 2019
Posts: 7
Location: Argentina

View user's profile Send private message Visit poster's website

optimize code, to free memory (Solved)
PostPosted: Thu Apr 16, 2020 8:34 pm     Reply with quote

CCS PCH C Compiler, Version 5.030
PIC16F887

Hello guys, I am making a navigation menu to display on a 4x20 lcd screen, but it takes up a lot of rom memory. Is there any way to optimize the code to free up memory ? Thank you in advance, thank you very much.
Code:

void menu_item(){

/* *****************************         INITIAL MENU            ******************************/
  if(!in(Menu_Boton) && item==1){ //Pressing the button, Access the main menu
   delay_us(20);
   lcd_clear();
   
// The values are shown on the lcd screen. The minimum and maximum values are established
   valor_menu=Temperatura_deseada;
   valor_max=250; //Max value temp
   valor_min=15;   //Min value temp

  lcd_gotoxy(1,1);
   printf(lcd_putc," Temperatura Deseada");
  lcd_gotoxy(1,4);
   printf(lcd_putc,"**  CONFUGURACION **");
   
   temporal=1;   
   item=2;
   }
 
 
 
/* *************************        ADJUST VALUES USING ROTARY ENCODER            *************************/
  if(item>=2 && item<=4){
 
   enable_interrupts(int_EXT);

  if(item==2 || item==4){   
   
  lcd_gotoxy(1,2);
   printf(lcd_putc,"         %04Ld        ",valor_menu);
 
  }else{
   
   char firstdig = valor_menu / 60;
   char seconddig = (valor_menu - (firstdig * 60))/ 10;
   char thirddig =  valor_menu - (firstdig * 60) - (seconddig*10);
   
  lcd_gotoxy(1,2);
   printf(lcd_putc,"       0%01u:%01u%01u       ",firstdig,seconddig,thirddig);
 
   }
   
   disable_interrupts(int_EXT);

}
 
 
/* *************************        MENU 1 INITIAL            *************************/
   if(item==2){

   if(in(Menu_Boton) && temporal==1){ // when the button is released..
  temporal=2;
}
   if(!in(Menu_Boton) && temporal==2){ //when the button is pressed it is saved in eeprom memory..
   delay_us(20);
   temporal=3;
}
   if(temporal==3){
 
   if(valor_menu!=0){

   if(Temperatura_deseada!=valor_menu){
    Temperatura_deseada=valor_menu;

   if(Temperatura_deseada>=20 && Temperatura_deseada<=250){
    guardar_valor16(0x2100,Temperatura_deseada);       // Save in eeprom

}
    Temperatura_deseada=Temperatura_deseada;
}
}
    valor_menu=Tiempo_deseado;
    valor_max=120; //Max value time
    valor_min=5;   //Min value time
    delay_us(20);


    lcd_gotoxy(1,1);
     printf(lcd_putc,"  Tiempo Deseado    ");
 
    temporal=4;   
    item=3;
   
 }

}
 
 
 
/* *************************        MENU 2            *************************/
   if(item==3){

   if(in(Menu_Boton) && temporal==4){ // when the button is released..
    temporal=5;
}
   if(!in(Menu_Boton) && temporal==5){ //when the button is pressed it is saved in eeprom memory.
    delay_us(20);
    temporal=6;
}
   if(temporal==6){

 
   if(valor_menu!=0){
   if(Tiempo_deseado!=valor_menu){
    Tiempo_deseado=valor_menu;

   if(Tiempo_deseado>=5 && Tiempo_deseado<=240){
    guardar_valor16(0x2110,Tiempo_deseado);       // Save in eeprom
}
    Tiempo_deseado=Tiempo_deseado;
}

}

    valor_menu=duty_PWM2;
 
    valor_max=1023; //Max value pwm
    valor_min=0;   //Min value pwm 
    delay_us(20);

    lcd_gotoxy(1,1);
     printf(lcd_putc,"Velocidad del Motor:");

   temporal=7;   
   item=4;

}
   }
 
 
 
/* *************************        MENU 3            *************************/
   if(item==4){

    duty_PWM2=valor_menu;
    set_pwm2_duty(duty_PWM2);
 
   if(in(Menu_Boton) && temporal==7){

    temporal=8;
}
    if(temporal==8 && !in(Menu_Boton)){
     delay_us(20);
    temporal=9;
}

   if(in(Menu_Boton) && temporal==9){ //Si btn_menu==1..

    temporal=10;
}

   if(temporal==10){

    delay_US(3);
    lcd_clear(); 
    temporal=0;
    duty_PWM2=0;
    set_pwm2_duty(0);
    item=1; //Exit menu.
}
}
}


Last edited by Guido_Batan on Fri Apr 17, 2020 2:36 pm; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 17, 2020 12:15 am     Reply with quote

The easiest way is switch to an 18F4620. Your program uses 15% of ROM
with a 16F887, but only 3% with an 18F4620.

Because you're using 16F887, I assume you have limited Microchip products
to choose from in your country. So it's possible that 18F4620 may also be
available. It's an older PIC.

Also, you didn't tell us your programmer. 18F4620 will work with Pickit 2,
if that's your programmer.

If you can, it's better to use 18F46K22. It's cheaper, has more features,
but it requires Pickit 3.
Ttelmah



Joined: 11 Mar 2010
Posts: 19218

View user's profile Send private message

PostPosted: Fri Apr 17, 2020 1:35 am     Reply with quote

Also, there are possible functional issues with what you show:

char seconddig = (valor_menu - (firstdig * 60))/ 10;
char thirddig = valor_menu - (firstdig * 60) - (seconddig*10);

firstdig*60 will overflow if it is above 4.

Best to have the 'digits' declared as int8, and use:

char seconddig = (valor_menu - (firstdig * 60L))/ 10;
char thirddig = valor_menu - (firstdig * 60L) - (seconddig*10);

Note the 2 'L's.

This then forces int16 arithmetic, but with the int8 variables.

Or:

char seconddig = (valor_menu - (_mul(firstdig,60)))/ 10;
char thirddig = valor_menu - (_mul(firstdig,60)) - (seconddig*10);

Which automatically performs an 8bit multiplication, but retains the
16bit result.

You show 'valor_menu' being loaded with 'duty_PWM2', which may
suggest this is a 16bit value. If so the digit divisions would need to
be able to cope with numbers above 255.
Guido_Batan



Joined: 20 May 2019
Posts: 7
Location: Argentina

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 17, 2020 9:13 am     Reply with quote

Hi PCM programmer, Ttelmah, thanks for reply.
I will take into account the replacement of the chip, I just checked and there is not a big price difference and it has 4 times more memory.

Perfect, I'm going to correct the char seconddig and char thirddig code to improve it.

As for the duty_PWM2 variable, it is correct, it is declared as int16, what do you recommend regarding the variable menu_value, is it ok to declare it as int16?

Here I publish part of the code (sorry, I need to order it and comment on the code lines)

Code:
int16 duty_PWM2=0;
int16 valor_menu=0;
int16 Temperatura_deseada=0;
int16 Tiempo=0;
int8 temporal=0;     
int16 Tiempo_deseado=0;   
int8 item=0;
int16 valor_min=0;
int16 valor_max=0;

int msec=0,sec=0,min=0;
char vel=0, cuenta=0;



Code:
#int_TIMER0
TIMER0_isr(){

   if(cuenta==10){  //Rapida 3.
     cuenta = 0;
         Encend(Led_Boton_Emerg);
     vel=1;
        set_timer0(velocidad_max); // Setea a 5 el timer 0
}else{
    Apag(Led_Boton_Emerg);
    vel=0;
    }
    if(velocidad_max!=0){
   cuenta++;
    }

    if(!in(Menu_Boton) && velocidad_max==0 && temporal==0){
    temporal=1;
    }
   set_timer0(velocidad_max); // Setea a 5 el timer 0
   

   return 0;
 
}

//***************************Interrupciones de los timers**************************

#int_TIMER1
     
   void imprimir_cronometro(){
     set_timer1(55661);
     
       if(tiempo==1){   //Si la variable swicht es igual a 1, se ejecuta el cronómetro
       
       if(item!=8){
         if(msec++>99){       //incrementa el valor de msec y si es mayor a 99
              msec=0;               //pone msec a 0.
          if(sec++>58){       //incrementa el valor de sec y si es mayor de 59
                sec=0;             //ponesec a 0.
           if(min++>60){
                 min=0;
           }
         }
         }
         
       }else{
       
         if(msec++>99){       //incrementa el valor de msec y si es mayor a 99
              msec=0;               //pone msec a 0.
          if(sec++>121){       //incrementa el valor de sec y si es mayor de 59
                sec=0;             //ponesec a 0.
         
         }
         }
         
       }
       }else{      //Si la variable siwcht no es igual a 1 se pone a 0 mse, sec, min
    msec=0;
    sec=0;
    min=0;
    }
   }

/*                ENCODER ROTARY    */
#INT_EXT
void IntRB0(){
     disable_interrupts(int_EXT);
     if (bit_test(portb,0)){ 
         ext_int_edge(H_TO_L);
         
         if ((bit_test(portb,1)) == 1 && valor_menu<valor_max && in(Menu_Boton)){

            valor_menu++;
          }
         
     }else{ 
         ext_int_edge(L_TO_H);
         if ((bit_test(portb,1)) == 1 && valor_menu>valor_min && in(Menu_Boton)){

            valor_menu--;
       
         }
     }
     enable_interrupts(int_EXT);
}


_________________
The universe has several frequency levels. We are software, an eternal present, time an illusion. Before our senses we perceive that it is physical. It is a hologram. We are characters "with different levels of consciousness"
temtronic



Joined: 01 Jul 2010
Posts: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Apr 17, 2020 10:21 am     Reply with quote

As PCMP suggested, choose a newer, bigger PIC.
Years ago I wrote down what I needed and wanted in a 'does everything' PIC. 2 HW UARTS, speed, 40 pins, LOTS of memory, 3 and 5 volt operation. The 'new' then' PIC18F46K22 seemed the best choice, a 'Swiss Army Knife' of PICs. It's never let me down. I've never used some internal peripherals or features, but over the years, I've developed a library of good,soild drivers. While 'overkill' for most projects, having ONE PIC makes for faster programming. It's been a very reliable PIC.Yes it costs more for smaller projects but it WORKS ! No need to worry about bugs or upgrades or some 'quirks'. Also,I use MPLAB 8.92 and a PICkit3, both 'stable' products.
Guido_Batan



Joined: 20 May 2019
Posts: 7
Location: Argentina

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 17, 2020 1:36 pm     Reply with quote

Temtronic thanks for the reply.
I will definitely buy the pic18f46k22 there is little price difference. I just tried compiling the code for that version and didn't get any errors. Excellent! Should i add lines of code like timer3, 4, 5 and 6? The fuses is important to change them for that version?

Code:
#INCLUDE <18f46k22.H>  //PIC utilizado
#DEVICE ADC = 16
#fuses XT              //Oscilador a cristal standar
#fuses NOWDT           //sin WatchDog Timer
#fuses NOPUT           //sin PowerUp Timer
#fuses BROWNOUT      //brownout
#fuses NOLVP           //sin programación en baja tensión
#FUSES PROTECT   //Code protected from reading
#FUSES NOMCLR // Master Clear pin Deshabilitado
//#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, parity=n, bits=8, stop=1)
#use delay(clock=4000000)

_________________
The universe has several frequency levels. We are software, an eternal present, time an illusion. Before our senses we perceive that it is physical. It is a hologram. We are characters "with different levels of consciousness"
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 17, 2020 2:06 pm     Reply with quote

Look at the end of the .LST file to see the fuses that will be placed in the
.HEX file. You can see the default fuses used by the compiler, if you don't
specify them. The default fuse settings are typically correct. You don't have
to specify all the fuses.
temtronic



Joined: 01 Jul 2010
Posts: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Apr 17, 2020 2:15 pm     Reply with quote

re: fuses

I always enable PUT, the Power Up Timer option. The fraction of a second it takes is nothing really BUT it does allow the PIC to startup in a controlled way.

Don't select 'PROTECT'. it's not needed until the very,very final version of the code ,just before you ship it out t the client. For home use, don't bother.
also...

ALWAYS add 'ERRORS' when using hardware UARTS. it will prevent the UART from 'locking up' when 3 or more characters come in before you servicve them.

Also...
the use delay() needs to be before use rs232(), well pretty sure, for the compiler to code the timeings properly.
Guido_Batan



Joined: 20 May 2019
Posts: 7
Location: Argentina

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 17, 2020 2:35 pm     Reply with quote

temtronic, PCM programmer Thanks for the reply, I am going to take your advice, and I am going to observe the fuses. Success!


Code:
#INCLUDE <18f46k22.H>  //PIC utilizado
#DEVICE ADC = 10
#fuses XT              //Oscilador a cristal standar
#fuses NOWDT           //sin WatchDog Timer
#fuses PUT           //sin PowerUp Timer
#fuses BROWNOUT      //brownout
#fuses NOLVP           //sin programación en baja tensión
#FUSES NOPROTECT   //Code protected from reading
#FUSES NOMCLR // Master Clear pin Deshabilitado

#use delay(clock=4000000)
//#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, parity=n, bits=8, stop=1, errors)

_________________
The universe has several frequency levels. We are software, an eternal present, time an illusion. Before our senses we perceive that it is physical. It is a hologram. We are characters "with different levels of consciousness"
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group