|
|
View previous topic :: View next topic |
Author |
Message |
mojsa2000
Joined: 18 May 2010 Posts: 78
|
a strange problem |
Posted: Wed Oct 19, 2011 3:54 am |
|
|
Hi
I make a program with PIC16f877a. In one of functions when I subtract two values (for example : delta=32760-(-32760)) its result is odd because its result is -16.
delta=32760-(-32760)=-16
Code: |
#include <16f877a.h>
#FUSES NOWDT,PUT,BROWNOUT,NOLVP,HS
#use delay (clock=16000000)
#use rs232(baud=19200, xmit=PIN_C6,rcv=PIN_C7)
#include <math.h>
#define DAC1 PIN_B4
#define DAC2 PIN_B5
//=========variables=================
signed int16 pre_in,input,step;
signed int16 delta;
unsigned int16 step_in,pre_step; |
and
Code: | delta=32760-(-32760);
if(abs(delta)<=abs(step_in))
pre_step=abs(delta);
else
pre_step=abs(step_in);
if(delta<0)
step=-pre_step;
else
step=pre_step;
|
Thanks
Last edited by mojsa2000 on Wed Oct 19, 2011 4:10 am; edited 1 time in total |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Oct 19, 2011 4:10 am |
|
|
Why do you find it odd? Its precisely what I'd expect your code to do. If you find it odd, that suggests you don't fully understand signed 2's compliment representation.
You are using 16 bit signed integers, with a range of -32768 to 32767. 32760-(-32760) is 32760 + 32760 which would give 65520, or 0xFFF0, as the sum will be done in unsigned 16bit arithmetic since both constants are unsigned, *despite* those minus signs: in C integer literals are always unsigned. However, you then assign the result to a *signed* 16 bit varaible and so 0xFFF0 is interpreted, in its 2's compliment form, as -16. Put another way, your sum has overflowed the range of signed 16bit and the result has wrapped round. Either way, its exactly what you should expect from the numbers and the variable type you've chosen to use.
RF Developer |
|
|
mojsa2000
Joined: 18 May 2010 Posts: 78
|
|
Posted: Wed Oct 19, 2011 4:47 am |
|
|
Dear RF_Developer
this is my function and definitions:
Code: | signed int16 pre_in,input,step,delta;
unsigned int16 step_in,pre_step;
signed int8 buffer[4];
int1 start_flag=0,int_flag=0,cal_flag=0,dg_flag=0,step_flag=0,nxt_byte=0;
int1 nxt_st_byte=0;
|
Code: | void make_data(){
input=make16(buffer[1],buffer[0]);
pre_in=make16(read_eeprom(0x01),read_eeprom(0));//hi=0x01,low=0x0
step_in=make16(buffer[3],buffer[2]);
delay_us(50);
write_eeprom(0x01, make8(input,1));
write_eeprom(0, make8(input,0));
delta=input-pre_in;
if(abs(delta)<=abs(step_in))
pre_step=abs(delta);
else
pre_step=abs(step_in);
if(delta<0)
step=-pre_step;
else
step=pre_step;
//return input,pre_in,step;
} |
ore_in & input are signed integers and give a signed integer as delta
now,what do I do?
please help me.
thanks again |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Oct 19, 2011 6:14 am |
|
|
mojsa2000 wrote: |
this is my function and definitions (reformatted to make them readable):
Code: | signed int16 pre_in, input, step, delta;
unsigned int16 step_in, pre_step;
signed int8 buffer[4];
int1 start_flag=0, int_flag=0, cal_flag=0, dg_flag=0, step_flag=0, nxt_byte=0;
int1 nxt_st_byte=0;
|
Code: | void make_data(){
input = make16(buffer[1], buffer[0]);
pre_in = make16(read_eeprom(0x01), read_eeprom(0)); //hi=0x01,low=0x0
step_in = make16(buffer[3], buffer[2]);
delay_us(50);
write_eeprom(0x01, make8(input,1));
write_eeprom(0, make8(input,0));
delta = input - pre_in;
if(abs(delta) <= abs(step_in))
pre_step = abs(delta);
else
pre_step = abs(step_in);
if(delta<0)
step = -pre_step;
else
step = pre_step;
//return input,pre_in,step;
} |
|
What are you trying to do? This code does what it does, which as you're asking, is clearly not what you want it to do. So, what do you want this code to do? What problem are you trying to solve?
RF Developer |
|
|
mojsa2000
Joined: 18 May 2010 Posts: 78
|
|
Posted: Wed Oct 19, 2011 6:51 am |
|
|
Hi again
I read two values on RS232 Port as "input" and "step".
then last "input" value that stored on memory on previous level, is loaded as "pre_in" .then I will count from "pre_in" to "input" .step is the "step"value.
for example :
I send 32760 as "input" and 100 as "step".assume that "pre_in" is -32760.
well,sign of "input-pre_in", determines if count up or count down and also "pre_in - input " value must be greater than "step" value.in this example :delta =32760-(-32760)=65520 and step is 100.
thus it counts up from -32760 to 32760 .each step is 100.note that step must be recieved on RS232 as a positive value (unsigned).
I simulate this code in protuos and I checked delta.
I think you're right.because when I count from zero to 32760 or -32760 its true but when I count from a negative value to positive value ( or viceversa) it do wrong.
thanks |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Oct 19, 2011 8:11 am |
|
|
HINT:
you can try try int32 vars -
and then use a bit of TYPE casting to fewer bits ,
when generating your results |
|
|
mojsa2000
Joined: 18 May 2010 Posts: 78
|
|
Posted: Wed Oct 19, 2011 8:45 am |
|
|
Hi
thank you
I did it
Code: | delta=((signed int32 )input- (signed int32 )pre_in);
|
best regards |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Oct 19, 2011 11:19 am |
|
|
Still, I think you have a problem.
The delta between -32760 and + 32760 is too big to fit into a signed integer.
You could change the delta variable to type unsigned, but then it would only work for a positive delta value (32760 - (-32760)) and fail for the delta in the other direction.
Easiest fix is to change delta to an int32. |
|
|
mojsa2000
Joined: 18 May 2010 Posts: 78
|
|
Posted: Wed Oct 19, 2011 2:08 pm |
|
|
Thanks for your attention.
I did it and it worked. I define a variable as signed int32 that supports -32760 to 32760. Then by "type casting", I did subtraction as you see.
Thanks again. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Oct 19, 2011 7:45 pm |
|
|
think you will find ....
Quote: | a variable as signed int32 that supports -32760 to 32760 |
that a signed int32 will hold MUCH Bigger values than that ..... |
|
|
|
|
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
|