View previous topic :: View next topic |
Author |
Message |
thomasj50
Joined: 23 Aug 2006 Posts: 19
|
Strange data from input function |
Posted: Sat Nov 18, 2006 1:35 am |
|
|
Hi, I use an input function call to read a digital pin and assign the result to a 16 bit int. When the pin is high sometimes I get a value different from 1; see the following small code snippet:
int16 val;
val = input(PIN_A4);
printf("val = %lu\n\r", val);
Recent results are 257 (0x0101) and 20481 (0x5001) - it seems that the top 8 bits are not masked out somehow, and since they vary perhaps they represent other input bits on the same port (they are connected to custom hardware and vary with the state of the system). If I mask the result with 0xff the function results the data as expected. I use a PIC18LF158 with compiler version 4.014. Perhaps someone out there can try this and study the list file - I don't know enough of PIC assembler to do this myself I'm afraid :-)
Best Regards,
Thomas Johansson |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
Posted: Sat Nov 18, 2006 7:21 am |
|
|
According to the manual (current manual page 155) the input() function is a digital function and returns the pin state as True or False. It is not an A/D function. Therefore any value greater than zero is actually just an indication of TRUE.
By definition a DIGITAL input can only be high or low (1 or 0). An ANALOG input value can can vary between zero and the maximum resolution of the A/D converter (255, 1024 etc.).
regards |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Sat Nov 18, 2006 7:38 am |
|
|
I'm just curious, why are you storing a bit value in an int16?
If that is truly what you're after, why not:
Code: |
int16 val;
if(input(PIN_A4))
{
bit_set(val,0); //<--- I think that's the proper syntax
}
else
{
bit_clear(val,0);
}
printf("val = %lu\n\r", val);
|
I'm sure there is a better way to mask the value into your int16. But this at least gives you an idea...
I'm not sure whether your experiences are a v4 problem, a CCS feature in general, or a C issue. One of the pros will be able to explain it and offer some better advice.
Share with the forum why you are doing what you are doing and they'll be able to offer better advice.
John |
|
|
thomasj50
Joined: 23 Aug 2006 Posts: 19
|
|
Posted: Sat Nov 18, 2006 8:38 am |
|
|
dyeatman - Yes, I know that a value different from 0 is regarded as a TRUE value, but my point is that the compiler help (and the manual) states that the return value should be either zero or one, and nothing else. In this case I use the value to test whether a certain signal is active and it does not matter if the true value is 1 or 257 - but it differs from what the function is supposed to return.
As you note yourself - a digital input can only be high or low (1 or 0), so I find it reasonable that the function should return only a one or a zero value.
Regarding the question why I store a bit value in a 16 bit integer - the variable is part of a structure composed mostly of 16 bit ints, mainly because the serial protocol used to read and write values to the struct is independent of what the value represents - it reads/writes 16 bits to a variable depending on its position in the struct, and to avoid a special case I treat booleans as 16 bit integers. To find the right place I use a union with an array of int16 (could have used pointer arithmetic, but I teach Java at the university and it's a personal thing :-). Why I dont use an array in the first place is beacuse the actual type of the values are not the same, specfically some are signed, some not, and there are actually a pair of 32 bit values in there too.
To sum up, I just wanted a digital function to return a 0/1 value as stated in the manual, and wondered if this is a compiler bug. (Actually I was just annoyed with the value 20481 showing up in a text box in the pc control program when it should have been a one :-)
Best Regards,
thomas Johansson |
|
|
SimpleAsPossible
Joined: 19 Jun 2004 Posts: 21
|
|
Posted: Sat Nov 18, 2006 10:09 am |
|
|
I looked at a listing file. The compiler defines two consecutive bytes for val. Then, for the call to input() it clears the low byte, tests the input pin and if it is low skips an opcode that increments the low byte. So you always get a 1 or a 0 in the low byte. Since it doesn't appear to clear the high byte, try adding:
before the call to input(), and see if it works. If this is happening, your high byte is left over from whatever code used this memory location before (I'm assuming val is an automatic variable).
May be a compiler "bug"? (depends on your definition of bug...)
On a style note, I prefer "\r\n" to "\n\r" since I always say "carriage return line feed." |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 18, 2006 11:36 am |
|
|
Quote: | I use a PIC18LF158 with compiler version 4.014. |
I don't have 4.014 on the system I'm on, so I tested it with vs. 3.249.
Also I compiled it for an 18F458, since there is no 'LF158'.
There is a problem if you put the result into an int16 variable.
I think the input() function expects that you will store the result in a
byte or an int1 variable. To put it in an int16, you need to cast the
result, as shown below:
Code: | val = (int16)input(PIN_A4); |
|
|
|
thomasj50
Joined: 23 Aug 2006 Posts: 19
|
|
Posted: Sat Nov 18, 2006 3:02 pm |
|
|
Thanks for the help on this, I wanted to be sure my brain wasn't on the fritz. This is actually the second 'compiler malfunction' I found this week, and I started to have some doubts ... :-)
The PIC I use is a 18LF258, I made a typo there.
Best Regards,
Thomas Johansson |
|
|
|