正在调试的板子是LPC2294芯片,板上有片EEPROM(24C04),需要在这个EEPROM里面存放一个IP地址。
首先需要确定EEPROM(24C04)器件的从地址,地址的确定需要看原理图上的接线。
先看一下AT24C02的芯片资料,我们会发现AT24C02有三个地址A0,A1,A2。同时,我们会在资料的Device Address介绍发现
I2C器件一共有七位地址码,还有一位是读/写(R/W)操作位,而在AT24C02的前四位已经固定为1010。R/W为1则为 读操作,为0则为写操作。R/W位我们要设置为0(写操作)
规则为:1010(A0)(A1)(A2)(R/W)
然后,看一下自己的设置PCB上的AT24C02的三位地址引脚的接法。我的板子上接法和一般常用的接法一样,注意SCL和SDA要接上拉电阻,如下:
对应上面的电路图,A0,A1,A2都是接的GND,所以为A0=0,A1=0,A2=0;可以知道AT24C02的从设备写地址为10100000(0xa0),读设备地址为10100001(0xa1)。
其他接法:
那么对应的A0,A1,A2都是接的VCC,所以为A0=1,A1=1,A2=1;可以知道AT24C02的从设备写地址为10101110(0xae),读设备地址为10101111(0xaf)。
程序及说明:
P0.4口接了一个LED灯,用这个灯来指示读写是否正确。这里是向EEPROM写入了一个IPV4的地址,每段IP地址用十六进制数表示。
/****************************************************************************
* 文 件 名:MyIic.c
* 功 能:使用硬件I2C对E2PROM进行操作,利用中断方式操作。
* 说 明:。
****************************************************************************/
#include "config.h"
#define CAT1025 0xA0 // 定义器件地址
#define LED1 1<<4 // P0.4控制LED
uint8 data_buf[12]={0xC0,0xA8,0x51,0x38,0x0};
uint8 data_buf1[12]={0xC0,0xA8,0x51,0x38,0x0};
/****************************************************************************
* 名 称:DelayNS()
* 功 能:长软件延时
* 入口参数:dly 延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
for(; dly>0; dly--)
{
for(i=0; i<50000; i++);
}
}
/*****************************************************************************
* 名 称:I2C_Init()
* 功 能:主模式I2C初始化,包括初始化其中断为向量IRQ中断。
* 入口参数:fi2c 初始化I2C总线速率,最大值为400K
* 出口参数:无
****************************************************************************/
void I2C_Init(uint32 fi2c)
{
if(fi2c>400000)
fi2c = 400000;
PINSEL0 = (PINSEL0&0xFFFFFF0F) | 0x50; // 设置I2C控制口有效
I2SCLH = (Fpclk/fi2c + 1) / 2; // 设置I2C时钟为fi2c
I2SCLL = (Fpclk/fi2c) / 2;
I2CONCLR = 0x2C;
I2CONSET = 0x40; // 使能主I2C
/* 设置I2C中断允许 */
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl0 = 0x29; // I2C通道分配到IRQ slot 0,即优先级最高
VICVectAddr0 = (int32)IRQ_I2C; // 设置I2C中断向量地址
VICIntEnable = 0x0200; // 使能I2C中断
}
/****************************************************************************
* 名 称:WrEepromErr()
* 功 能:读写EEPRM出错LED闪烁。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void WrEepromErr(void)
{
while(1)
{
PINSEL0=PINSEL0&0xFFFFFCFF; //管脚功能选择寄存器,配置p0.4为IO功能
IO0DIR=IO0DIR|0x10;//配置p0.4口方向为输出,0为输入,1为输出
IO0SET=IO0SET|0x10;//设置p0.4口输出为1,led熄灭
DelayNS(50);
IO0CLR=LED1;//输出清零寄存器。
//该寄存器控制输出管脚的状态。
//写入 1 使对应管脚输出低电平
//并清零 IOSET 寄存器中的对应位。写入0 无效。
DelayNS(50);
}
}
/****************************************************************************
* 名 称:main()
* 功 能:向E2PROM写入10字节数据,然后读出判断是否正确写入。
* 说 明:在CONFIG.H文件中包含I2CINT.H。
****************************************************************************/
int main(void)
{
uint8 i;
//volatile uint8 ii;
IRQEnable();
//PINSEL0 = 0x00000000;
//PINSEL1 = 0x00000000;
//IO0DIR = BEEPCON;
//IO0SET = BEEPCON;
I2C_Init(400000); // I2C初始化,总线速率400kb/s
//IO0DIR = 0x040;
//IO0SET = 0x040;
//IO0CLR = 0x040;
ISendStr(CAT1025, 0x00, data_buf, 12); // 在0x00地址处写入10字节数据
DelayNS(10); // 等待写周期结束
for(i=0; i<12; i++) //清零数据缓冲区,防止出错
data_buf[i] = 0;
IRcvStr(CAT1025, 0x00, data_buf, 12); // 在0x00地址处读出10字节数据
/* 校验读出的数据,若不正确则LED闪烁 */
for(i=0; i<12; i++)
{
if(data_buf[i]!=data_buf1[i])
{
WrEepromErr();
DelayNS(1);
}
}
/* 校验读出的数据,正确则LED常亮 */
PINSEL0=PINSEL0&0xFFFFFCFF; //管脚功能选择寄存器,配置p0.4为IO功能
IO0DIR=IO0DIR|0x10;//配置p0.4口方向为输出,0为输入,1为输出
IO0SET=IO0SET|0x10;//设置p0.4-p0.6口输出全为1,led熄灭
DelayNS(50);
IO0CLR=LED1;//输出清零寄存器。
//该寄存器控制输出管脚的状态。
//写入 1 使对应管脚输出低电平
//并清零 IOSET 寄存器中的对应位。写入0 无效。
while(1);
return(0);
}