0,0 → 1,289 |
/**************************************************************************//** |
* \brief EEPROM 24C04/24C08/24C16 library. |
* \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com |
* \version 1.0 |
* \date 20121102 |
* |
* This file is part of the iDreamMicro library. |
* |
* This library is free software: you can redistribute it and/or modify it under |
* the terms of the GNU Lesser General Public License as published by the Free |
* Software Foundation, either version 3 of the License, or (at your option) any |
* later version. |
* |
* This library is distributed in the hope that it will be useful, but WITHOUT |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
* details. |
* |
* You should have received a copy of the GNU Lesser General Public License |
* along with this program. If not, see http://www.gnu.org/licenses/ |
******************************************************************************/ |
|
/**************************************************************************//** |
* \file eeprom_24c04_24c16.c |
******************************************************************************/ |
|
/****************************************************************************** |
* Header file inclusions. |
******************************************************************************/ |
|
#include "../eeprom_24c04_24c16.h" |
|
#include <twi/twi.h> |
|
#include <util/delay.h> |
|
#include <assert.h> |
#include <stdint.h> |
#include <stdlib.h> |
|
/****************************************************************************** |
* Private macro definitions. |
******************************************************************************/ |
|
/**************************************************************************//** |
* \def EEPROM_24C04_24C16__ADDRESS |
* \brief EEPROM 24C04/24C08/24C16 address. Given by datasheet. |
******************************************************************************/ |
#define EEPROM_24C04_24C16__ADDRESS 0xA0 |
|
/**************************************************************************//** |
* \def EEPROM_24C04_24C16__PAGE_SIZE |
* \brief Size of a page in EEPROM memory. |
* This size is given by EEPROM memory datasheet. |
******************************************************************************/ |
#define EEPROM_24C04_24C16__PAGE_SIZE 16 |
|
/****************************************************************************** |
* Private function prototypes. |
******************************************************************************/ |
|
/**************************************************************************//** |
* \fn static void eeprom_24c04_24c16__write_page( |
* uint16_t address, |
* uint8_t length, |
* uint8_t* p_data) |
* |
* \brief Write a page in memory. |
* |
* \param address Start address of data to write. |
* \param length Number of bytes to write. |
* \param[in] p_data Bytes to write. |
******************************************************************************/ |
static |
void |
eeprom_24c04_24c16__write_page |
( |
uint16_t address, |
uint8_t length, |
uint8_t* p_data |
); |
|
/****************************************************************************** |
* Private variable declarations. |
******************************************************************************/ |
|
static uint8_t device_address = 0; |
|
/****************************************************************************** |
* Public function definitions. |
******************************************************************************/ |
|
/**************************************************************************//** |
* \fn void eeprom_24c04_24c16__initialize(uint8_t hardware_address) |
* |
* \brief Initialize EEPROM 24C04/24C08/24C16. |
* |
* \param hardware_address Hardware address. Pins A1 to A2. |
******************************************************************************/ |
void |
eeprom_24c04_24c16__initialize |
( |
uint8_t hardware_address |
){ |
// Compute device address. |
device_address = EEPROM_24C04_24C16__ADDRESS | ((hardware_address & 0x06) << 1); |
|
// We don't initialize TWI here: we may have several devices on the bus. |
// Initialize TWI. |
//twi__initialize(EEPROM_24C04_24C16__CLOCK_RATE); |
} |
|
/**************************************************************************//** |
* \fn void eeprom_24c04_24c16__write_byte(uint16_t address, uint8_t data) |
* |
* \brief Write a byte into memory. |
* |
* \param address Address in memory. |
* \param data Byte to write. |
******************************************************************************/ |
void |
eeprom_24c04_24c16__write_byte |
( |
uint16_t address, |
uint8_t data |
){ |
twi__start(); |
twi__send_slaw(device_address | ((address & 0x30) >> 7)); |
twi__send_data(address & 0xFF); |
twi__send_data(data); |
twi__stop(); |
} |
|
/**************************************************************************//** |
* \fn void eeprom_24c04_24c16__write_bytes( |
* uint16_t address, |
* uint16_t length, |
* uint8_t* p_data) |
* |
* \brief Write bytes into memory. |
* |
* \param address Start address. |
* \param length Number of bytes to write. |
* \param[in] p_data Bytes to write. |
******************************************************************************/ |
void |
eeprom_24c04_24c16__write_bytes |
( |
uint16_t address, |
uint16_t length, |
uint8_t* p_data |
){ |
// Check the preconditions. |
assert(NULL != p_data); |
|
// Write first page if not aligned. |
uint8_t not_aligned_length = 0; |
uint8_t page_offset = address % EEPROM_24C04_24C16__PAGE_SIZE; |
if (page_offset > 0) |
{ |
not_aligned_length = EEPROM_24C04_24C16__PAGE_SIZE - page_offset; |
eeprom_24c04_24c16__write_page(address, not_aligned_length, p_data); |
length -= not_aligned_length; |
} |
|
if (length > 0) |
{ |
address += not_aligned_length; |
p_data += not_aligned_length; |
|
// Write complete and aligned pages. |
uint16_t page_count = length / EEPROM_24C04_24C16__PAGE_SIZE; |
for (uint16_t i = 0; i < page_count; i++) |
{ |
eeprom_24c04_24c16__write_page(address, EEPROM_24C04_24C16__PAGE_SIZE, p_data); |
address += EEPROM_24C04_24C16__PAGE_SIZE; |
p_data += EEPROM_24C04_24C16__PAGE_SIZE; |
length -= EEPROM_24C04_24C16__PAGE_SIZE; |
} |
|
if (length > 0) |
{ |
// Write remaining uncomplete page. |
eeprom_24c04_24c16__write_page(address, EEPROM_24C04_24C16__PAGE_SIZE, p_data); |
} |
} |
} |
|
/**************************************************************************//** |
* \fn uint8_t eeprom_24c04_24c16__read_byte(uint16_t address) |
* |
* \brief Read a byte in memory. |
* |
* \param address Address to read. |
* |
* \return Read byte. |
******************************************************************************/ |
uint8_t |
eeprom_24c04_24c16__read_byte |
( |
uint16_t address |
){ |
uint8_t data = 0; |
|
twi__start(); |
twi__send_slaw(device_address | ((address & 0x30) >> 7)); |
twi__send_data(address & 0xFF); |
twi__repeat_start(); |
twi__send_slar(device_address); |
twi__receive_data_nack(&data); |
twi__stop(); |
|
return data; |
} |
|
/**************************************************************************//** |
* \fn void eeprom_24c04_24c16__read_bytes( |
* uint16_t address, |
* uint16_t length, |
* uint8_t* p_data) |
* |
* \brief Read bytes in memory. |
* |
* \param address Start address of data to read. |
* \param length Number of bytes to read. |
* \param[in] p_data Buffer to fill with read bytes. |
******************************************************************************/ |
void |
eeprom_24c04_24c16__read_bytes |
( |
uint16_t address, |
uint16_t length, |
uint8_t* p_data |
){ |
// Check the preconditions. |
assert(NULL != p_data); |
|
twi__start(); |
twi__send_slaw(device_address | ((address & 0x30) >> 7)); |
twi__send_data(address & 0xFF); |
twi__repeat_start(); |
twi__send_slar(device_address); |
for (uint16_t i = 0; i < length - 1; i++) |
{ |
twi__receive_data_ack(p_data + i); |
} |
twi__receive_data_nack(p_data + length - 1); |
twi__stop(); |
} |
|
/****************************************************************************** |
* Private function definitions. |
******************************************************************************/ |
|
/**************************************************************************//** |
* \fn static void eeprom_24c04_24c16__write_page( |
* uint16_t address, |
* uint8_t length, |
* uint8_t* p_data) |
* |
* \brief Write a page in memory. |
* |
* \param address Start address of data to write. |
* \param length Number of bytes to write. |
* \param[in] p_data Bytes to write. |
******************************************************************************/ |
static |
void |
eeprom_24c04_24c16__write_page |
( |
uint16_t address, |
uint8_t length, |
uint8_t* p_data |
){ |
// Check the preconditions. |
assert(NULL != p_data); |
|
twi__start(); |
twi__send_slaw(device_address | ((address & 0x30) >> 7)); |
twi__send_data(address & 0xFF); |
for (uint8_t i = 0; i < length; i++) |
{ |
twi__send_data(p_data[i]); |
} |
twi__stop(); |
|
// Write cycle time (tWR). See EEPROM memory datasheet for more details. |
_delay_ms(10); |
} |