Access I2C EEPROM (was Reading value from AtMega328P pin)

Go To Last Post
84 posts / 0 new

Pages

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

PsySc0rpi0n wrote:
I read your sentence. I'm just not sure what is or what could be "proper bank". I know that my IC has A0, A1 and A2 not connected internally.

Keep Reading.  It's in there.  Hint...I said Proper Bank.  THey call it Bank Select.  And you are correct, it's on page 7 wink

 

Anyway I do not have any of your EEPROMS handy but I have a X2404P sitting here that I can configure to operate just like yours does so I set up a little project and got things working.

 

Since I am familiar with your setup from your other thread I elected to make some changes to the example program to better suit your set up.

 

A couple of notes about the modifications I made:

1.  In the i2cmaster.h file I removed all of the references to the example code as it was commented out and hence confusing...so out it went.

2. in twimaster.c I changed the F_CPU to 16Mhz

3. In twimaster.c I changed SCL frequenct to 100khz

4. In the MEGA328_I2C_EEPROM file I changed the DEFINE for the device and its address to what you need for your part to work with the example.

5. In the MEGA328_I2C_EEPROM file I changed the value WRITTEN to the memory cells to something you can display on your setup

6. In the MEGA328_I2C_EEPROM file I changed the PORTB configuration to use only the lower 4 pins.  THe reason you were seeing one or two LED's come on and stay on is because they are used by the XTAL clock

7. in the MEGA328_I2C_EEPROM file I ADDED a PORTB = RET instruction and a DELAY to show the value from the reads of teh EEPROM.

 

All of these changes I made are noted in their respective files at the locations with a "//<-------jgmdesigns"  OR "<-------jgmdesigns" as a comment at the line of change.

 

The i2cmaster.h file:

#ifndef _I2CMASTER_H
#define _I2CMASTER_H
/************************************************************************* 
* Title:    C include file for the I2C master interface 
*           (i2cmaster.S or twimaster.c)
* Author:   Peter Fleury <pfleury@gmx.ch>
* File:     $Id: i2cmaster.h,v 1.12 2015/09/16 09:27:58 peter Exp $
* Software: AVR-GCC 4.x
* Target:   any AVR device
* Usage:    see Doxygen manual
**************************************************************************/

/**
 @file
 @defgroup pfleury_ic2master I2C Master library
 @code #include <i2cmaster.h> @endcode
  
 @brief I2C (TWI) Master Software Library

 Basic routines for communicating with I2C slave devices. This single master 
 implementation is limited to one bus master on the I2C bus. 

 This I2c library is implemented as a compact assembler software implementation of the I2C protocol 
 which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
 Since the API for these two implementations is exactly the same, an application can be linked either against the
 software I2C implementation or the hardware I2C implementation.

 Use 4.7k pull-up resistor on the SDA and SCL pin.
 
 Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module 
 i2cmaster.S to your target when using the software I2C implementation ! 
 
 Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.

 @note 
    The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted 
    to GNU assembler and AVR-GCC C call interface.
    Replaced the incorrect quarter period delays found in AVR300 with 
    half period delays. 
    
 @author Peter Fleury pfleury@gmx.ch  http://tinyurl.com/peterfleury
 @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
 


*/


/**@{*/

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif

#include <avr/io.h>

/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ    1

/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_WRITE   0


/**
 @brief initialize the I2C master interace. Need to be called only once 
 @return none
 */
extern void i2c_init(void);


/** 
 @brief Terminates the data transfer and releases the I2C bus 
 @return none
 */
extern void i2c_stop(void);


/** 
 @brief Issues a start condition and sends address and transfer direction 
  
 @param    addr address and transfer direction of I2C device
 @retval   0   device accessible 
 @retval   1   failed to access device 
 */
extern unsigned char i2c_start(unsigned char addr);


/**
 @brief Issues a repeated start condition and sends address and transfer direction 

 @param   addr address and transfer direction of I2C device
 @retval  0 device accessible
 @retval  1 failed to access device
 */
extern unsigned char i2c_rep_start(unsigned char addr);


/**
 @brief Issues a start condition and sends address and transfer direction 
   
 If device is busy, use ack polling to wait until device ready 
 @param    addr address and transfer direction of I2C device
 @return   none
 */
extern void i2c_start_wait(unsigned char addr);

 
/**
 @brief Send one byte to I2C device
 @param    data  byte to be transfered
 @retval   0 write successful
 @retval   1 write failed
 */
extern unsigned char i2c_write(unsigned char data);


/**
 @brief    read one byte from the I2C device, request more data from device 
 @return   byte read from I2C device
 */
extern unsigned char i2c_readAck(void);

/**
 @brief    read one byte from the I2C device, read is followed by a stop condition 
 @return   byte read from I2C device
 */
extern unsigned char i2c_readNak(void);

/** 
 @brief    read one byte from the I2C device
 
 Implemented as a macro, which calls either @ref i2c_readAck or @ref i2c_readNak
 
 @param    ack 1 send ack, request more data from device<br>
               0 send nak, read is followed by a stop condition 
 @return   byte read from I2C device
 */
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); 



/**@}*/
#endif

 

 

The twimaster.c file:

/*************************************************************************
* Title:    I2C master library using hardware TWI interface
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
* File:     $Id: twimaster.c,v 1.4 2015/01/17 12:16:05 peter Exp $
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
* Target:   any AVR device with hardware TWI 
* Usage:    API compatible with I2C Software Library i2cmaster.h
**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>

#include "i2cmaster.h"


/* define CPU frequency in hz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 16000000UL		//<---jgmdesigns changed - F_CPU value
#endif

/* I2C clock in Hz */
#define SCL_CLOCK  100000L		//<---jgmdesigns changed - LOW SPEED CLOCK


/*************************************************************************
 Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
  
  TWSR = 0;                         /* no prescaler */
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
  

}/* i2c_init */


/*************************************************************************	
  Issues a start condition and sends address and transfer direction.
  return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

	// send device address
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

	return 0;

}/* i2c_start */


/*************************************************************************
 Issues a start condition and sends address and transfer direction.
 If device is busy, use ack polling to wait until device is ready
 
 Input:   address and transfer direction of I2C device
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
    uint8_t   twst;


    while ( 1 )
    {
	    // send START condition
	    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
    	// wait until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
    
    	// send device address
    	TWDR = address;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    
    	// wail until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
    	{    	    
    	    /* device busy, send stop condition to terminate write operation */
	        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	        
	        // wait until stop condition is executed and bus released
	        while(TWCR & (1<<TWSTO));
	        
    	    continue;
    	}
    	//if( twst != TW_MT_SLA_ACK) return 1;
    	break;
     }

}/* i2c_start_wait */


/*************************************************************************
 Issues a repeated start condition and sends address and transfer direction 

 Input:   address and transfer direction of I2C device
 
 Return:  0 device accessible
          1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
    return i2c_start( address );

}/* i2c_rep_start */


/*************************************************************************
 Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
    /* send stop condition */
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	
	// wait until stop condition is executed and bus released
	while(TWCR & (1<<TWSTO));

}/* i2c_stop */


/*************************************************************************
  Send one byte to I2C device
  
  Input:    byte to be transfered
  Return:   0 write successful 
            1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{	
    uint8_t   twst;
    
	// send data to the previously addressed device
	TWDR = data;
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits
	twst = TW_STATUS & 0xF8;
	if( twst != TW_MT_DATA_ACK) return 1;
	return 0;

}/* i2c_write */


/*************************************************************************
 Read one byte from the I2C device, request more data from device 
 
 Return:  byte read from I2C device
*************************************************************************/
unsigned char i2c_readAck(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
	while(!(TWCR & (1<<TWINT)))
	;    

    return TWDR;

}/* i2c_readAck */


/*************************************************************************
 Read one byte from the I2C device, read is followed by a stop condition 
 
 Return:  byte read from I2C device
*************************************************************************/
unsigned char i2c_readNak(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)))
	;
	
    return TWDR;

}/* i2c_readNak */

 

And the main project file Mega328_I2C_EEPROM:

/*
 * Mega328_I2C_EEPROM.c
 *
 * Created: 10/30/2016 10:44:51 PM
 *  Author: jgmDESIGNS-Laptop
 */ 

#define F_CPU 16000000ul
#include <avr/io.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <avr/pgmspace.h>

#include "i2cmaster.h"


#define Dev_24LC08B  0xA0      // device address of EEPROM 24LC88, see datasheet	<---jgmdesigns changed device name and address for device - See datasheet

 

int main(void)
{
   
    unsigned char ret;

    DDRB  = 0x0f;                              // use LOWER pins on port B for output <---jgmdesigns changed PINS USED
    PORTB = 0x0f;                              // (active HIGH LED's )	<---jgmdesigns changed to ACTIVE HIGH

    i2c_init();                                // init I2C interface

    /* write 0x75 to eeprom address 0x05 (Byte Write) */
    ret = i2c_start(Dev_24LC08B+I2C_WRITE);       // set device address and write mode
    if ( ret ) {
        /* failed to issue start condition, possibly no device found */
        i2c_stop();
        PORTB=0x00;                            // activate all 8 LED to show error */
    }else {
        /* issuing start condition ok, device accessible */
        i2c_write(0x05);                       // write address = 5
        i2c_write(0x75);                       // ret=0 -> Ok, ret=1 -> no ACK 
        i2c_stop();                            // set stop conditon = release bus

        /* write ok, read value back from eeprom address 0x05, wait until 
           the device is no longer busy from the previous write operation */
        i2c_start_wait(Dev_24LC08B+I2C_WRITE);     // set device address and write mode
        i2c_write(0x05);                        // write address = 5
        i2c_rep_start(Dev_24LC08B+I2C_READ);       // set device address and read mode
        ret = i2c_readNak();                    // read one byte
        i2c_stop();
        
        PORTB = ~ret;                           // output byte on the LED's

        /* write 0x70,0x71,072,073 to eeprom address 0x00..0x03 (Page Write),
           wait until the device is no longer busy from the previous write operation */
        i2c_start_wait(Dev_24LC08B+I2C_WRITE);     // set device address and write mode
        i2c_write(0x00);                        // write start address = 0
        i2c_write(0x01);                        // write data to address 0	<---jgmdesigns changed value for demo
        i2c_write(0x02);                        //    "    "   "    "    1	<---jgmdesigns changed value for demo
        i2c_write(0x04);                        //    "    "   "    "    2	<---jgmdesigns changed value for demo
        i2c_write(0x08);                        //    "    "   "    "    3	<---jgmdesigns changed value for demo
        i2c_stop();                             // set stop conditon = release bus
    
        /* write ok, read value back from eeprom address 0..3 (Sequencial Read),
           wait until the device is no longer busy from the previous write operation */
        i2c_start_wait(Dev_24LC08B+I2C_WRITE);      // set device address and write mode
        i2c_write(0x00);                         // write address = 0
        i2c_rep_start(Dev_24LC08B+I2C_READ);        // set device address and read mode
        ret = i2c_readAck();                       // read one byte form address 0
		PORTB = ret;		//<---jgmdesigns added output for display on LED's
		_delay_ms(750);		//<---jgmdesigns changed - added delay for display on PORTB
        ret = i2c_readAck();                       //  "    "    "    "     "    1
		PORTB = ret;		//<---jgmdesigns added output for display on LED's
		_delay_ms(750);		//<---jgmdesigns changed - added delay for display on PORTB
        ret = i2c_readAck();                       //  "    "    "    "     "    2
		PORTB = ret;		//<---jgmdesigns added output for display on LED's
		_delay_ms(750);		//<---jgmdesigns changed - added delay for display on PORTB
        ret = i2c_readNak();                       //  "    "    "    "     "    3
		PORTB = ret;		//<---jgmdesigns added output for display on LED's
		_delay_ms(750);		//<---jgmdesigns changed - added delay for display on PORTB
        i2c_stop();                              // set stop condition = release bus
    
		//<---jgmdesigns changed - removed last PORT B write
    }
    
    for(;;);	
}

 

 

Attached is the complete project with HEX file.

 

You connect your LEDs to PORTB 0, 1, 2, 3 Active High.

 

Project has been tested on a Mega328 with an X2404P EEPROM using Studio6_2 and an STK600 with an Atmel ICE.

 

Jim

 

Attachment(s): 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Do you have any decoupling capacitors?

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

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

jgmdesign wrote:
And you are correct, it's on page 7
My only gripe about page 7 is that it's not clear what the X=don't care bit should be set to. Why don't they simply show it as a fixed 0? I can't imagine anyone passing 1 in that position though I suppose the implication is that you could, which is why it is "don't care".

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

Brian Fairchild wrote:
Do you have any decoupling capacitors?

 

Well the OP did type:

 

PsySc0rpi0n wrote:
The circuit I have is kind of this:

 

If you look at the video of his circuit in the other thread you will understand.

 

clawson wrote:
My only gripe about page 7 is that it's not clear what the X=don't care bit should be set to.

"Don't care" is pretty straightforward.....At least to me.  "'Don't care" has been used in datasheets for decades.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Brian Fairchild wrote:

Do you have any decoupling capacitors?

 

Yes, I have but probably I wouldn't need because I'm using power from my USB-to-Serial converter which should be smooth enough, I guess. But I always use decoupling caps!

 

clawson wrote:

jgmdesign wrote:
And you are correct, it's on page 7
My only gripe about page 7 is that it's not clear what the X=don't care bit should be set to. Why don't they simply show it as a fixed 0? I can't imagine anyone passing 1 in that position though I suppose the implication is that you could, which is why it is "don't care".

 

Are you also sceptical about those bits??? I'm also too but I always set them to 0 no matter what! If they say it's a "don't care" I do believe and always set them to 0.

 

 

jgmdesign wrote:

Brian Fairchild wrote:
Do you have any decoupling capacitors?

 

Well the OP did type:

 

PsySc0rpi0n wrote:
The circuit I have is kind of this:

 

If you look at the video of his circuit in the other thread you will understand.

 

clawson wrote:
My only gripe about page 7 is that it's not clear what the X=don't care bit should be set to.

"Don't care" is pretty straightforward.....At least to me.  "'Don't care" has been used in datasheets for decades.

 

JIm

 

Although I haven't placed any decoupling caps on the schematic I placed here, I indeed have one 10uF (35V) cap between (+) and (-) lines!

 

 

jimdesigns, I'm going to write another post about the code you wrote because I have some questions about it!

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

0.1uF caps perform better as decoupling caps. Sprinkle a few across your supply lines... especially close to the chip's supply pins... and each of them even if there are two or three on each package.

 

Ross McKenzie ValuSoft Melbourne Australia

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

valusoft wrote:
0.1uF caps perform better as decoupling caps
+1yes

The 10uF is a good bulk cap, but not as good for fast transients...

David (aka frog_jr)

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

I'm still writing the post about jgmdesign code but I'll answer to these latest posts. The smallest polarised caps I have is 1uF. Lower caps are film caps. Not sure if they are good for decoupling purposes...

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

What size film caps?  Unless they are in the picofarad range you can use them....something is better than nothing.

 

Cannot wait to see this post you are writing....getting a little nervous. blush

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

jgmdesign wrote:

What size film caps?  Inless they are in the picofarad range you can use them....something is better than nothing.

 

Cannot wait to see this post you are writing....getting a little nervous. blush

 

JIm

 

I have a .01M and a 100n film caps... But I said I have a 10uF 35V decoupling cap... I didn't said I had none! ;) I also have a 1uF 50V cap here! Is this one better?

 

The reason that the post is taking so much time is because I went to have lunch in the meantime! :)

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

 

 

This pic is from AVR042 app note, note the use of "bypass" 100n caps on all (a)vcc/gnd pairs of pins.  Your avr will only have one or two pairs of pins, but all of them need 100nf caps as shown.  Download this app note, it has lots of good info, and explains why these caps are needed in addition to the one(s) you already have.

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

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

jgmdesign wrote:

PsySc0rpi0n wrote:
I read your sentence. I'm just not sure what is or what could be "proper bank". I know that my IC has A0, A1 and A2 not connected internally.

Keep Reading.  It's in there.  Hint...I said Proper Bank.  THey call it Bank Select.  And you are correct, it's on page 7 wink

 

Anyway I do not have any of your EEPROMS handy but I have a X2404P sitting here that I can configure to operate just like yours does so I set up a little project and got things working.

 

Since I am familiar with your setup from your other thread I elected to make some changes to the example program to better suit your set up.

 

A couple of notes about the modifications I made:

1.  In the i2cmaster.h file I removed all of the references to the example code as it was commented out and hence confusing...so out it went.

2. in twimaster.c I changed the F_CPU to 16Mhz

3. In twimaster.c I changed SCL frequenct to 100khz

4. In the MEGA328_I2C_EEPROM file I changed the DEFINE for the device and its address to what you need for your part to work with the example.

5. In the MEGA328_I2C_EEPROM file I changed the value WRITTEN to the memory cells to something you can display on your setup

6. In the MEGA328_I2C_EEPROM file I changed the PORTB configuration to use only the lower 4 pins.  THe reason you were seeing one or two LED's come on and stay on is because they are used by the XTAL clock

7. in the MEGA328_I2C_EEPROM file I ADDED a PORTB = RET instruction and a DELAY to show the value from the reads of teh EEPROM.

 

All of these changes I made are noted in their respective files at the locations with a "//<-------jgmdesigns"  OR "<-------jgmdesigns" as a comment at the line of change.

 

[I removed the code to make the post smaller]

...

...

...

 

 

Attached is the complete project with HEX file.

 

You connect your LEDs to PORTB 0, 1, 2, 3 Active High.

 

Project has been tested on a Mega328 with an X2404P EEPROM using Studio6_2 and an STK600 with an Atmel ICE.

 

Jim

 

 

I have downloaded your code just to make sure I was changing the correct lines in the original code!

 

The fisrt 4 points of your "todo list" I also did them! 1, 2, 3 and 4.

 

I changed the line:

#define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet

to this:

 

#define Dev24LC08B  0xA0      // device address of EEPROM 24C02, see datasheet

If I understood correctly, the Block Address value, is a 3 bit value in which the MSB of these 3 bit, is a "don't care" bit! This leaves me with 2 bits to select a Block Address. If I ignore the "don't care" bit I have 4 possible Block Addresses, correct? 00, 01, 10 and 11.

 

 

Another thing is that datasheet says:

 The next three bits of the control byte are the block-select bits (B2, B1, B0). B2 is a “don’t care” for the 24XX08. They are used by the master device to select which of the four 256 word-blocks of memory are to be accessed.

 I'm having some issues to understand this sentence!

 

There are 4 blocks of 256 words. Does this means that each block has 256 words and so, there will be a total of 1024 words (4 x 256) ???

 

Another question is what size has each of those 256 words? If the IC as 8k bytes of memory, means 8192 bytes... How does this relates to the 256 words per block of the 4 block the IC has? I would say that 8192 divided by 1024 (1 byte) equals to 8 bytes! Is this the size of each word?

 

Then in main function I have several questions:

 

1 -

/* write 0x75 to eeprom address 0x05 (Byte Write) */
    ret = i2c_start(Dev_24LC08B+I2C_WRITE);       // set device address and write mode

The comment on this piece of code, says that we are going to write the value 0x75 to  address 0x05 of the IC?

 

Is this action taken in 1 step (1 line of code) or in more steps (more than one line of code)???

 

In the "else" statement in the main function you have:

i2c_write(0x05);                       // write address = 5
i2c_write(0x75);                       // ret=0 -> Ok, ret=1 -> no ACK

I don't understand how the same function sets the "place" where we are going to write and actually writes there the data we want!

 

Also, what is the 'ret' is saving and what for is that value used for? Ok I know it saves the return of the i2c_start() function, but what means thar value? (this question and almost all the others is result of me not using my own code, I don't know how things are working - that's why I always try to do my own stuff).

 

Then we have this:

/* write ok, read value back from eeprom address 0x05, wait until
       the device is no longer busy from the previous write operation */
      i2c_start_wait(Dev_24LC08B+I2C_WRITE); // set device address and write mode
      i2c_write(0x05);                       // write address = 5
      i2c_rep_start(Dev_24LC08B+I2C_READ);   // set device address and read mode
      ret = i2c_readNak();                   // read one byte
      i2c_stop();

So, this suggests we have writen the value 0x75 at adress 0x05 and now we are going to read it back from the same address (0x05)

But why are we "waiting" in the first line of code and we send the same parameter as we did in the previous block of code and why are we sending a I2C_WRITE when we pretend to READ? And the comment says explicitly "write mode"???

And why are we using the function i2c_write() to specify the memory address where from we should read the previous written value of 0x75??? This is confusing and the comments are not intuitive!

Then we use a function i2c_rep_start() that is a supposed "repeated start condition" and we send a parameter that was sent before in the previous block of code? I mean, in the previous block of code, we firstly sent the device address and write mode and only after that we specified the memory address where to write the 0x75 value. In this piece of code we are sending first the memory address where we want to read and only after that we are sending the device memory address and write mode and again here we are using "write mode" when we are going to read! This looks like a paradox to me!

 

Then another thing that I cannot fully understand is that the ACK bit is a bit that should tells us if the write process has gone smoothly and has ended. So what are the functions i2c_ReadAck() i2c_ReadNack means? Couldn't it be a single function that would return 1 if there was an error or return 0 if the bit was read/written ok??? And why is the comment of the line code "ret = i2c_readNack()" "read one byte"??? Shouldn't this comment be something like "read the ACK bit state" or so???

 

Ok, I'm going to end this post here... But I'll apply the same questions to the rest of the code! Sorry if I'm not getting the point of the comments and the name of the functions used!

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

PsySc0rpi0n wrote:
If I understood correctly, the Block Address value, is a 3 bit value in which the MSB of these 3 bit, is a "don't care" bit! This leaves me with 2 bits to select a Block Address. If I ignore the "don't care" bit I have 4 possible Block Addresses, correct? 00, 01, 10 and 11.
Say you have block number 0, 1, 2, 3. The datasheet says:

 

So, yes the top nibble is going to 0xA?. As the 00/01/10/11 block bits are at position 1 this means the 4 block values are A0, A2, A4 and A6. Those are for read. Add 1 for write so A1, A4, A5 and A7. In reality you would likely create the address with:

addr = 0xA0 + (block_num << 1) + read_write_flag;

Say block_num is 3 (0b11) and the read_write_flag is 1 (meaning write) then this would be:

addr = 0xA0 + (0b11 << 1) + 1;

in which

(0b11 << 1)

is 6. So this comes out as:

addr = 0xA0 + 6 + 1;

so

addr = 0xA7;

PS forgot to say that if you only ever use:

ret = i2c_start(Dev_24LC08B+I2C_WRITE)

and Dev_24LC08B is defined as 0xA0 this can only ever be 0xA0 or 0xA1 so it only reads/writes block 0. That's why the addition of:

+ (block_num << 1)

is required.

Last Edited: Tue. Nov 1, 2016 - 04:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson, I just didn't understood the A0, A2, A4 and A6. I think I would need to see a possible graphic representation of the memory mapping of these kind of devices so that I could understand better these addressing issues. Can I think of it like if 4 layers of memory and in each layer there are 256 words of 8 bytes per word???

      ____________________________________________________________________

00-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

01-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

02-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

03-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

04-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

05-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

06-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

07-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

08-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

09-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

10-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

11-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

12-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

13-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

14-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

15-/00W/01W/02W/03W/04W/05W/06W/07W/08W/09W/10W/11W/12W/13W/14W/15W/

 

This would be 1 of the 4 banks. A 16 x 16 matrix where would be the 256 words of 8 bytes each to make the 8K memory total!

And there were 3 more banks like this!

 

Could it be pictured like this???

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

PsySc0rpi0n wrote:
I have downloaded your code just to make sure I was changing the correct lines in the original code!

I am guessing you went and manually made the changes instead of just using my source because you wanted to. 

 

PsySc0rpi0n wrote:
I changed the line: #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet to this: #define Dev24LC08B 0xA0 // device address of EEPROM 24C02, see datasheet

I should have mentioned that you will also need to change EVERY location in the main code where you see the old Dev24C02 to Dev24LC08B otherwise you will get an error at compile time.

 

PsySc0rpi0n wrote:
There are 4 blocks of 256 words. Does this means that each block has 256 words and so, there will be a total of 1024 words (4 x 256) ???

Correct. 

 

PsySc0rpi0n wrote:
Another question is what size has each of those 256 words? If the IC as 8k bytes of memory, means 8192 bytes... How does this relates to the 256 words per block of the 4 block the IC has? I would say that 8192 divided by 1024 (1 byte) equals to 8 bytes! Is this the size of each word?

It is an 8K BIT not BYTE EEPROM, so 256 x8 = 2048 bits.  4 x 2048 = 8192 bits, or 1024 BYTES

PsySc0rpi0n wrote:
/* write 0x75 to eeprom address 0x05 (Byte Write) */ ret = i2c_start(Dev_24LC08B+I2C_WRITE); // set device address and write mode The comment on this piece of code, says that we are going to write the value 0x75 to address 0x05 of the IC? Is this action taken in 1 step (1 line of code) or in more steps (more than one line of code)??? In the "else" statement in the main function you have: i2c_write(0x05); // write address = 5 i2c_write(0x75); // ret=0 -> Ok, ret=1 -> no ACK I don't understand how the same function sets the "place" where we are going to write and actually writes there the data we want! Also, what is the 'ret' is saving and what for is that value used for? Ok I know it saves the return of the i2c_start() function, but what means thar value? (this question and almost all the others is result of me not using my own code, I don't know how things are working - that's why I always try to do my own stuff). Then we have this: /* write ok, read value back from eeprom address 0x05, wait until the device is no longer busy from the previous write operation */ i2c_start_wait(Dev_24LC08B+I2C_WRITE); // set device address and write mode i2c_write(0x05); // write address = 5 i2c_rep_start(Dev_24LC08B+I2C_READ); // set device address and read mode ret = i2c_readNak(); // read one byte i2c_stop(); So, this suggests we have writen the value 0x75 at adress 0x05 and now we are going to read it back from the same address (0x05)

This confused me as well, and IMO is not something you need to worry about.  It can be removed as far as I can tell.  I just left it as it was a no harm, no foul.  I guess I should have removed it for you.

 

PsySc0rpi0n wrote:
But why are we "waiting" in the first line of code and we send the same parameter as we did in the previous block of code and why are we sending a I2C_WRITE when we pretend to READ?

We are not 'pretending' anything.  The comment says to wait for the previous WRITE to finish first, so...WAIT.  THEN READ.

 

PsySc0rpi0n wrote:
And why are we using the function i2c_write() to specify the memory address where from we should read the previous written value of 0x75???

You do an I2C_WRITE to set the base address of where you want to READ from.  As I just wrote, the write of 0x75 to location 5 should have been omitted by me.  Forget about it...if you can.

 

PsySc0rpi0n wrote:
This is confusing and the comments are not intuitive!

I disagree with you.  The comments are pretty self explanatory and if you go to Peter FLeurys website there is an Oline MAnual that explains this even further:

http://homepage.hispeed.ch/peter...

 

PsySc0rpi0n wrote:
Then another thing that I cannot fully understand is that the ACK bit is a bit that should tells us if the write process has gone smoothly and has ended. So what are the functions i2c_ReadAck() i2c_ReadNack means?

If you read teh Online manual you will find that I2CReadACK() is for reading multiple bytes sequentially as the code does and the I2C)ReadNak() is to read one single byte which the code does at the very end.

 

PsySc0rpi0n wrote:
Couldn't it be a single function that would return 1 if there was an error or return 0 if the bit was read/written ok??? And why is the comment of the line code "ret = i2c_readNack()" "read one byte"??? Shouldn't this comment be something like "read the ACK bit state" or so???

No, and I explained why one paragraph up.

 

PsySc0rpi0n wrote:
But I'll apply the same questions to the rest of the code! Sorry if I'm not getting the point of the comments and the name of the functions used!

Read the documentation in the Online Manual.

 

But I am going to ask WHICH comments are you having trouble with?  Peter's or Mine?

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

PsySc0rpi0n wrote:
clawson, I just didn't understood the A0, A2, A4 and A6. I think I would need to see a possible graphic representation of the memory mapping of these kind of devices so that I could understand better these addressing issues. Can I think of it like if 4 layers of memory and in each layer there are 256 words of 8 bytes per word???

That device says it is an 8Kbit memory. That is 1Kbyte of memory (the correct term is KibiByte but let's not get bogged down in semantics). The 1024 bytes are accessed as 4 banks of 256bytes.

 

So let's say you want to access the 687th byte of the 1024 available. Well 687/256 is 2. So this location is somewhere in block 2 (counting the 4 blocks as 0,1,2,3). In fact it is the 175th byte in block 2. (that is offset 0xAF). So say I wanted to write it I would start by addressing the device and block number as 0xA0 and block=2 and because it is a write the write_bit=1. So the high part of the address is 0xA0 + (2 << 1) + 1. That is 0xA0 + 4 +1 = 0xA5. So the i2c_start() would specify 0xA5. Then the address byte that follows that picks some offset in that 256 bytes would be the 0xAF meaning the 175th byte in block .

 

More generally:

uint16_t byte_num = 687; // for example
uint8_t block_num = byte_num / 256; // so 2 in this case
i2c_start(0xA0 + (block_num << 1) + read_write);
i2c_write(byte_num % 256)

byte_num could be any value from 0..1023 to access any one of the 1024 bytes.

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

Cliff:

clawson wrote:
and because it is a write the write_bit=1.

The WRITE bit is a 0, not a 1.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

clawson wrote:
That device says it is an 8Kbit memory. That is 1Kbyte of memory (the correct term is KibiByte but let's not get bogged down in semantics). The 1024 bytes are accessed as 4 banks of 256bytes.

Why bother going through all this for 1KB when the device already has 1KB of byte-addressable EEPROM on board?

 

I've totally lost how this applies to "reading value from pin", so I'll crawl back into my lair. [drifted off topic - I'll do something with the title]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Tue. Nov 1, 2016 - 06:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Why bother going through all this for 1KB when the device already has 1KB of byte-addressable EEPROM on board?

+1

 

(though my guess is that this is the classic error of reading 8Kb as 8KB. It can come as something of a disappointment to find you have 1/8th the memory you thought you were getting! ;-)

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

jgmdesign wrote:

I am guessing you went and manually made the changes instead of just using my source because you wanted to. 

 

I was already doing it before you post your code... Obviously I was not absolutely sure of what I was changing. But at least a few things are the same as in your code!

 

jgmdesign wrote:

I should have mentioned that you will also need to change EVERY location in the main code where you see the old Dev24C02 to Dev24LC08B otherwise you will get an error at compile time.

 

And yes I also changed all the occurrences of the old macro name to the new one. 

 

Well, maybe it's me but the comments confuses me! the function names are counter intuitive! This is why I always like to write my own code!

Why the functions are not something lile:

i2c_init()

i2c_readByte()

i2c_writeByte()

i2c_startBit()

i2c_stopBit()

i2c_checkACK()

i2c_setDeviceAddress()

i2c_setByteAddress()

 

I'm not sure if these would be enough to the whole I2C process, but I think these names are a lot more intuitive than the ones used!

I simply cannot understand some of the points that I stated in my post #63 that were not addressed! And to read and understand the online Peter Fleury's manual, I should know exactly what are each and every registers used in his code. I'll name them:

TWSR

TWBR

TWCR

TWINT

TWSTA

TWEN

TW_STATUS

TW_START

TW_REP_START

TWDR

TW_MT_SLA_ACK

TW_MR_SLA_ACK

TW_MR_DATA_NACK

TWSTO

TW_MT_DATA_ACK

TWEA

 

I cannot understand Peter's code if I don't know what are each of these registers and what they do/control!

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

Well, I guess if one wanted to experiment with I2C and had this device lying about, it would be a good place to start.  Or maybe RTC such as DS1307.  But why would one have these lying about nowadays?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

PsySc0rpi0n wrote:
, I should know exactly what are each and every registers used in his code.
You do own a copy of the 328 datahseet don't you? As I think I pointed out previously:

 

 

That is the from the "Register Summary" table towards the end of the document. If you click on any of the blue links there it takes you to the likes of:

 

That was what I saw when I clicked through on TWCR.

 

Using:

 

http://www.atmel.com/Images/Atme...

 

The things you list are documented as follows:

TWSR - page 293

TWBR - page 292

TWCR - page 296

TWINT - (a bit within TWCR so also on) page 296

TWSTA - (a bit within TWCR so also on) page 296

TWEN - (a bit within TWCR spills over onto) page 296

TW_STATUS - this comes form the compiler's headers. Fleury includes <compat/twi.h> and that in turn includes  <util/twi.h>

C:\SysGCC\avr\avr\include\util>grep TW_STATUS twi.h
 * \def TW_STATUS_MASK
#define TW_STATUS_MASK          (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|\
 * \def TW_STATUS
 * TWSR, masked by TW_STATUS_MASK
#define TW_STATUS               (TWSR & TW_STATUS_MASK)

TW_START

C:\SysGCC\avr\avr\include\util>grep TW_START twi.h
    \def TW_START
#define TW_START                0x08

TW_REP_START

C:\SysGCC\avr\avr\include\util>grep TW_REP_START twi.h
    \def TW_REP_START
#define TW_REP_START            0x10

TWDR - page 295

TW_MT_SLA_ACK - see the following

TW_MR_SLA_ACK - see the following

TW_MR_DATA_NACK - see the following

TW_MT_DATA_ACK - see the following...

C:\SysGCC\avr\avr\include\util>grep _ACK twi.h
    \def TW_MT_SLA_ACK
#define TW_MT_SLA_ACK           0x18
    \def TW_MT_DATA_ACK
#define TW_MT_DATA_ACK          0x28
    \def TW_MR_SLA_ACK
#define TW_MR_SLA_ACK           0x40
    \def TW_MR_DATA_ACK
#define TW_MR_DATA_ACK          0x50
    \def TW_ST_SLA_ACK
#define TW_ST_SLA_ACK           0xA8
    \def TW_ST_ARB_LOST_SLA_ACK
#define TW_ST_ARB_LOST_SLA_ACK  0xB0
    \def TW_ST_DATA_ACK
#define TW_ST_DATA_ACK          0xB8
    \def TW_SR_SLA_ACK
#define TW_SR_SLA_ACK           0x60
    \def TW_SR_ARB_LOST_SLA_ACK
#define TW_SR_ARB_LOST_SLA_ACK  0x68
    \def TW_SR_GCALL_ACK
#define TW_SR_GCALL_ACK         0x70
    \def TW_SR_ARB_LOST_GCALL_ACK
#define TW_SR_ARB_LOST_GCALL_ACK 0x78
    \def TW_SR_DATA_ACK
#define TW_SR_DATA_ACK          0x80
    \def TW_SR_GCALL_DATA_ACK
#define TW_SR_GCALL_DATA_ACK    0x90

TWSTO - (a bit within TWCR so also on) page 296

TWEA - (a bit within TWCR so also on) page 296

To be honest there aren't that many places you need to look. If they any such symbol appears in the Fleury code it's either a symbol he's created or it's coming from a header file. The only headers you have to explore are:

#include <inttypes.h>
#include <compat/twi.h>

#include <i2cmaster.h>

and in turn:

#include <avr/io.h>

If you don't find the symbols in Peter's local headers then they must be in the compiler/C library headers. As I say <util/twi.h> is fairly key to all this. There is some documentation for it in the compiler user manual:

 

http://www.nongnu.org/avr-libc/u...

 

PS one slight gripe I have with the Fleury code is that he does not make the correct use of <> and "" in #include statements. For his own headers he should be using "" not <> so, for example:

#include <inttypes.h>
#include <compat/twi.h>

#include "i2cmaster.h"

that would instantly tell you that the top 2 come from the compiler/C library while the latter is local to the Fleury code. Also C compilers have different search paths for <> (system headers) versus "" (user headers) so it is important to use the right one.

Last Edited: Tue. Nov 1, 2016 - 06:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

clawson wrote:
That device says it is an 8Kbit memory. That is 1Kbyte of memory (the correct term is KibiByte but let's not get bogged down in semantics). The 1024 bytes are accessed as 4 banks of 256bytes.

Why bother going through all this for 1KB when the device already has 1KB of byte-addressable EEPROM on board?

 

I've totally lost how this applies to "reading value from pin", so I'll crawl back into my lair. [drifted off topic - I'll do something with the title]

 

Indeed... If I can change the title myself, I'll change it to something like "I2C Peter Fleury's library questions" or so...

 

 

clawson wrote:

theusch wrote:
Why bother going through all this for 1KB when the device already has 1KB of byte-addressable EEPROM on board?

+1

 

(though my guess is that this is the classic error of reading 8Kb as 8KB. It can come as something of a disappointment to find you have 1/8th the memory you thought you were getting! ;-)

 

Yes, it is usual that 8K is assumed to be 8K bytes... I don't mind, at this point that I have 1/8t of what thought to have! I just need/want to understand this! And in the datasheet I have, there's no reference to 8K bit nor 8k byte... Just 8k...

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

PsySc0rpi0n wrote:
there's no reference to 8K bit nor 8k byte... Just 8k...
Err no...

From Page 1.

 

For readers used to these things (most memory devices are specified in bit rather than byte capacity as it makes no assumption about the width you will use to access it) then the "8k-bit"stands out like a sore thumb.

 

It then goes onto say 4 blocks of 256 8bit locations. That is 4 lots of 256 bytes which is a grand total of 1024 bytes.

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

Arrgghhh... I search the document by "8kbit". It didn't found any match... Of course, it was "8 Kbit"... There was a space and a capital 'K' that i didn't include in the search!

 

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

PsySc0rpi0n wrote:

Arrgghhh... I search the document by "8kbit". It didn't found any match... Of course, it was "8 Kbit"... There was a space and a capital 'K' that i didn't include in the search!

 

If you are trolling, you are doing an excellent job of it.

 

Earlier, it seemed that no search was done in the AVR datasheet for SCL or SDA.  Now, the TWI chapter doesn't come right out and give a pin assignment table, but as pointed out it can be seen in Pin Configurations and explained in Alternate Functions of Port C.  So I can see where reading the datasheet might miss it.

 

Now it seems you are a convert to searching, and skipping the reading part.  Like the first page of the EEPROM datasheet Description: paragraph.  I assume you got these devices from somewhere, like DigiKey.  I read there:

 

Reading is also involved when using e.g. Fleury code.  What does the first page of description say?

 

Detailed Description

I2C (TWI) Master Software Library.

#include <i2cmaster.h>

Basic routines for communicating with I2C slave devices. This single master implementation is limited to one bus master on the I2C bus.

This I2c library is implemented as a compact assembler software implementation of the I2C protocol which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). Since the API for these two implementations is exactly the same, an application can be linked either against the software I2C implementation or the hardware I2C implementation.

Use 4.7k pull-up resistor on the SDA and SCL pin.

Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module i2cmaster.S to your target when using the software I2C implementation !

Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.

Note

The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted to GNU assembler and AVR-GCC C call interface. Replaced the incorrect quarter period delays found in AVR300 with half period delays.

Author

Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury

Copyright

(C) 2015 Peter Fleury, GNU General Public License Version 3

API Usage Example

The following code shows typical usage of this library, see example test_i2cmaster.c

#include <i2cmaster.h>

#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet

int main(void)

Did you study or use the worked example?  If I had to guess 2402 code might even work unmodified for 2408.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

PsySc0rpi0n wrote:
And to read and understand the online Peter Fleury's manual, I should know exactly what are each and every registers used in his code. I'll name them:

The read the bloody datasheet like the rest of us do!

 

For someone that says they want to learn, you sure can throw a lot of crap back at the people that are in fact trying very patiently to help you...again!

 

I spent quite a bit of time last night making sure that code worked according to your setup.  And I also told you why the LED's were coming on and staying on because of the crystal oscillator...  Rather than bitch at me, and the others here, I would think that you would have run loaded the HEX file I provided, and confirmed what I wrote should happen with the LED's so you know the code is working...THEN start to dissect what was happening in the code itself.  BUT theres nothing in any of your posts that says you have done this.

 

I'll repeat what was said to you in your other thread....STOP fighting something that works.  See that it works so you have something to reference off of, THEN dissect it.  HAd you run the code I sent, you could modify the four data bytes I used (0x01, 0x02, 0x04, 0x08) with anything between 0x00 and 0xfF to see that the code indeed works.  YOu then go back and walk through the code and look at what registers are used in each function.  They are clearly seen in each function in the twimaster.c file.

 

I thought wrong all the way around on this one.

 

All the best on your quest.

 

theusch wrote:
so I'll crawl back into my lair.

Got any more room in there?  I'll bring some ribs for the BBQ

 

Jim

 

Edit:

@Lee:

Did you study or use the worked example?  If I had to guess 2402 code might even work unmodified for 2408.

 

I uploaded a project with HEX file last night for him to simply load into the AVR and it should work

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Tue. Nov 1, 2016 - 07:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

PsySc0rpi0n wrote:

Arrgghhh... I search the document by "8kbit". It didn't found any match... Of course, it was "8 Kbit"... There was a space and a capital 'K' that i didn't include in the search!

 

If you are trolling, you are doing an excellent job of it.

 

Earlier, it seemed that no search was done in the AVR datasheet for SCL or SDA.  Now, the TWI chapter doesn't come right out and give a pin assignment table, but as pointed out it can be seen in Pin Configurations and explained in Alternate Functions of Port C.  So I can see where reading the datasheet might miss it.

 

Now it seems you are a convert to searching, and skipping the reading part.  Like the first page of the EEPROM datasheet Description: paragraph.  I assume you got these devices from somewhere, like DigiKey.  I read there:

 

Reading is also involved when using e.g. Fleury code.  What does the first page of description say?

 

Detailed Description

I2C (TWI) Master Software Library.

#include <i2cmaster.h>

Basic routines for communicating with I2C slave devices. This single master implementation is limited to one bus master on the I2C bus.

This I2c library is implemented as a compact assembler software implementation of the I2C protocol which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). Since the API for these two implementations is exactly the same, an application can be linked either against the software I2C implementation or the hardware I2C implementation.

Use 4.7k pull-up resistor on the SDA and SCL pin.

Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module i2cmaster.S to your target when using the software I2C implementation !

Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.

Note

The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted to GNU assembler and AVR-GCC C call interface. Replaced the incorrect quarter period delays found in AVR300 with half period delays.

Author

Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury

Copyright

(C) 2015 Peter Fleury, GNU General Public License Version 3

API Usage Example

The following code shows typical usage of this library, see example test_i2cmaster.c

#include <i2cmaster.h>

#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet

int main(void)

Did you study or use the worked example?  If I had to guess 2402 code might even work unmodified for 2408.

 

 

 

I'm definitely feeling insulted/disrespected. I'm not here to troll anyone or anything! As I always said, I'm a beginner. So, I think I should be given a slack when I miss details! I assume that I don't read the datasheet line by line and all of the 444 pages but I DO read the blocks of text where I think the important info on some subject might be! And I doubt that anyone in this world when purchases a new uC that he doesn't know, that he reads the whole datasheet all in a row! I think that the reading should be done when it is needed! But that's just my opinion!

 

What would be my interest in knowing something and saying that I don't? Do you think I could ever have any kind of pleasure/interest writing this amount of posts if I didn't need to do it? I wish I understand all details in the datasheet and that I wouldn't need to ask anything to anyone!

 

Before I purchased my 24LC08B and 24LC16B IC's, I searched Google and I found these 2 models. So I purchased them in a local Electronics shop!

 

I have also missed, as I already said, that I have looked into AtMega328P a million times and I have ever noticed that pins 27 and 28 were assigned to SDA and SCL! Can I be blamed for that??? If I have realised earlier, I wouldn't have asked... You make things look like then happen because I have the intent for them to happen this way! That's sad that someone who's trying to learn by his own hands that is claimed to be lazy, that I do not read the datasheet and that I'm trolling with others! I'm not! I'm a grown man and I'm a mature person...

 

About Peter's code that you have "bolded", for instance, for the line where the device address is defined, i got the idea that the datasheet would tell us that each device would have their own specific and unique address to start saving data there, which is not the case! My reasoning might not be the best, but if the comments or explanations were more clear, probably I wouldn't have this questions! Those comments are meant to someone who already has some knowledge, though, I'm almost forced to understand all comments and all function definitions and all registers descriptions!

 

And finally yes, I tried the code and I think it is working! But I'm still not happy because I have not full control of the device, I don't know what is going on in the background and I still have not enough knowledge yet to understand the code!

 

 

jgmdesign wrote:

PsySc0rpi0n wrote:
And to read and understand the online Peter Fleury's manual, I should know exactly what are each and every registers used in his code. I'll name them:

The read the bloody datasheet like the rest of us do!

 

For someone that says they want to learn, you sure can throw a lot of crap back at the people that are in fact trying very patiently to help you...again!

 

I spent quite a bit of time last night making sure that code worked according to your setup.  And I also told you why the LED's were coming on and staying on because of the crystal oscillator...  Rather than bitch at me, and the others here, I would think that you would have run loaded the HEX file I provided, and confirmed what I wrote should happen with the LED's so you know the code is working...THEN start to dissect what was happening in the code itself.  BUT theres nothing in any of your posts that says you have done this.

 

I'll repeat what was said to you in your other thread....STOP fighting something that works.  See that it works so you have something to reference off of, THEN dissect it.  HAd you run the code I sent, you could modify the four data bytes I used (0x01, 0x02, 0x04, 0x08) with anything between 0x00 and 0xfF to see that the code indeed works.  YOu then go back and walk through the code and look at what registers are used in each function.  They are clearly seen in each function in the twimaster.c file.

 

I thought wrong all the way around on this one.

 

All the best on your quest.

 

theusch wrote:
so I'll crawl back into my lair.

Got any more room in there?  I'll bring some ribs for the BBQ

 

Jim

 

Edit:

@Lee:

Did you study or use the worked example?  If I had to guess 2402 code might even work unmodified for 2408.

 

I uploaded a project with HEX file last night for him to simply load into the AVR and it should work

 

 

This aggravated attitude against me makes me to give up of this forum! I'm not allowed to miss anything and I'm almost forced to understand every single word said!

jgmdesign, I have tried to dissect the code you sent me, but most of my questions were not answered! Do you want me to ask them again? (Don't worry, I won't)!

 

 

I appreciate, and truly do, all the help given, but I'm not feeling comfortable  here! So, probably the best is to step down and keep my self away from this forum until I have more knowledge acquired somewhere else and be able to come here and discuss wisely the subjects of my interest!

 

Best regards!

Psy 

Last Edited: Tue. Nov 1, 2016 - 08:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
And finally yes, I tried the code and I think it is working! But I'm still not happy because I have not full control of the device, I don't know what is going on in the background and I still have not enough knowledge yet to understand the code!

Who gives a s*** if you have control of it, or understand it at this time?  Iit would have been nice to tell us that it worked, or whatever so everyone has a foundation to work with you on.  Like I said use something proven and get that to work...THEN mess with it.  At least you have something to fall back on.  But you are too stubborn to listen.

 

PsySc0rpi0n wrote:
This aggravated attitude against me makes me to give up of this forum!

 

Fair thee well then.  If you try Stack Exchange be prepared to have your threads deleted if the moderators there dont like the way things are going.  They posted a video telling the world they do this.

 

You will also find that AVRfreaks are some of the most forgiving, and talented people you will ever have the privilege of tapping for information.  But this will become more evident as you foray into the other forums out there.

 

We'll leave the light on, and the door unlocked in case you change your mind. wink

 

In the meantime, I have ribs on the BBQ

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

jgmdesign wrote:

Fair thee well then.  If you try Stack Exchange be prepared to have your threads deleted if the moderators there dont like the way things are going.  They posted a video telling the world they do this.

 

I can vouch for that - I've asked what I considered to be perfectly reasonable questions on Stack Overflow and a fair few times I've been absolutely torn to shreds for the finest of detail. One specific occasion comes to mind where  I asked a question regarding fully compiling .NET applications rather than simply compiling to MISL which would then be fully compiled at runtime by .NET. All I got was "No one wants to de-compile your programs" and the thread locked ha!

 

 

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

jgmdesign wrote:
Before this turns into another 70+ post count...

laugh

 

 

EDIT:

82 and counting....50 of which were just to get the basics.... angry

JIM

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Nov 1, 2016 - 09:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I more than once wondered if bianchi had a pseudonym.

 

Ross McKenzie ValuSoft Melbourne Australia

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

Ok, this has dragged on long enough.

 

If the OP returns, he can PM me to unlock the thread, or start a clean thread.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Pages

Topic locked