This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR5994: INTERFACING ISSUE

Part Number: MSP430FR5994

Hi.

I was trying to store and retrieve ADXL345 accelerometer data into AT24C256 EEPROM.But when i run the program some garbage values are printing on output. The accelerometer output is not storing into EEPROM.I'm sharing the piece of code please help me.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/////////////////// main.c /////////////////
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
LPM1_Clock_config();
// I2C pins
P7SEL0 |= BIT0 | BIT1;
P7SEL1 &= ~(BIT0 | BIT1);
PM5CTL0 &= ~LOCKLPM5;
// i2c Configuration
initI2C();
uart_config();
power_ctrl();
while (1)
{
int ADXL345_Dev_id, res_data,bw_data,data_format,count;
I2C_Master_ReadReg(0x53,0x32,6);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • >  sprintf(addr1,"x=%d,y=%d,z=%d\r\n",X);

    You can't use sprintf() with an array like this. One possible alternative:

    >  sprintf(addr1,"x=%d,y=%d,z=%d\r\n", X[0], X[1], X[2]);

    ----------

    How is your X[] array declared? You're writing into it using "count", which is the result of a strlen() and thus might be larger than you think.

    ----------

    I don't see any code which writes to the EEPROM.

  • No need to memset() before you use sprintf(). sprintf will append the trailing '\0'.

    Are you sure addr and addr1 are big enough to hold your strings?

  • Hi Bruce

    1) I have changed my sprintf statement as you suggested. And I'm declared my array as unsigned char X[20]; But still some values are getting and those are repeating continuously.

    2) I think writing function is not happening  1st. 

    3)I have a doubt that 1st I'm passing the string(addr) of accelerometer values to eeprom. For example lets assume values as X1=10,Y1=-40,Z=120.I'm passing these values as string therefore each number will store in each address location as 1 byte in EEPROM. So totally 9 locations EEPROM consumes including NULL. But while retrieving  How can we retrieve same data to same as X=10,Y=-40,Z=120. Or If we go with storing integers 1st values can be stored easily but it is again getting tough for storing next X,Y,Z values. So could you please suggest me weather there any better way to solve this issue?

  • That is totally up to you. I would think that storing as an integer would be better, but atoi() can convert a null terminated string to an integer.

  • Hi keith

    Even i thought the same and tried accordingly but no change in the output. First of all the data is not storing in the EEPROM i think.

  • I suggest you take a step back.

    Write a program that only stores and retrieves data from the eeprom.

    Write a program that only gets the accelerometer data

    Combine the two as required.

  • >  case TX_REG_ADDRESS_MODE:
    > if(TransmitRegAddr==0x50)

    I suspect this comparison should be with dev_addr rather than TransmitRegAddr. The data sheet (doc0670) doesn't say what happens if you only send one address byte; it may be that it is ignored, which would cause your read to start at the end of the string in the EEPROM.

    What values do you see in the  UART output? A %c format might be more appropriate. If you breakpoint at strategic spots in main (breakpointing in the i2c routines can be tricky) you can see what data you're actually working with.

    [Edit: fixed typo.]

  • Hi keith

    Yes already i have interfaced accelerometer and eeprom seperately with MSP430FR5994. I could write and read 1 integer value on EEPROM .After confirming that i have started this merging of both.But as u said i tried to write and  read 3 integers into EEPROM But the data is not writing into eeprom.I'm sharing the piece of code here please help me.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ///////////////////// main.c ///////////////////
    #include <msp430.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <i2c.h>
    uint16_t X1;
    uint16_t Y1;
    uint16_t Z1;
    //uint16_t X=Y=Z=0;
    float f=0.004;
    int device_address= 0x50;
    char addr[30]="";
    char device_id[6]="";
    char string[10]="started";
    uint8_t num[5]={27};
    uint8_t x=10;
    uint8_t y=20;
    uint8_t z=30;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Bruce

    I have compared with dev_addr only I did'nt compared with TransmitRegAddr.  I have given condition as if(dev_addr==0x53).

    I could see some values like this but these are wrong values because all these values are got when i keep the accelerometer in base. if I change the orientation values should change and also negetive values should come.If i interface only accelerometer it is working great but when i merge code with EEPEOM it is not working  and also not storing in EEPROM. 

    X=45,Y=97,Z=110
    X=100,Y=45,Z=97
    X=98,Y=99,Z=100
    X=101,Y=102,Z=103
    X=104,Y=105,Z=106
    X=107,Y=49,Z=61
    X=54,Y=44,Z=89
    X=49,Y=61,Z=49
    X=52,Y=44,Z=90
    X=49,Y=61,Z=49
    X=57,Y=50,Z=13
    X=10,Y=10,Z=13
    X=10,Y=10,Z=0
    X=0,Y=0,Z=0
     

  • When I read these values as ASCII, I see something like: "-and-abcdefghijk1=14,Z1=14,Z1=192\r\n\n\r\n".

    Some of this looks familiar, so I suspect you are writing to the EEPROM but you're not using the (EEPROM) address you think you are. What does that case statement I mentioned look like now?

    Since you're writing a string, you could try formatting X[] using "%s". Just make sure to  add the string terminator with something like X[count]='\0';

  • Hi Bruce

    I'm using EEPROM address as a function argument as 0x50  in function call and comparing the address in write and read function body to store the data. and when i use %s it is not getting the proper data 1st the data is not storing into EEPROM even though  i use the address. I tried to store integer values into EEPROM in seperate program. But in there also it is not storing. I'm sharing that code here. please help me.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //////////// main.c /////////////////
    #include <msp430.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <i2c.h>
    char* X[10];
    uint16_t X1;
    uint16_t Y1;
    uint16_t Z1;
    int device_address= 0x50;
    char addr[30]="";
    char device_id[6]="";
    int x=10;
    int y=20;
    int z=30;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     

  • >  I2C_Master_WriteReg(0x50,0x00,x,1);

    The 3rd argument to WriteReg should be a "uint8_t *"  pointer, and you're supplying it a small integer. This will write the (unknown) value found at location 10 to the EEPROM. (I'm somewhat surprised the compiler didn't issue a Warning for this.) 

    You should declare "uint8_t x" and use:

    >  I2C_Master_WriteReg(0x50,0x00,&x,1);

    Similarly for the WriteReg calls for y and z.

  • Hi Bruce

    I did as you suggested but when i see the output x and  y values are getting proper but z value is getting wrong. and when i try to store string the string is not getting store in EEPROM.So please help me 

  • Which code are we talking about? What wrong value are you getting?

    In the "string" version: Did you fix that case statement (really the if() which follows it) that I mentioned?

  • Hi Bruce

    I was talking about storing integer values in the EEPROM. I have followed the same as you said. When i pass x=10,y=20,z=30 EEPROM is storing these values. But when i pass x=100,y=200,z=300 this EEPROM is storing as x=100 y=200,z=44. And coming to the string storing code YES there also i have followed that if() statement but nothing is storing into it. What i thought was if any of these two ( interger storing version or string storing version) worked fine i will use that code on my main code. But none of them are working good.  So please help me.

  • 10,20, and 30 all fit into a byte (uint8_t), but 300 doesn't. 300(mod 256)=44.

    If you need to write/read values > 255, you should go back to uint16_t for x,y,z, and

    1) For writing, use something like:

    > I2C_Master_WriteReg(0x50,0x00,(uint8_t *)&x, 2);

    where 2=sizeof(uint16_t)

    2) For reading, you need to reconstruct the uint16_t with something like:

    I2C_Master_ReadReg(0x50,0x00,2);
    X1=ReceiveBuffer[0] | (ReceiveBuffer[1] << 8);

    since the high byte is at index [1] ("little endian").

    3) Step your EEPROM addresses by 2 rather than 1.

  • Hi Bruce

    Thankyou for your replay yes I have done the same thing 5hours back and working great but facing issue on storing string. I'm sharing the code here please help me.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ///////////////// main.c ////////////////////
    #include <msp430.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <i2c.h>
    uint16_t X1,Y1,Z1;
    char* X;
    uint16_t address1=0x00;
    uint16_t address2=0x00;
    char addr[30]="";
    char addr1[30]="";
    char device_id[6]="";
    int i,count=0,j;
    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • What issue are you seeing?

    > char* X;

    This creates a pointer (your array) to memory location 0 ("reserved" memory) which is at best hazardous. Try instead something like:

    > char X[30];  // Same size as addr[]

  • Hi Bruce 

    i could see the string while reading . I was trying to store the same string contineously and read it back. I'm passing string as "hello" But while reading the string is getting with shuffled after some sometime .I'm sharing that piece of code here please help me

     

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
    LPM1_Clock_config();
    // I2C pins
    P7SEL0 |= BIT0 | BIT1;
    P7SEL1 &= ~(BIT0 | BIT1);
    PM5CTL0 &= ~LOCKLPM5;
    // i2c Configuration
    initI2C();
    uart_config();
    while (1)
    {
    uint8_t count1;int i;
    count1=strlen(string);
    I2C_Master_WriteReg(0x50,address1,string,count1);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Can you give an example of the shuffling?

    I suspect you're encountering address wrapping (they call it "roll over"), i.e. what happens when certain addressing boundaries are reached. This is done differently for writes and reads, and is described in data sheet (doc0670) pages 10-11.

    For this reason it is usually best to work with fixed-length records whose size divides the page size (in this case 64) evenly.

  • I'm using AT24C256 EEPROM. It's maximum size is 32kb so maximum address would be 7FFF. I'm not sure weather the data  over-writes from zero'th location or not once it reaches to 7FFF location. But here as I'm incrementing the address manually that address is going beyond 7FFF and printing and wonder is the data is also printing eventhough it crossed the memory. But I'm not able to understand how and  now I'm getting a doubt that is the EEPROM storing data or not. 

    I'm passed the string as "sindhusha" and Here is the shuffled output.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    7e
    X=sindhusha
    7e
    87
    X=sidhushaa
    87
    90
    X=sindhusha
    90
    99
    X=sindhusha
    99
    a2
    X=sindhusha
    a2
    ab
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • >c6
    >X=sinhusha
    >c6

    This write crossed a page boundary. The write address wrapped, but the read address didn't. At the end of the memory (0x7FFF+1) the write and read addresses will wrap to different values. I encourage you to read pages 10-11 of the datasheet (look for "roll over").

    Something like "hello678" would probably work well.

  • ok i will read but i wanted to use sequential write and read rather using the page concept. Because i wanted to collect the data randomly on my main project so. will the sequential concept works?

  • The page concept (for writing) is imposed on you, so you need to work within it. There is no "sequential write", only "byte" and "page". These are really the same thing, except that writing a (single) byte can't cross a page boundary.

    If you need to write non-divisor-of-64-sized records, you have the option of anticipating when a write will cross a page boundary and splitting it into two transactions. This is a bit of a pain, but can be done.

    If you want to use variable-length records, you should (additionally) put some thought into how you'll find them later.

  • Hi bruce 

    I'm sorry I was using byte write and reading by using sequential read by mistake i have typed like that previously. On my main project i will store variable length only so all ways i need to track the length to store next data.One more thing can you clarify me that will the eeprom will start over-writing from address location of zero once it get filled completely?

  • A Byte Write is a Page Write with size=1. The code above uses size>1, so they are Page Writes.

    You could in theory write each string one byte (transaction size=1) at a time. You would never have to think about Page addressing, but it would be rather slow (5msec "penalty" for each byte).

    If you perform a write which Extends past the end of the current page, the address wraps back to the beginning of that page [datasheet p. 10]. That would apply to the final page in the memory as well. If you Begin a write at address (0x7FFF+1)=0x8000, that will write to address 0x0000 since the high-order address bit is ignored [datasheet Fig. 9].

  • Hi Bruce

    Now my code is working fine but I got a new doubt that I was storing data into eeprom and retrieving but I'm sure that data willl store in the eeprom when the power supply was there. But when i power off the microcontroller and re-connect again will my eeprom is capable to store data from where it stopped.

    for example lets say initially I'm storing x=10,y=20,z=30 in 0x0000,0x0001,0x0002,0x0003 and I'm incrementing the address and data in the next write cycle i.e.,x=11,y=21,z=31 in 0x0004,0x0005,0x0006.and now I have disconnected the microcontroller and re-connected  at this time I wanted to store x=12,y=22,z=32 in 0x0007,0x0008,0x0009. will this be possible? If yes can you please help me to execute this thing. when I try my eeprom is storing from 1st onwards. i.e,x=10,y=20,z=30 in 0x0000,0x0001,0x0002,0x0003. so please help me.  

  • This is in the general case a fairly complex problem. I'm not really in a position to walk you through a complete design, but here are some notions.

    The simpler methods use a memory scan at startup, finding the boundary between newer data and (a) nonsense, perhaps erased bytes, or (b) older data, if you write your data cyclically. This could take a while -- reading the entire memory takes close to a second in the best case.

    All the methods I know add extra data ("redundancy") to allow you to distinguish these cases. Consider adding 2 bytes (total (6+2) byte record). One should be a checksum/CRC to detect nonsense. The other can be used to distinguish old vs new data. A simple use might be a "generation counter" which you increment each time you fill the memory and circle back. If your scan finds a record whose counter is different from that of the previous, that indicates the boundary.

    You could speed up or avoid the startup scan by using a reserved EEPROM area that contains an index to the final record. However, this introduces a different set of complexities since you will be writing this area very often, and could wear out (exceed Write Endurance of) those EEPROM cells. (Keyword: "Wear Leveling")

    People have been doing this for a long time, and a Web search can turn up a collection of methods based on different assumptions and requirements.

  • Hi Bruce

    Can I get example code of FRAM read. I found FRAM write example code but I did'nt find FRAM read. So can you please send me some example code? 

  • If you have a new question you really should start a new thread.

    Nothing special needs to be done to read FRAM. In the Example (msp430fr599x_framwrite.c) you could reference the array FRAM_write by saying (e.g.) "int x = 1 + FRAM_write[3];". If you declare a variable "const" it is normally placed in FRAM.

    Without knowing your goal, it's hard to say more.

  • Hi,

    I'm facing an issue while interfacing storing accelerometer with eeprom while doing I could able to write and read the positive data of accelerometer but I could'nt read the negative values. Instead the negative value is getting stored as its equivalent positive value.I have searched in some sites to know how to store a negative value but i did'nt find proper matter.So can you please help me to slove this issue.I'm sharing EEPROM part of code.Write_address is 0x01.

    .

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    read_address=write_address;
    __delay_cycles(8000000);
    I2C_Master_WriteReg(0x50,write_address,X1,2);
    __delay_cycles(8000000);
    write_address=write_address+2;
    sprintf(addr,"X1=%d\r\n",X1);
    id_print(addr);
    I2C_Master_WriteReg(0x50,write_address,Y1,2);
    __delay_cycles(8000000);
    write_address=write_address+2;
    sprintf(addr,"Y1=%d\r\n",Y1);
    id_print(addr);
    I2C_Master_WriteReg(0x50,write_address,Z1,2);
    __delay_cycles(8000000);
    write_address=write_address+2;
    sprintf(addr,"Z1=%d\r\n",Z1);
    id_print(addr);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • If X1 is declared as "uint16_t", you should be able to re-interpret it as a 16-bit signed with something like:

    > int16_t signed_X1 = (int16_t)X1;

    Though if that is the case, I expect:

    >  I2C_Master_WriteReg(0x50,write_address,X1,2);

    should be

    >  I2C_Master_WriteReg(0x50,write_address,&X1,2);

**Attention** This is a public forum