您的位置:首页 > 编程语言

CC2538 zigbee I2C示例代码读写AT24C02D eeprom

2017-06-22 17:24 323 查看

AT24C02D

AT24C02D由于不是标准的I2C总线,所以没有完全使用I2C的8字节地址总线,而是使用了5+3外部引脚设置(A2,A1,A0)来决定和哪路器件通讯的,一个i2c总线上最多能挂载8个AT24C02D,刚好是2的三次方。

不明白为什么AT24C02D把i2c里面的sub address叫做Word Address,很是奇怪,我这里表述都按照sub address来表述,下同。

AT24C02D 作为CC2538外挂的eeprom,通过i2c总线和CC2538通讯,实现读写,花了很长时间一直搞不定,网上找的十有八九都是什么GPIO模拟i2c,我的CC2538本身就有i2c接口,还模拟什么模拟。

开始没搞懂读写AT24C02D eeprom,以为和普通的i2c器件一样,写的话,发送slave address+ sub address+data,就可以写了,读的话,发送slave address+sub address,就可以读出指定地址的数据了,其实是错的

我们都知道,i2c有起始位,也就是Start,有停止位,也就是Stop。写的话,按照eeprom芯片手册给的时序图,就是Start以后,发送从机地址slave address,发送完从机地址,是不能有Stop的,必须接着发送sub address,然后也不能有Stop,接着发送data,就是需要写入的数据,最后再发送Stop,才算是完成了一次写操作,真麻烦。

读的话,芯片手册里面提到的有三种读的方式,分别为Current Address Read、Random Address Read、Sequential Read,

我们这里先探讨随机读,我认为说是随机读不太准确,应该是读取指定地址的数据才准确。随机读实际上是通过写入一个地址改变eeprom里面data word address 的值,然后再进行当前地址读。并不是直接发送slave address+sub address就可以读的。读之前,必须先把slave address+sub address写进去,延时20ms,然后再开始读,读的时候,只需要给slave address就可以,不需要sub address,就能读出数据了。

CC2538 I2C功能

找遍互联网,也找不到CC2538 I2C相关的示例代码,除了一个master_slave_loopback.c示例回环读写i2c之外,别的要么是什么gpio模拟i2c,要么是什么firmware foundation提供的示例代码,竟没有一个是真正能成功使用过的。看来使用CC2538的人少的很,多数人都用CC2530带十几个二十个节点满足home应用就完事了。

给出CC2538 i2c读写eeprom头文件:

/*
Atmel AT24C02 EEPROM read and write
*/

#ifndef HAL_EEPROM_H
#define HAL_EEPROM_H

#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

/*
* PC.6->I2C_SCL
* PC.7->I2C_SDA
*/
#define I2C_SCL             GPIO_PIN_6
#define I2C_SDA             GPIO_PIN_7
#define GPIO_I2C_BASE       GPIO_C_BASE

void HalEepromInit(void);
uint32_t HalEepromWriteByte(uint8 slaveAddr,uint32_t subAddr,uint32_t data);
uint32_t HalEepromReadByte(uint8 slaveAddr,uint32_t subAddr);
uint32_t HalEepromReadByteEx(uint8 slaveAddr,uint32_t subAddr);

#ifdef __cplusplus
}
#endif

#endif


给出CC2538 i2c读写eeprom的源文件,可以参考i2c功能的使用和eeprom功能的使用

/**************************************************************************************************
*                                           INCLUDES
*
* Description: Atmel Inc  AT24C02D eeprom chip write and read. For CC2538 cortex-M3 core
*
*
**************************************************************************************************/

#include <string.h>
#include "hal_types.h"
#include "hal_eeprom.h"
#include "hw_ioc.h"
#include "hal_mcu.h"

void HalEepromInit(void)
{
#if (HAL_EEPROM == TRUE)
//
// Set the clocking to run directly from the external crystal/oscillator.
// (no ext 32k osc, no internal osc)
//
SysCtrlClockSet(false, false, SYS_CTRL_SYSDIV_32MHZ);
//
// Set IO clock to the same as system clock
//
SysCtrlIOClockSet(SYS_CTRL_SYSDIV_32MHZ);
//
//  The I2C peripheral must be enabled before use.
//
SysCtrlPeripheralEnable(SYS_CTRL_PERIPH_I2C);

//
// Do reset of I2C module
//
SysCtrlPeripheralReset(SYS_CTRL_PERIPH_I2C);

//
// Configure I2C physical pins
//
GPIOPinTypeI2C(GPIO_I2C_BASE, I2C_SCL);
GPIOPinTypeI2C(GPIO_I2C_BASE, I2C_SDA);

// Configure pins as peripheral input and output
//IOCPinConfigPeriphInput(GPIO_I2C_BASE, I2C_SCL,IOC_I2CMSSCL);
IOCPinConfigPeriphInput(GPIO_I2C_BASE, I2C_SDA,IOC_I2CMSSDA);
IOCPinConfigPeriphOutput(GPIO_I2C_BASE, I2C_SCL,IOC_MUX_OUT_SEL_I2C_CMSSCL);
IOCPinConfigPeriphOutput(GPIO_I2C_BASE, I2C_SDA,IOC_MUX_OUT_SEL_I2C_CMSSDA);

// data rate setting
// fase:100kbps
// true:400kbps
I2CMasterInitExpClk(SysCtrlClockGet(), false);

#endif
}

/*
*Write data to external eeprom(AT24C02D)
*
@param 7-bit of slave address
@param 8-bit of sub-address
@param byte to be write
@param index of total eeprom(0~255)
*/
uint32_t HalEepromWriteByte(uint8 slaveAddr,uint32_t subAddr,uint32_t data)
{
#if (HAL_EEPROM == TRUE)
if(subAddr < 0xFF)
{
//set slave address(Device Address)
I2CMasterSlaveAddrSet(slaveAddr,false);       //false:write

//set sub address(Word Address)
I2CMasterDataPut(subAddr);
I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_START);     //star+run

// Wait until master module is done transferring.
while(I2CMasterBusy()){}

// Place the data to be sent in the data register
I2CMasterDataPut(data);
I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_FINISH);    //run+stop

// Wait until master module is done transferring.
while(I2CMasterBusy()){}
}
#endif
return 0;
}

/*
* dummy write for read purpose
@param index of total eeprom(0~255)
*/
uint32_t HalEepromReadByte(uint8 slaveAddr,uint32_t subAddr)
{
uint32_t uRead=0;
#if (HAL_EEPROM == TRUE)
if(subAddr < 0xFF)
{
//1. dummy write
//set slave address(Device Address)
I2CMasterSlaveAddrSet(slaveAddr,false);       //false:write
//set sub address(Word Address)
I2CMasterDataPut(subAddr);
I2CMasterControl(I2C_MASTER_CMD_BURST_SEND_START);

while(I2CMasterBusy()){}
}
#endif
return uRead;
}

/*
* Radom read(AT24C02D chip),read the specify Word address
* @param index of total eeprom(0~255)
*/
uint32_t HalEepromReadByteEx(uint8 slaveAddr,uint32_t subAddr)
{
uint32_t uRead=0;
#if (HAL_EEPROM == TRUE)
if(subAddr < 0xFF)
{
//2. actual read
I2CMasterSlaveAddrSet(slaveAddr,true);
I2CMasterControl(I2C_MASTER_CMD_SINGLE_RECEIVE);

// Read the data from the master.
//
uRead = I2CMasterDataGet();
while(I2CMasterBusy()){}
}
#endif
return uRead;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: