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 CCS Technical Support

Read User ID memory words

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



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

Read User ID memory words
PostPosted: Wed Sep 23, 2015 6:29 am     Reply with quote

I would like to write an serial number in the User ID memory which I would like to transfer through RS232, but unfortunately I can't get it working.

As I read the CCS manual the read_configuration_memory() is only for 18F controllers and with the read_program_memory it will not work for me.

Code:

#include <16F1824.H>

#FUSES INTRC_IO,NOWDT
#FUSES PUT,NOMCLR,NOPROTECT,NOCPD,BROWNOUT,BORV25                             
#FUSES NOCLKOUT,NOIESO
#FUSES NOFCMEN,WRT
#FUSES PLL_SW,NOSTVREN,NODEBUG,NOLVP
#Device ADC=8
#use delay(clock=8000000)

#use rs232(baud=9600, xmit = PIN_A0)             

#define user_id 0x8000

#rom 0x8000={0x3F01}    // maximaal bereik is 3FFF hex
#rom 0x8001={0x3F02}    //   
#rom 0x8002={0x3F03}    //
#rom 0x8003={0x3F04}

int serialnumber1, serialnumber2, serialnumber3, serialnumber4, serialnumber5, serialnumber6, serialnumber7, serialnumber8;
int userid_serialnumber1, userid_serialnumber2, userid_serialnumber3, userid_serialnumber4, userid_serialnumber5, userid_serialnumber6, userid_serialnumber7, userid_serialnumber8;

struct twobytes
{
     int8 l;
     int8 h;
};

union prog_mem
{
     int16 word;
     struct twobytes b;
};

void main()
{

struct
{
 union prog_mem userid_serialnumber1;
 union prog_mem userid_serialnumber2;
 union prog_mem userid_serialnumber3;
 union prog_mem userid_serialnumber4;
 union prog_mem userid_serialnumber5;
 union prog_mem userid_serialnumber6;
 union prog_mem userid_serialnumber7;
 union prog_mem userid_serialnumber8;



} values;

read_program_memory(user_id, &values, 8);

serialnumber1 = values.userid_serialnumber1.b.l;
serialnumber2 = values.userid_serialnumber2.b.l;
serialnumber3 = values.userid_serialnumber3.b.l;
serialnumber4 = values.userid_serialnumber4.b.l;
serialnumber5 = values.userid_serialnumber5.b.l;
serialnumber6 = values.userid_serialnumber6.b.l;
serialnumber7 = values.userid_serialnumber7.b.l;
serialnumber8 = values.userid_serialnumber8.b.l;

printf("%u ", serialnumber1);
printf("%u ", serialnumber2);
printf("%u ", serialnumber3);
printf("%u ", serialnumber4);
printf("%u ", serialnumber5);
printf("%u ", serialnumber6);
printf("%u ", serialnumber7);
printf("%u ", serialnumber8);
}



With the HEF this sort of programming worked for me. But why is the address 8000 not working for me?

In CCS-load I can see the values correct in the configuration ID section.

I receive the following numbers: 136 0 0 255 251 255 127 194

Anyone a idea what I do wrong?

CCS version: 5.026
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Wed Sep 23, 2015 8:13 am     Reply with quote

Read the manual again. You will find the read_configuration memory function, is for PIC18, _and enhanced PIC16_ devices. Yours is such a device.

You only have 4 words of user ID (not the 8 you are trying to access).
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 12:56 am     Reply with quote

I know I have only 4 bytes, but I thought that it doesn't matter if I read 8 bytes. Just to be sure I had more info to debug.

I also tried the read_configuration_memory(); function, but I receive an error 12 (undefined identifier) on that function. Is that because of my CCS version, 5.026?
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 1:29 am     Reply with quote

Probably. It exists in the current releases for your chip.

Shouldn't matter to 'read' the extra, but does matter if you try to write. If you look at the table in the data sheet, there is only write access for the first four words.
The key point is that the CGFS bit has to be set to access these locations, which the read_program_memory function won't do. The EEADR register only holds a 15bit address, so can't access 0x8000.

Simplest answer, just code your own function:
Code:

#byte EEADRL=getenv("SFR:EEADRL")
#byte EEADRH=getenv("SFR:EEADRH")
#bit CFGS=getenv("BIT:CFGS")
#bit RD=getenv("BIT:RD")
#word EEDAT=getenv("SFR:EEDATL")
#bit EEPGD=getenv("BIT:EEPGD")

int16 read_ID_word(int8 offset)
{

   EEADRL=offset; //must be 0 to 8 only
   EEADRH=0;
   EEPGD=TRUE;
   CFGS=TRUE;
   disable_interrupts(GLOBAL); //ensure interrupts are disabled for read
   RD=TRUE; //initiate read vyte
   delay_cycles(1); //NOP
   delay_cycles(1);
   enable_interrupts(GLOBAL);
   return EEDAT;
}


Should be close to right (look at example 11-3 in the data sheet).


Last edited by Ttelmah on Thu Sep 24, 2015 7:01 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 1:35 am     Reply with quote

I see that Ttelmah posted while I was typing. I'll post this anyway.

This program compiles with no errors with compiler vs. 5.049:
Code:
#include <16F1824.H>
#fuses INTRC_IO, NOWDT
#use delay(clock=8M)

//===========================
void main()
{
int8 buffer[8];

read_configuration_memory(buffer, 8);

while(TRUE);   
}


Here is the ASM code, if you wanted to use it as a guide
to write your own routine:
Code:

@READ_CONFIGURATION_MEMORY:

0003:  MOVLB  03
0004:  BSF    EECON1.CFGS
0005:  MOVLB  00
0006:  MOVF   @READ_CONFIGURATION_MEMORY.P2,W
0007:  MOVWF  @77
0008:  BCF    STATUS.C
0009:  INCF   @77,F
000A:  RRF    @77,F
000B:  MOVLB  03
000C:  BSF    EECON1.EEPGD
000D:  BSF    EECON1.RD
000E:  NOP
000F:  NOP
0010:  MOVF   EEDATL,W
0011:  MOVWF  INDF0
0012:  ADDFSR 01,FSR0
0013:  MOVF   EEDATH,W
0014:  MOVWF  INDF0
0015:  ADDFSR 01,FSR0
0016:  INCF   EEADRL,F
0017:  BTFSC  STATUS.Z
0018:  INCF   EEADRH,F
0019:  DECFSZ @77,F
001A:  GOTO   00D
001B:  BCF    EECON1.CFGS
001C:  MOVLP  00
001D:  MOVLB  00
001E:  GOTO   035 (RETURN)
.................... 

.................... void main() 
{
.
.
.
.................... read_configuration_memory(buffer, 8); 
002A:  MOVLB  03
002B:  CLRF   EEADRH
002C:  CLRF   EEADRL
002D:  MOVLW  buffer+-1
002E:  MOVWF  FSR0H
002F:  MOVLW  buffer+-32
0030:  MOVWF  FSR0L
0031:  MOVLW  08
0032:  MOVLB  00
0033:  MOVWF  @READ_CONFIGURATION_MEMORY.P2
0034:  GOTO   @READ_CONFIGURATION_MEMORY



.................... while(TRUE);     
0035:  GOTO   035
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 7:19 am     Reply with quote

Now, we hit the question of whether MPLAB (8.92) correctly simulates this....

The following code:
Code:

#include <16F1824.H>

#FUSES INTRC_IO,NOWDT
#FUSES PUT,NOMCLR,NOPROTECT,NOCPD,BROWNOUT,BORV25                             
#FUSES NOCLKOUT,NOIESO
#FUSES NOFCMEN,WRT
#FUSES PLL_SW,STVREN,NODEBUG,NOLVP
#Device ADC=8
#use delay(clock=8000000)

#use rs232(baud=9600, xmit = PIN_A0)             

#define user_id 0x8000

#rom user_id={0x0001,0x0002,0x0003,0x0004}    // maximaal bereik is 3FFF hex

#byte EEADRL=getenv("SFR:EEADRL")
#byte EEADRH=getenv("SFR:EEADRH")
#bit CFGS=getenv("BIT:CFGS")
#bit RD=getenv("BIT:RD")
#word EEDAT=getenv("SFR:EEDATL")
#bit EEPGD=getenv("BIT:EEPGD")

int16 read_ID_word(int8 offset)
{

   EEADRL=offset; //must be 0 to 8 only
   EEADRH=0;
   CFGS=TRUE;
   EEPGD=TRUE; //data sheet does not show this - needed.....
   disable_interrupts(GLOBAL); //ensure interrupts are disabled for read
   RD=TRUE; //initiate read byte
   delay_cycles(1); //NOP
   delay_cycles(1);
   enable_interrupts(GLOBAL);
   return EEDAT;
}

struct twobytes
{
     int8 l;
     int8 h;
};

union prog_mem
{
     int16 word;
     struct twobytes b;
};

void main()
{

   struct
   {
      union prog_mem userid_serialnumber[4];
   } values;
   int ctr;
   for (ctr=0;ctr<4;ctr++)
      values.userid_serialnumber[ctr].word=read_ID_word(ctr);

   for (ctr=0;ctr<4;ctr++)
      printf("%u ", values.userid_serialnumber[ctr].b.l);

   while(TRUE)
      ;
}

Correctly sets every bit in the EECON1 register and triggers the read. However in MPLAB 8.92 simulator, it returns the bytes from the start of program memory, not the config memory (CFGS is set).

Using the read_configuration_memory function on a current compiler, does exactly the same. So it looks as if MPLAB SIM, does not correctly implement this. So 'beware' if testing this.....
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 8:43 am     Reply with quote

Thanks for your effort Ttelmah and PCM programmer.

It was not my intention to write to the ID section, only read.

I've looked in the compiler update and found this:

5.027 read/write_configuration_memory() now work on the ID area in Enhanced 16 chips

So my version is unfortunately too old for the read_configuration memory function.

I've tried Ttelmah's test program and at this moment I read 3FFF instead of 3F01, this is not the right value, but is a better value then I had before.

Is it correct to write EEDAT to RS232?

I've used the function as follows:

Code:

read_ID_word(0); //no offset

printf("%Lu ", EEDAT);



Do I have to set an address (8000) somewhere? Or is this what you mean in your last post?
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Sep 24, 2015 9:11 am     Reply with quote

The function returns the word it reads.
So:
Code:

printf("%Lu ",read_ID_word(0));

The point I found was that both using the CCS function, and mine, running in the simulator (haven't got that chip at the moment), it returned the value from the bottom of the program memory, rather than the config....
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Sep 25, 2015 6:34 am     Reply with quote

Yes, it works and I understand it, thanks.

I've also bought the 1 year maintenance renewal again, this is the second problem where the older version of the compiler makes trouble (also with the HEF).

One final question (but it is more a general C question):

If I would like to use your function in a different .c file which is attached to my main.c file, how can I access your function. If I write "printf("%Lu ",read_ID_word(0));" in the other .c file it creates a "error12 Undefined identifier".
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Sep 25, 2015 8:43 am     Reply with quote

Just #include "different_file.c" before using it.
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Oct 19, 2015 7:41 am     Reply with quote

I think I find another bug in the compiler (5.050).

The getenv from the CFGS bit (EECON1 register) isn't compiled correct.

Code:
#bit    CFGS = 195.6
....................    CFGS=TRUE; 
0062:  MOVLB  01
0063:  BSF    43.6


Code:
#bit    CFGS =  getenv("bit:CFGS")
....................    CFGS=TRUE; 
0062:  BSF    15.6


The getenv function doesn't change the bank I think, therefore the getenv doesn't work.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 19, 2015 9:23 am     Reply with quote

Quote:
I think I find another bug in the compiler (5.050).
The getenv from the CFGS bit (EECON1 register) isn't compiled correct.

I tried it and it works for me. It changes to Bank 3 correctly below.
This is with compiler vs. 5.050:
Code:

.................... void main() 
0003:  MOVLW  6A
0004:  MOVLB  01
0005:  MOVWF  OSCCON
0006:  MOVLB  03
0007:  CLRF   ANSELA
0008:  CLRF   ANSELC
0009:  MOVLB  02
000A:  CLRF   CM1CON1
000B:  CLRF   CM1CON0
000C:  CLRF   CM2CON1
000D:  CLRF   CM2CON0
.................... { 
.................... 
.................... CFGS=TRUE;
000E:  MOVLB  03                    // Sets bank 3 correctly
000F:  BSF    EECON1.CFGS
.................... 
.................... while(1); 
0010:  GOTO   010
.................... }   
....................   
0011:  SLEEP

Test program:
Code:

#include <16F1824.H>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)

#bit    CFGS =  getenv("bit:CFGS")

//===================================
void main()
{

CFGS=TRUE;

while(1);
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Oct 22, 2015 3:06 am     Reply with quote

Ok, strange that the program act different if I change from the getenv(CFGS) to the 195.6 line. But I've locate the problem a bit more. The problem I have is related to the CFGS bit and the read_eeprom() function.

The read_id_word() function from Ttelmah:
Code:
int16 read_ID_word(int8 offset)
{

   EEADRL=offset; //must be 0 to 8 only
   EEADRH=0;
   CFGS=TRUE;
   disable_interrupts(GLOBAL); //ensure interrupts are disabled for read
   RD=TRUE; //initiate read vyte
   delay_cycles(1); //NOP
   delay_cycles(1);
   enable_interrupts(GLOBAL);
   return EEDAT;
}


overrules the read_eeprom function in a kind of way so they don't work together, but only seperately. If I disable the CFGS=true line or the read_eeprom() line in my program they act correct, but together they don't.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Oct 22, 2015 3:44 am     Reply with quote

Simple.

Set CFGS back to FALSE at the end of the function.

Problem is that read_eeprom is _assuming_ that CFGS (which is the flag to say 'I want to talk to the configuration memory'), is set to 'FALSE' already when it is called. Silly programming.
You need CFGS set to TRUE, or the routine won't talk to the configuration memory...
mvanvliet



Joined: 02 Jun 2009
Posts: 123
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Oct 22, 2015 4:28 am     Reply with quote

Good idea to set the CFGS false after the function, I didn't thought about that. Rolling Eyes
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