View previous topic :: View next topic |
Author |
Message |
davidd
Joined: 30 Sep 2010 Posts: 38
|
16 bit pointer question |
Posted: Thu Feb 25, 2016 10:22 am |
|
|
Hello All,
The following function operates normally 1st and 2nd function in. But *tensdigit value is showing 0 with function placed third function in. The function works fine if the pointers are 8 bit.
yes I am using #device *=16
Question in general: How do I know when to start using 16 bit pointers.
pic18F46k22 with 3896 RAM -- can only use 256 spots with 8-bit pointers?
ver 5.045
Code: |
void dec_to_2digit(int16 *tensdigit, int16 *onesdigit, int8 int_number){
*tensdigit = 0;
*onesdigit = 0;
while (int_number >= 10){
int_number -= 10;
(*tensdigit)++;
}
*onesdigit = int_number;
return;
} |
thanks,
Davidd |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Feb 25, 2016 10:45 am |
|
|
comments..
1) don't think you need the device *=16 for the 18 series PICs..
2) why int16 for *tensdigit, *onesdigit ? Int_number can only be from 0 to 255 if unsigned, -128 to 127 if signed. You also don't decode the hundreds digit so I'm at a loss to understand what you really want unless int_number is only valid for say 00-99 ?. If true 'tensdigit'can only be 0-9, so an unsigned int8.
Would appreciate more info on what you're trying to do.
input ( range) ---------> function-----------variables
I'm thinking you have 00-99--->and it gets 'parsed' to 9,9
45 parses to 4,5 ?
Jay |
|
|
davidd
Joined: 30 Sep 2010 Posts: 38
|
|
Posted: Thu Feb 25, 2016 11:15 am |
|
|
Thanks Jay,
This particular function is servicing clock digits so yes indeed it is handling 00-59 actually.
I guess I'm not understanding the 16 bit pointer usage. I assumed that even though the actual variables are 8-bit, if the variables were stored in higher ram locations I would need to declare INT16 *ptr because the addresses wouldn't fit in INT8 *ptr. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Feb 25, 2016 11:22 am |
|
|
OK...I'm NOT a 'C' guy but why not just use 'regular' variables instead of 'pointed' ones? Heck most of my programs use global variables even though 'local' ones are supposed to be 'better'. I've never run out of RAM on the 46K22, if I was getting close, then I'd do the 'local' stuff.
The last project was an updated version of the 'monodigicron' clock using the 46K22 and a single 8" tall LED digit.Way overkill but .... it works !
Jay |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Feb 25, 2016 12:27 pm |
|
|
PCM_PROGRAMMER donated these routines to the code library.
his work is uniformly excllent IMHO and it may prove to be of benefit to you.
Code: |
/----------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.
int8 bin2bcd(int8 value) {
char retval;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(value >= 10)
{
value -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += value;
break;
}
}
return(retval);
}
//----------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.
char bcd2bin(char bcd_value) {
char temp;
temp = bcd_value;
// Shifting the upper digit right by 1 is
// the same as multiplying it by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
} |
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Thu Feb 25, 2016 12:32 pm |
|
|
davidd wrote: | Thanks Jay,
This particular function is servicing clock digits so yes indeed it is handling 00-59 actually.
I guess I'm not understanding the 16 bit pointer usage. I assumed that even though the actual variables are 8-bit, if the variables were stored in higher ram locations I would need to declare INT16 *ptr because the addresses wouldn't fit in INT8 *ptr. |
I'm not that well versed with pointers, but I'm pretty sure that when you declare an int8 *ptr, it just means that the pointer ptr points to a byte (int8) in RAM. Declaring int16 *ptr means that the pointer ptr points to a word (int16) in RAM. It has nothing to do with the size of the pointer itself. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Feb 25, 2016 12:39 pm |
|
|
Newguy is right.
Declaring a pointer as int16*, just means that when you write a value, it'll be written to where the pointer points, and to the next location in memory. So if the pointers are to 8bit variables, the code will destroy the next location/variable in memory as well.... Not what you want. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Feb 26, 2016 2:27 am |
|
|
He is just splitting an int8, into two digits. In a horribly complex way...
Code: |
//ensure <stdlib.h> is included before using this
void dec_to_2digit(int8 *tensdigit, int8 *onesdigit, int8 int_number)
//The declaration here does _[u]not[/u]_ affect the size of the pointer
//It changes what the pointer is deemed to point 'to'.
//These are single digits, so only need/use int8 storage
{
div_t idiv;
idiv=div(int_number,10);
*onesdigit=idiv.rem;
*tensdigit=idiv.quot;
}
|
The div function is specifically 'there' to do exactly this type of thing, giving you access to the quotient and remainder from a division. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Feb 26, 2016 2:57 am |
|
|
To try to get this clear, I've put together a crude demo program:
Code: |
#include <18F4520.h>
#device ADC=10
#fuses INTRC_IO,NOWDT,NOLVP,NOXINST
#use delay(Internal=4MHz)
#use rs232(UART1, ERRORS, baud=9600) //Basic UART setup
void demo_function8(int8 * data)
{
//write a value to an 8bit variable pointed to by 'data'
*data = 0x55;
}
void demo_function16(int16 * data)
{
//write a value to a 16bit variable pointed to by 'data'
*data = 0x55;
}
#define INIT_ARRAY() for (ctr=0;ctr<4;ctr++) test_array[ctr]=ctr+1
//initialise array with 1 to 4
#define PRINT_ARRAY() printf("%2x %2x %2x %2x\n\r",test_array[0],test_array[1],test_array[2],test_array[3])
void main()
{
int8 test_array[4];
int8 ctr;
int8 *ptr8;
int16 *ptr16;
INIT_ARRAY(); //initilise the array to 1 to 4
//Now watch what using a pointer to a 8bit value does
demo_function8(test_array);
PRINT_ARRAY();
//Print the four bytes. Note only one has changed
//Now repat with a pointer to a 16bit variable
INIT_ARRAY(); //initilise the array to 1 to 4
//Now watch what using a pointer to a 16bit value does
demo_function16(test_array);
PRINT_ARRAY();
//Print the four bytes from the array. Note _2_ bytes have changed.
//Now display the _size_ of the pointers
printf("8bit pointer size is %2x\n\r",sizeof(ptr8));
printf("16bit pointer size is %2x\n\r",sizeof(ptr16));
while(TRUE)
{
}
}
|
Running this, you get:
Code: |
55 02 03 04
55 00 03 04
8bit pointer size is 02
16bit pointer size is 02
|
When you declare the pointer to be to an int16, the routine writes 'to' an int16, so 0x0055 gets transferred to the buffer. When it points to an int8, only '0x55' gets transferred. The size of the pointer is the same in both cases. |
|
|
davidd
Joined: 30 Sep 2010 Posts: 38
|
|
Posted: Fri Feb 26, 2016 6:35 am |
|
|
very good explanation!
Thanks Ttelmah, Thanks everyone! |
|
|
avatarengineer
Joined: 13 May 2013 Posts: 51 Location: Arizona
|
pointers |
Posted: Mon Feb 29, 2016 10:21 am |
|
|
It seems to me that using pointers "now-a-days" is akin to peek and poke of the "olden-days".
Unless I'm managing large amounts of dynamic memory that I've mapped and need to reallocate during runtime,
it's difficult to find code advantages in using them.
CCS has many built-ins and so I rarely find pointers that helpful.
In the original example above, I might have just used a union of a word + 2 bytes + 16bits within and played swap games or bit shifts.
It all depends on the goal. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Feb 29, 2016 12:17 pm |
|
|
pointers IMHO, while perhaps not obviously useful with SIMPLE vars,
can be a great help when dealing with strings, and more complicated data structures such as multi-element arrays where passing by direct reference is awkward or inefficient in use of scratch ram AND CPU cycles
as an example look at the MEM** family OR the two ROTATE_() functions in the CCS manual --
and show how passing by direct reference would be better for any of these.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Mon Feb 29, 2016 3:19 pm |
|
|
and (of course), if you are using arrays, you are actually using pointers all the time.
Pointers are a fundamental part of C. |
|
|
|