Loading integers into EEPROM from CSV file.

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Been using strings but never retrieved data from CSV file.

Example of a string in the format "123,485,1023,28,876,1010,52,542". These are sent from Laptop to the device using RS232.

How do I retrieve these number and load it into EEPROM.

 

Once the numbers are retrieved as string can be converted to integer using atoi. Later can be stored in EEPROM. Main issue is from the CSV file.

 

Thanking you

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) Always post the toolchain and MCU you're using( also clk source and frequency ), in your OP.

2) Get the entire string into the MCU, then begin to parse it.

3) Study the strtok(), which will allow you to use the comma to parse each #into a temp VAR .

4) Convert using atoi()

5) Study the eeprom functions for your toolchain, and use those to store to it.

 

There are howto's in the Tutorial forum on how to receive chars and strings(IIRC), using UARTs, and also on using eeprom()'s ( if using GCC tools ).

I also suggest using search function here and on the internet for examples on receiving strings with a UART, as further help guidance and examples on doing this.

 

 

Jerome

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

Last Edited: Wed. Jan 23, 2019 - 09:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

K.Chandramohan wrote:
How do I retrieve these number and load it into EEPROM.

#include <avr/io.h>
#include <avr/eeprom.h>

uint16_t EEMEM EEdata[8];
uint16_t RAMdata[8];

char testInput[] = "123,485,1023,28,876,1010,52,542";

int main(void) {
    char * p;
    uint8_t i = 0;

    // assume UART routne has delivered testInput[]
    p = strtok(testInput, ",");
    while (p != NULL) {
        RAMdata[i++] = atoi(p);
        // check i for exceeding number of elements in data[]

        p = strtok(NULL, ",");
    }
    eeprom_update_block(EEData, RAMdata, 8 * sizeof(uint16_t));
}

In this I actually store the data in a RAM copy of the array then write (well update) the whole thing at the end in one block write. You might choose, instead, to reduce RAM usage and write the EEPROM array an element at a time perhaps? That might look something like:

#include <avr/io.h>
#include <avr/eeprom.h>

uint16_t EEMEM EEdata[8];

char testInput[] = "123,485,1023,28,876,1010,52,542";

int main(void) {
    char * p;
    uint8_t i = 0;

    // assume UART routne has delivered testInput[]
    p = strtok(testInput, ",");
    while (p != NULL) {
        eeprom_update_word(&EEdata[i], atoi(p));
        // check i for exceeding number of elements in data[]

        p = strtok(NULL, ",");
    }
}

PS taking onboard what Jerome just said I should say this example code is only for avr-gcc (the C compiler in AS7).

Last Edited: Wed. Jan 23, 2019 - 09:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A key thing to note if you are using atoi() to perform the conversion is atoi() does not have mechanisms to report invalid input or overflow to the programmer. In the case of invalid input, atoi() silently returns 0 (at least it should according to the standard, avr-libc documentation makes no mention of this). In the case of overflow, the return value is undefined.

 

If you do not trust the source of your data / are not completely confident that it is formatted correctly you should be using strtol() or stdtoul() instead to ensure the data in EEPROM is valid.

github.com/apcountryman/build-avr-gcc: a script for building avr-gcc

github.com/apcountryman/toolchain-avr-gcc: a CMake toolchain for cross compiling for the Atmel AVR family of microcontrollers

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Code snippets such as the parse loop with strok() are much easier to debug on a PC.

A PC does not have an eeprom_update_block( ) though, and the obvious options are:

- Simply outcomment or remove it.

- Add an empty function that does nothing.

- Write some functions to "emulate" the eeprom function in an array in ram.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a ton for the solution. Working fine.

 

A doubt. 8 * sizeof(uint16_t) not understood in the below line

 

eeprom_update_block(EEData, RAMdata, 8 * sizeof(uint16_t));

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My array is 8 elements. The array is of type uint16_t (I picked this as it looked the most appropriate for your example data). In the call to eeprom_update_block the third parameter is the number of BYTES. Well I know there's 8 elements and I suppose that i could guess that uint16_t were two byes each so it would be a write of 16 bytes but using sizeof(uint16_t) takes any guess work out of it. The compiler (via sizeof) knows better than I do how many bytes a uint16_t is. Now maybe this doesn't matter so much with simple integer types but suppose the array was an array of struct using some struct type that I typedef'd then it'd be far easier to use sizeof(struct_type) tban to go adding up all the bytes in the struct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It might not be clear from Clawson's post:

 

"sizeof" is a special reserved keyword in C. During preprocessing (I think) it is replaced by the number of bytes that the datatype behind it occupies in memory.

For a more comprehensive explanation, look into some of these tutorials:

https://duckduckgo.com/html?q=c+tutorial+"sizeof"

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
During preprocessing (I think)
Not during preprocessing. It is a C operator.

https://en.m.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

clawson wrote:
eeprom_update_block(EEData, RAMdata, 8 * sizeof(uint16_t));
Why not just sizeof(EEData) ?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
Why not just sizeof(EEData) ?
Catering for the case where that's not visible this file (an extern)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Catering for the case where that's not visible this file (an extern)
Fair.

 

But that requires knowledge of the type.

 

How about:

eeprom_update_block(EEData, RAMdata, 8 * sizeof(*EEData));

 

That still requires knowledge of the size of the array, but that can be communicated via either a macro:

#define EEDATA_SZ 8
uint16_t EEMEM EEdata[EEDATA_SZ]
eeprom_update_block(EEData, RAMdata, EEDATA_SZ * sizeof(*EEData));

 

... or via a constant:

#define EEDATA_SZ 8
.
.
.
const size_t EEdata_sz = EEDATA_SZ;
uint16_t EEMEM EEdata[EEdata_sz]
eeprom_update_block(EEData, RAMdata, EEdata_sz * sizeof(*EEData));

 

A good toolchain might not allocate storage for the constant.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]