|
|
View previous topic :: View next topic |
Author |
Message |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
writing and reading internal registers |
Posted: Mon Jun 13, 2011 9:42 pm |
|
|
Hi,
I'm currently working with Texas Instruments DAC8571 IC. It is a 16bit DAC with I2C interface.
I thought it is easy to send 16bit of data, if I store decimal value to int16 variable and then get high byte and low byte of that value from internal registers and directly assigned them to I2C_write(). I tried this method and its working.
My problem is, how to map this int16 variable into 2 permanent 8bit registers. In current code int16 value is stored in registers 0x27 and 0x28, but if I add a new variable or remove any variable, this Int16 variable's assigned registers also get changed.
Is there anyway to assign high byte and low byte of this int16 variable into a permanent register, that will not change every time I make an adjustment?
Below is the code so far, and my compiler version is v4.120
Code: | #include <main.h>
#include <16F877A.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B7,rcv=PIN_B6,bits=8,stream=PORT1)
#use i2c(Master,fast,sda=PIN_C6,scl=PIN_C7)
#BYTE low1 = 0x22
#BYTE val_low = 0x27
#BYTE val_high = 0x28
/* if we add or remove new variable or change variable type, internal register mapping we did above will change. therefore
we need to re map, variables as soon as we add or remove new variable*/
int c=5;
float volt=1.473; // this should be the output voltage of DAC
int16 high= 16384; // high
float frac=0;
void main()
{
WHILE(1)
{
IF ( ! input (pin_D1) )
{
frac = volt/5.08;
high= (frac*65536);
output_high (pin_D0) ; // test LED on
delay_ms (500) ;// debouncing
i2c_start () ;
i2c_write(0x98); // Device address
i2c_write(16); // control word
i2c_write(val_high); // high byte
i2c_write(val_low); // low byte
i2c_stop();
output_low(pin_D0); // test LED off
printf("\nhigh= %Lu \r",high);
printf("\nhigh1= %U \r",val_low);
printf("\nhigh2= %U \r",val_high);
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Jun 14, 2011 2:19 am |
|
|
#byte
#word
These allows you to locate a variable (or create a byte or word sized one), at a specific location. So:
Code: |
int16 fred;
#byte fred=0x27
//variable 'fred' will now be located at memory location 0x27, and 0x28
//or
#word fred=0x27
//variable 'fred' is created as a 16bit variable and placed at locations 0x27
//& 0x28
|
With #byte you can locate _any_ type of variable at a location, so you could create a complete 'structure', then place it at a specific location. #word is effectively like a macro version of #byte that automatically creates a 16bit variable and then locates it.
Best Wishes |
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
thank you |
Posted: Tue Jun 14, 2011 2:26 am |
|
|
Quote: | #byte
#word
These allows you to locate a variable (or create a byte or word sized one), at a specific location. So:
Code:
int16 fred;
#byte fred=0x27
//variable 'fred' will now be located at memory location 0x27, and 0x28
//or
#word fred=0x27
//variable 'fred' is created as a 16bit variable and placed at locations 0x27
//& 0x28
With #byte you can locate _any_ type of variable at a location, so you could create a complete 'structure', then place it at a specific location. #word is effectively like a macro version of #byte that automatically creates a 16bit variable and then locates it.
Best Wishes |
thank you Ttelmah I will try this.
I also found that this Garibaldi location change happens only if you define a new variable above the variable we want to keep in a permanent place. If we define new variables below it or if we make permanent variable, the top most variable to be defined, problem will be gone.
EDIT:
I just tried simple code nothing but some variables.I have defined cat variable as you said and other variables as normal; but now both cat and bat variables use same register( 0x21) (look at the sym file I added below)
Code: | #include <main.h>
int horse;
int cat = 5;
#byte cat=0x21
int bat=0;
int dog=4;
void main()
{
} |
and here is the sym file content
Code: | 004-005 @READ_PROGRAM_MEMORY8.P1
004 @WRITE_PROGRAM_MEMORY8.P2
008 PSP_DATA
015 CCP_1
015 CCP_1_LOW
016 CCP_1_HIGH
01B CCP_2
01B CCP_2_LOW
01C CCP_2_HIGH
020 horse
021 cat
021 bat
022 dog
077 @SCRATCH
078 @SCRATCH
078 _RETURN_
079 @SCRATCH
07A @SCRATCH
09C.6 C1OUT
09C.7 C2OUT
10D-10E @READ_PROGRAM_MEMORY8.P1
10D-10E @WRITE_PROGRAM_MEMORY8.P2
ROM Allocation:
0004 main
0004 @cinit
User Memory space:
User Memory space:
Project Directory:
C:\Documents and Settings\Aruna\Desktop\tets\
Project Files:
main.c [14-Jun-11 14:55 CRC=00000000]
main.h [14-Jun-11 13:31 CRC=D8102B21]
..\..\..\..\Program Files\PICC\devices\16F877A.h [13-Apr-11 15:01 CRC=44AB3CC4]
Source signature=6166A4A9
Units:
C:\Documents and Settings\Aruna\Desktop\tets\main (main)
Compiler Settings:
Processor: PIC16F877A
Pointer Size: 16
ADC Range: 0-65535
Opt Level: 9
Short,Int,Long: UNSIGNED: 1,8,16
Float,Double: 32,32
Output Files:
Errors: main.err
Ext Symbols: main.esym
INHX8: main.hex
Symbols: main.sym
List: main.lst
Debug/COFF: main.cof
Project: main.PJT
Call Tree: main.tre
Statistics: main.STA |
|
|
|
Bhanu Watawana
Joined: 01 Jun 2011 Posts: 15
|
Why can't you use bit test operation? |
Posted: Tue Jun 14, 2011 9:35 am |
|
|
Macho,
Why can't you use bit_test('variable','bit number')
This doesn't need the registry address + you can run this in a simple loop for sending the data.
That's far more easy, isn't it?
CCS Help contains more on this. _________________ ~~~~~~~~~~~~~~~~
Bhanu Watawana
Uva Wellassa University
Sri Lanka |
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Tue Jun 14, 2011 9:37 am |
|
|
nope machan, this is for i2c_write() command. I have to use 8 bit integer on that. no serial data stream is possible |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Re: thank you |
Posted: Tue Jun 14, 2011 10:04 am |
|
|
aruna1 wrote: | I also found that this Garibaldi location change happens only if you define a new variable above the variable we want to keep in a permanent place. If we define new variables below it or if we make permanent variable, the top most variable to be defined, problem will be gone. | You have discovered how it works for your current compiler, but in a new version this behaviour might be totally different. Another problem is that your solution is not portable to processors having a different memory layout (PIC18, etc.).
There are several standard ways for splitting an int16 into two 8 bit values.
Method 1: Code: | int16 value;
int8 val_high, val_low;
value = 12345;
val_low = (value & 0xFF)
val_high = (value >> 8) & 0xFF; |
Method 2 uses unions, the standard C method for overlaying variables at the same memory location and results in efficient code: Code: | union joiner {
int8 b[2]
int16 w;
} Value;
Value.w = 12345;
i2c_write(Value.b[0]); // high byte
i2c_write(Value.b[1]); // low byte |
Method 3 uses the CCS specific make8() function. Just as efficient code as with unions; I think it is easier to read but it is less portable: Code: | int16 Value = 12345;
i2c_write( make8(Value,1) ); // high byte
i2c_write( make8(Value,0) ); // low byte |
|
|
|
aruna1
Joined: 14 Oct 2008 Posts: 103
|
Re: thank you |
Posted: Tue Jun 14, 2011 10:09 am |
|
|
ckielstra wrote: | aruna1 wrote: | I also found that this Garibaldi location change happens only if you define a new variable above the variable we want to keep in a permanent place. If we define new variables below it or if we make permanent variable, the top most variable to be defined, problem will be gone. | You have discovered how it works for your current compiler, but in a new version this behaviour might be totally different. Another problem is that your solution is not portable to processors having a different memory layout (PIC18, etc.).
There are several standard ways for splitting an int16 into two 8 bit values.
Method 1: Code: | int16 value;
int8 val_high, val_low;
value = 12345;
val_low = (value & 0xFF)
val_high = (value >> 8) & 0xFF; |
Method 2 uses unions, the standard C method for overlaying variables at the same memory location and results in efficient code: Code: | union joiner {
int8 b[2]
int16 w;
} Value;
Value.w = 12345;
i2c_write(Value.b[0]); // high byte
i2c_write(Value.b[1]); // low byte |
Method 3 uses the CCS specific make8() function. Just as efficient code as with unions; I think it is easier to read but it is less portable: Code: | int16 Value = 12345;
i2c_write( make8(Value,1) ); // high byte
i2c_write( make8(Value,0) ); // low byte |
|
coooool
thank you very much |
|
|
|
|
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
|