CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

writing and reading internal registers

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
aruna1



Joined: 14 Oct 2008
Posts: 103

View user's profile Send private message

writing and reading internal registers
PostPosted: Mon Jun 13, 2011 9:42 pm     Reply with quote

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: 19359

View user's profile Send private message

PostPosted: Tue Jun 14, 2011 2:19 am     Reply with 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
aruna1



Joined: 14 Oct 2008
Posts: 103

View user's profile Send private message

thank you
PostPosted: Tue Jun 14, 2011 2:26 am     Reply with quote

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

View user's profile Send private message Send e-mail

Why can't you use bit test operation?
PostPosted: Tue Jun 14, 2011 9:35 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jun 14, 2011 9:37 am     Reply with quote

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

View user's profile Send private message

Re: thank you
PostPosted: Tue Jun 14, 2011 10:04 am     Reply with quote

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

View user's profile Send private message

Re: thank you
PostPosted: Tue Jun 14, 2011 10:09 am     Reply with quote

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 Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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