another thing i need reminding of is do i need to set the pin as input or output ? I'm disabling the pin's digital register in my channel select function as it saves power apparently
multiple ways to skin a cat :
method 1:
define a 16 bit variable.
then create a pointer to that variable
write adcl to pointer, increment pointer write adh to pointer
read 16 bit number.
method 2 : create a structure of two bytes. obtain pointer to structure , read a 16 bit number from pointer address.
method 3: (my preferred one , but the language / compiler must have such capability)
#pragma location = 0x100
byte lsb;
#pragma location = 0x101
byte msb;
#pragma location = 0x100
int16 sixteenbit;
lsb and msb are two bytes , sixteenbit is .. well .. what it says.
lsb = 0x55
msb = 0xaa
print sixteenbit gives 0xaa55
it also works in reverse. throw some 16 bit value in 'sixteenbit' and you can snatch msb and lsb directly
the advantage is that it takes ZERO cpu instructions. it is memory operations
disadvantage : you need to know a bit about memroy layout of the cpu
another thing i need reminding of is do i need to set the pin as input or output ? I'm disabling the pin's digital register in my channel select function as it saves power apparently
Right! Simply set the ADC pin to HiZ mode (set the pin in the DDR and PORT registers to zero, or if PUD is set only set DDR to zero).
but doesn't
result |= (ADCH<<8);
mean that the ADCH can get lost unless it is treated as 16 bit ?
Not quite. What actually happens is that ADCH will get promoted to an int (which should be a 16-bit signed integer on an 8-bit processor) before the shift. So as long as ADCH < 128 this is actually fine (although I still wouldn't recommend it). If ADCH >= 128, this triggers undefined behavior, which you should never ever let happen (even if you would probably get away with it in this instance). You could do this instead:
result |= (uint16_t)ADCH << 8;
multiple ways to skin a cat :
method 1:
define a 16 bit variable.
then create a pointer to that variable
write adcl to pointer, increment pointer write adh to pointer
read 16 bit number.
method 2 : create a structure of two bytes. obtain pointer to structure , read a 16 bit number from pointer address.
method 3: (my preferred one , but the language / compiler must have such capability)
#pragma location = 0x100
byte lsb;
#pragma location = 0x101
byte msb;
#pragma location = 0x100
int16 sixteenbit;
lsb and msb are two bytes , sixteenbit is .. well .. what it says.
lsb = 0x55
msb = 0xaa
print sixteenbit gives 0xaa55
it also works in reverse. throw some 16 bit value in 'sixteenbit' and you can snatch msb and lsb directly
the advantage is that it takes ZERO cpu instructions. it is memory operations
disadvantage : you need to know a bit about memroy layout of the cpu
There's no need to write such platform/compiler-specific and error-prone code in the 21st century. Modern compilers have no trouble translating a little bit of bit-shifting into efficient object code.
I'll stick with what I have as I'm yet to understand pointers etc.
Free electron, on avr the high and low bytes of a register need to be read in a certain order for atomicity. C does not guarantee the that order (it's about reading order, not memory address order)
Free electron, on avr the high and low bytes of a register need to be read in a certain order for atomicity. C does not guarantee the that order (it's about reading order, not memory address order)
avr-gcc will read the registers in the correct order.