 |
 |
View previous topic :: View next topic |
Author |
Message |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Thu Mar 03, 2011 12:24 am |
|
|
Actually memory is consuming here I think.
After total_kg_i=total_kg_i -1;
I am breaking total_kg_i into seperate kg's like
Code: |
sprintf(buffer_a,"%lu",total_kg_i);
if(total_kg_i==0)
{
kg_1=0;kg_2=0;kg_3=0;kg_4=0;kg_5=0;kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=1 && total_kg_i<10)
{
kg_1=ToInt(buffer_a[0]);kg_2=0;kg_3=0;kg_4=0;
kg_5=0;kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=10 && total_kg_i<100)
{
kg_1=ToInt(buffer_a[1]);kg_2=ToInt(buffer_a[0]);kg_3=0;kg_4=0;
kg_5=0;kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=100 && total_kg_i<1000)
{
kg_1=ToInt(buffer_a[2]);kg_2=ToInt(buffer_a[1]);kg_3=ToInt(buffer_a[0]);kg_4=0;
kg_5=0;kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=1000 && total_kg_i<10000)
{
kg_1=ToInt(buffer_a[3]);kg_2=ToInt(buffer_a[2]);kg_3=ToInt(buffer_a[1]);
kg_4=ToInt(buffer_a[0]);kg_5=0;kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=10000 && total_kg_i<100000)
{
kg_1=ToInt(buffer_a[4]);kg_2=ToInt(buffer_a[3]);kg_3=ToInt(buffer_a[2]);
kg_4=ToInt(buffer_a[1]);kg_5=ToInt(buffer_a[0]);kg_6=0;kg_7=0;kg_8=0;
}
else if(total_kg_i>=100000 && total_kg_i<1000000)
{
kg_1=ToInt(buffer_a[5]);kg_2=ToInt(buffer_a[4]);kg_3=ToInt(buffer_a[3]);
kg_4=ToInt(buffer_a[2]);kg_5=ToInt(buffer_a[1]);kg_6=ToInt(buffer_a[0]);
kg_7=0;kg_8=0;
}
else if(total_kg_i>=1000000 && total_kg_i<10000000)
{
kg_1=ToInt(buffer_a[6]);kg_2=ToInt(buffer_a[5]);kg_3=ToInt(buffer_a[4]);
kg_4=ToInt(buffer_a[3]);kg_5=ToInt(buffer_a[2]);kg_6=ToInt(buffer_a[1]);
kg_7=ToInt(buffer_a[0]);kg_8=0;
}
else if(total_kg_i>=10000000 && total_kg_i<100000000)
{
kg_1=ToInt(buffer_a[7]);kg_2=ToInt(buffer_a[6]);kg_3=ToInt(buffer_a[5]);
kg_4=ToInt(buffer_a[4]);kg_5=ToInt(buffer_a[3]);kg_6=ToInt(buffer_a[2]);
kg_7=ToInt(buffer_a[1]);kg_8=ToInt(buffer_a[0]);
}
|
Can I get rid of this code into simple routine? |
|
 |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Mar 03, 2011 3:18 am |
|
|
You may be able to reduce this but it depends.
We have not got the full picture here and it looks like you are trying to crack an egg with a hammer.
it looks like you are using kg_1, kg_2 etc to ooutput you left justified value!
I also assume you are using putc(c) for 6 of the chars and output_(port) for the other 2.
I don't think there is any need for this routine at all. You have the value in buffer_a why move it to int8's ?
Also how is your buffer defined?
Show us your display routine.
how big is the full program? |
|
 |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Mar 03, 2011 3:32 am |
|
|
Whenever I see variables like kg_1 to kg_8 my fingers start to itch. This is a perfect example of code to be replaced by a function as it will be smaller, better to understand and hence less error prone.
As Wayne points out, it looks like you are trying to create a left justified output. You can create that with a simple extra parameter to the sprintf command, see the manual for details. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19732
|
|
Posted: Thu Mar 03, 2011 4:11 am |
|
|
Seriously, go back to small counters, keeping the digits separate. It is important to understand that an 'increment', or a 'test', in machine terms are single instructions. Something like a multiply is dozens of instructions, while a division can be thousands. Some things that look easy to us, can involve huge amounts of machine time, while other solutions that almost look 'silly' to us, are really fast.
Just handle your digits as needed:
Code: |
#define INC_DIGIT(x) (((x=(x==9)?(x=0):++x)),x==0)
int kg00001=0;
int kg00010=0;
int kg00100=0;
int kg01000=0;
int kg10000=0;
if (INC_DIGIT(kg00001))
if (INC_DIGIT(kg00010))
if (INC_DIGIT(kg00100))
if (INC_DIGIT(kg01000))
if (INC_DIGIT(kg10000)) ;
|
This shows five digits being handled, and you could add another digit, or overflow handling at the end.
The key is that the later code only gets called when there _is_ a carry. So for 9 out of ten digits, it takes just 15 machine cycles. In the tenth call, this almost doubles, then on the hundredth rises again, but even handling a wrap on all five digits, takes less than 75 machine cycles.
Syntactically, the macro definition is 'wrong', in standard C terms, but for some reason CCS needs the odd double assignment to actually perform the required result, and the resulting assembler is efficient:
Code: |
27: if (INC_DIGIT(kg00001))
005D 0020 MOVLB 0 //bank select
005E 0820 MOVF 0x20, W //Load the value
005F 3C09 SUBLW 0x9 //test if nine
0060 1D03 BTFSS 0x3, 0x2
0061 2865 GOTO 0x65 //here if 0 to 8
0062 01A0 CLRF 0x20 //Here if nine
0063 0820 MOVF 0x20, W
0064 2867 GOTO 0x67 //Clear and exit
0065 0AA0 INCF 0x20, F //Increment
0066 0820 MOVF 0x20, W
0067 3A00 XORLW 0 //Test for zero and exit
0068 1D03 BTFSS 0x3, 0x2
0069 289A GOTO 0x9a
|
Best Wishes |
|
 |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Mar 03, 2011 4:24 am |
|
|
Something like this should do what you want.
I have not tested it. I don't know if it reduces your code.
It may be possible to improve on this based on the rest of your code.
Someone here may have a better solution.
Code: |
int32 val;
int32 d;
int8 pos;
int8 c;
int1 outFlag = false;
val = total_kg_i;
d = 100000000;
pos = 0;
do {
c = val / d; // Get the (d) value.
val = val - (c * d); // Adjust val
d = d / 10; // Move d on to the next d val
if (c > 0)
outFlag = true;
if (outFlag)
{
if (pos < 6)
putc(c + '0'); // LCD
else if (pos == 6)
output_a(c + '0'); // 7 Seg 1
else
output_b(c + '0'); // 7 Seg 2
pos++;
}
} while ((pos < 8) && (d > 1));
while (pos < 8)
{
// Clean up by clearing the rest of the display.
if (pos < 6)
putc(0); // LCD
else if (pos == 6)
output_a(0); // 7 Seg 1
else
output_b(0); // 7 Seg 2
pos++;
}
|
[ EDIT ]
LOL, As sugested above, single 8 bit vars is proberbly your best way to go for speed and code size. |
|
 |
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Thu Mar 03, 2011 5:15 am |
|
|
Thanks for your support again.
I am going to use two variables.one for total kg and one for sending pulse.
total kg should be int32.
Tell me how i read and write int32 in/form eeprom.
for storing and reading int16 bit data i use the following macro
Code: |
#define mReadWord(addr) make16(read_eeprom(addr+1),read_eeprom(addr)) //macros for read and write on
#define mWriteWord(addr,data) {write_eeprom(addr,make8(data,0));write_eeprom((addr+1),make8(data,1));}//eeprom 16 bit data
|
can i add the remainng address in the above macro to save the data like
Code: |
#define mReadWord(addr) make32(read_eeprom(addr+4),read_eeprom(addr+2),read_eeprom(addr+1),read_eeprom(addr)) //macros for read and write on
#define mWriteWord(addr,data) {write_eeprom(addr,make8(data,0));write_eeprom((addr+1),make8(data,1));write_eeprom((addr+2),make8(data,2));write_eeprom((addr+4),make8(data,4));}//eeprom 16 bit data
|
|
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19732
|
|
Posted: Thu Mar 03, 2011 5:40 am |
|
|
As a further comment on what I posted, understand that if you want a pulse every 100 counts for example, you can do it as:
Code: |
if (INC_DIGIT(kg00001))
if (INC_DIGIT(kg00010)) {
//pulse here will be given every 100 counts
if (INC_DIGIT(kg00100))
if (INC_DIGIT(kg01000))
if (INC_DIGIT(kg10000)) ;
}
|
With this the digits are already separate, kept and handled as decimal digits, instead of converting backwards and forwards to binary, with divisions of multiplications, and lots of time/space.
Best Wishes |
|
 |
|
|
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
|