本实验为IIC总线通信协议,以友善之臂mini2440为实验平台,对其开发板上的AT24c08a指定位置写入字符串“hello”,并指定位置读出该位置的内容。
初始工作,首先需要配置GPE14、15管脚分别为IICSLC、IICSDA,并禁止上拉功能。然后设置IIC时钟频率,使能应答信号,并使IIC中断使能,禁止IIC中断屏蔽寄存器。
应答中断处理函数为清除中断标志位,清除中断标记flag。
指定内存写函数的实现为:首先设置主设备发送模式,写入从设备地址,清除中断标记,然后等待应答,写入设备内存地址,等待到应答后开始连续发送数据,存入指定空间。发送结束发出停止命令,结束本次通讯,让IIC状态改为开始状态,准备下一次读写操作。
指定内存读函数,首先配置设备为发送模式,写入要读的设备地址,写入要读的设备内存,设置为主机接收模式,发送接收设备地址,此后从设备会返回一个要读的内存地址,读取该地址抛弃后,连续读取指定内存数据,读到最后一个数据不再产生应答,停止接收,改为准备状态。
AT24C08 的地址格式为: 1 0 1 0 A2 P1 P0 W/R
A2为设备地址位、P1,P0为片内页寻址 LSB=0 写 LSB=1 读
其中mini2440读写位为自动标记无需配置。
本实验实验代码如下:
#define GLOBAL_CLK 1
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"
#define writedevAddr 0xa0;
#define readdevAddr 0xa0;
int flag;
void delay(int times)//延时函数
{
int i;
for(;times>0;times--)
for(i=0;i<400;i++);
}
void init_24c08a(void)
{
rGPEUP |= 0xc000; //禁止上拉
rGPECON |= 0xa00000;//设置管脚为时钟线和数据线
rIICCON = 0xe0; //设置IIC时钟频率,使能应答信号,并开启中断
rIICSTAT = 0x10;//IIC中断使能
rINTMSK &=~(0x1<<27);//禁止IIC中断屏蔽寄存器,使其中断使能
}
static void __irq IicISR(void)//IIC中断函数
{
rSRCPND |=0x1<<27;
rINTPND |=0x1<<27;
flag=0;//标记中断发生
}
void wr_24c08a(unsigned char wordAddr,unsigned char *buffer,int sizeofdate) //写EEPROM程序
{
int i;
flag=1;//应答标记为无应答
rIICSTAT=0xf0;//设置为在主设备发送模式
rIICDS=writedevAddr;//写入从设备地址
rIICCON &=~(0x1<<4);//清除应答中断标记位
while(flag)//等待中断是否发生,即从设备是否有应答
delay(100);
flag=1;//清除中断标记
rIICDS=wordAddr;//写入设备内存地址
rIICCON &=~(0x1<<4);//清除应答中断标记位
while(flag)//等待中断是否发生,即从设备是否有应得
delay(100);
for(i=0;i<sizeofdate;i++)//连续写入数据
{
flag =1;
rIICDS =*(buffer+i);
rIICCON &=~(0x1<<4);//清除应答中断标记位
while(flag)
delay(100);
}
rIICSTAT=0xd0;//发出停止命令,结束本次通讯
rIICCON =0xe0;//为下次通讯做准备
delay(100);
}
void rd24c02a(unsigned char wordAddr,unsigned char *buffer,int sizeofdate )//读指定内存地址程序
{
int i;
unsigned char temp;
flag =1;
rIICSTAT = 0xf0; //主设备发送模式
rIICDS=readdevAddr; //发送要读设备地址
rIICCON &= ~0x10; //清中断标志
while(flag)
delay(100);
flag = 1;
rIICDS = wordAddr;//发送要读取内存地址
rIICCON &= ~0x10;
while(flag)
delay(100);
flag = 1;
rIICSTAT = 0xb0; //主设备接收模式
rIICDS =readdevAddr; //真正发送要读取从设备地址,开始接收数据
rIICCON &= ~0x10;
while (flag)
delay(100);
flag = 1;
temp = rIICDS;//读取从设备地址
rIICCON &= ~0x10;
while(flag)
delay(100);
//连续读
for(i=0;i<sizeofdate;i++)
{
flag = 1;
if(i==sizeofdate-1) //如果是最后一个数据
rIICCON &= ~0x80; //不再响应
*(buffer+i) = rIICDS;
rIICCON &= ~0x10;
while(flag)
delay(100);
}
rIICSTAT = 0x90; //结束该次通讯
rIICCON = 0xe0; //为下次通讯做准备
delay(100);
}
void Main()
{
int i;
unsigned char *ptr,*ptr1;
unsigned char data[6]="hello",data1[6];
ptr=data;
ptr1=data1;
MMU_Init();//内存初始化
init_24c08a();//IIC初始化
pISR_IIC = (U32)IicISR;//中断函数入口地址传递给中断向量表
wr_24c08a(0x0,ptr,6);//向EEPROM写入hello字符串
delay(500);//写完不能马上读,否则出乱码,此处反复实验终于解决读乱码问题!
rd24c02a(0x0,ptr1,6);//读出EEPROM内的数据并用Uart_print()函数打印出来
Uart_Printf("从EEPROM读出的数据为:");
for(i=0;i<5;i++)
{
Uart_Printf("%c",data1[i]);
}
}