📄 i2c.c
字号:
#define __I2C_H__
#include "Config.h"
#define SLA24CL04 0xA4 //1010,0(A2)1(A1)0(高半叶)0 低256字节
#define SLA3104Mem 0xA0 //1010,*(无关位)0(A1)0(A0)0
#define SLA3104RTC 0xD0 //1101,*(无关位)0(A1)0(A0)0
/********************************************************************************************************
函数名称:I2CMasterInit
函数功能:初始化I2C模块
输 入:无
输 出:无
********************************************************************************************************/
void I2CMasterInit(void)
{
PERIPHEN1 |= BIT5; //使能I2C外设模块
I2CTIMING = 0x0C; //大概100KHz
I2CCONFIG = 0x01; //主模式
}
/********************************************************************************************************
函数名称:WaitTxEmpty
函数功能:等待发送空
输 入:无
输 出:无
********************************************************************************************************/
void WaitTxEmpty(void)
{
#ifdef DOWNLOAD
while((I2CSTATUS & BIT0) == 0x00);
#endif
}
/********************************************************************************************************
函数名称:WaitRxAvailable
函数功能:等待接收完毕
输 入:无
输 出:无
********************************************************************************************************/
void WaitRxAvailable(void)
{
#ifdef DOWNLOAD
while((I2CSTATUS & BIT1) == 0x00);
#endif
}
/********************************************************************************************************
函数名称:WaitI2CIdle
函数功能:等待I2C总线空闲
输 入:无
输 出:无
********************************************************************************************************/
void WaitI2CIdle(void)
{
#ifdef DOWNLOAD
while((I2CSTATUS & BIT3) == 0x00);
#endif
}
/********************************************************************************************************
**函数名称:I2CNByteRecv
**函数功能:I2C总线向有子地址器件读取多字节数据函数
**输 Sla 从机地址;
** SubAddr 丛机子地址;
** pRecvBuf 待发送的数据缓冲头指针,若是发送单字节则直接取变量地址即可;
** Num 待发送数据的字节数
**输 出:返回0表示操作失败,返回1表示操作成功
********************************************************************************************************/
uchar I2CNByteRecv(uchar Sla, uint SubAddr, uchar *pRecvBuf, uint Num)
{
I2CRXTX = Sla; //写从机地址,发送写命令
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr >> 8);
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF);
WaitTxEmpty(); //等待发送完成
WaitI2CIdle(); //等待总线空闲(这将产生一个停止)
I2CRXTX = Sla + 1; //发送读命令,重新启动总线
WaitTxEmpty(); //等待发送完成
for(; Num > 1; Num --)
{
WaitRxAvailable(); //等待接收数据完成
*pRecvBuf = I2CRXTX;
pRecvBuf ++;
}
I2CCONFIG |= BIT1; //接收完最后一个数据发送非应答
WaitRxAvailable(); //等待接收数据完成
*pRecvBuf = I2CRXTX;
I2CCONFIG &= ~BIT1; //接收完最后一个数据发送非应答
WaitI2CIdle();
return 1;
}
/********************************************************************************************************
**函数名称:I2CNByteSend
**函数功能:I2C 总线向有子地址器件发送多字节数据函数
**输 入: Sla 从机地址;
** SubAddr 丛机子地址;
** pStr 待发送的数据缓冲头指针,若是发送单字节则直接取变量地址即可;
** Num 待发送数据的字节数
**输 出: 返回0表示操作失败,返回1表示操作成功
********************************************************************************************************/
uchar I2CNByteSend(uchar Sla, uint SubAddr, uchar *pSendBuf, uint Num)
{
I2CRXTX = Sla; //写从机地址,发送写命令
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr >> 8);
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF);
WaitTxEmpty(); //等待发送完成
for(; Num > 0; Num --)
{
I2CRXTX = *pSendBuf;
pSendBuf ++;
WaitTxEmpty(); //等待发送完成
}
WaitI2CIdle();
return 1;
}
/********************************************************************************************************
24CL04的读写有一些特殊故单写出来
********************************************************************************************************/
/********************************************************************************************************
**函数名称:FM24CL04NByteRecv
**函数功能:I2C总线向有子地址器件读取多字节数据函数
**输 入:Sla 从机地址;
* SubAddr 丛机子地址;
* pRecvBuf 待发送的数据缓冲头指针,若是发送单字节则直接取变量地址即可;
* Num 待发送数据的字节数
**输 出:返回0表示操作失败,返回1表示操作成功
********************************************************************************************************/
uchar FM24CL04NByteRecv(uchar Sla, uint SubAddr, uchar *pRecvBuf, uint Num)
{
uchar UserSla;
if(SubAddr <= 0xFF) //写低页数据
{
UserSla = Sla; //保存从机地址
I2CRXTX = Sla; //写从机地址,发送写命令
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF);
WaitTxEmpty(); //等待发送完成
}
else
{
UserSla = (Sla | BIT1); //保存从机地址
I2CRXTX = (Sla | BIT1); //写从机地址,发送写命令,选择低半页,256字节
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF); //低八位地址
WaitTxEmpty(); //等待发送完成
}
WaitI2CIdle();
I2CRXTX = UserSla + 1; //发送读命令,重新启动总线
WaitTxEmpty(); //等待发送完成
for(; Num > 1; Num --)
{
WaitRxAvailable(); //等待接收数据完成
*pRecvBuf = I2CRXTX;
pRecvBuf ++;
}
I2CCONFIG |= BIT1; //接收完最后一个数据发送非应答
WaitRxAvailable(); //等待接收数据完成
*pRecvBuf = I2CRXTX;
I2CCONFIG &= ~BIT1; //接收完最后一个数据发送非应答
WaitI2CIdle();
return 1;
}
/********************************************************************************************************
**函数名称:FM24CL04NByteSend
**函数功能:I2C 总线向有子地址器件发送多字节数据函数
**输 入:Sla 从机地址;
* SubAddr 丛机子地址;
* pStr 待发送的数据缓冲头指针,若是发送单字节则直接取变量地址即可;
* Num 待发送数据的字节数
**输 出:返回0表示操作失败,返回1表示操作成功
********************************************************************************************************/
uchar FM24CL04NByteSend(uchar Sla, uint SubAddr, uchar *pSendBuf, uint Num)
{
if(SubAddr <= 0xFF) //写低页数据
{
I2CRXTX = Sla; //写从机地址,发送写命令
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF);
WaitTxEmpty(); //等待发送完成
}
else
{
I2CRXTX = (Sla | BIT1); //写从机地址,发送写命令,选择低半页,256字节
WaitTxEmpty(); //等待发送完成
I2CRXTX = (uchar)(SubAddr & 0xFF); //低八位地址
WaitTxEmpty(); //等待发送完成
}
for(; Num > 0; Num --)
{
I2CRXTX = *pSendBuf;
pSendBuf ++;
WaitTxEmpty(); //等待发送完成
}
WaitI2CIdle();
return 1;
}
/********************************************************************************************************
**函数名称:FM24CL04Test
**函数功能:24CL04数据存储器测试
**输 入:无
**输 出:无
********************************************************************************************************/
void FM24CL04Test(void)
{
//------------------------------------------------------------
//I2C接口存储器FM24CL04测试使用到的变量
//------------------------------------------------------------
uint Addr;
uchar DatWR; //写入的数据
uchar xdata WRStore[512] = {0}; //写入数据存储的数组
uchar xdata RDStore[512] = {0}; //读取的数据存储殊组
//------------------------------------------------------------
Addr = 0x0000; //24CL04的地址计数器
UART0_Printf("\n ->FM24CL04 test begin! \n");
//------------------------------------------------------------
//先将待写的数据存储,方便用写多字节的方法一次写入
//------------------------------------------------------------
for(Addr = 0x00; Addr < 512; Addr ++)
{
DatWR = (int)rand();
WRStore[Addr] = DatWR;
}
FM24CL04NByteSend(SLA24CL04, 0x00, WRStore, 512);
#ifdef FM24CL04DATASHOW
UART0_Printf("\n\n Write to 0x:%x \n",0x0000);
for(Addr = 0x00; Addr < 512; Addr ++)
{
UART0_Printf(" %d ",(int)WRStore[Addr]);
}
#endif
//------------------------------------------------------------
//读出所有的数据并存起来,下面将其写入的数据挨个比较
//------------------------------------------------------------
FM24CL04NByteRecv(SLA24CL04, 0x00, RDStore, 512);
#ifdef FM24CL04DATASHOW
UART0_Printf("\n\n Read from 0x:%x \n",0x0000);
for(Addr = 0x00; Addr < 512; Addr ++)
{
UART0_Printf(" %d ",(int)RDStore[Addr]);
}
#endif
for(Addr = 0x00; Addr < 512; Addr ++) //检查是否有错误
{
if(RDStore[Addr] == WRStore[Addr])
{;}
else
{
UART0_Printf("\n\n Data Err Occur at 0x:%x \n\n", Addr);
}
}
UART0_Printf("\n FM24CL04 test OK! \n");
}
//****************************************************************************************************
//FM3104内部数据存储器测试
//传入参数:无
//返 回 值:无
//测试方法:写入512个随机数,再读回来比较
//****************************************************************************************************
void FM3104MemTest(void)
{
//------------------------------------------------------------
//I2C接口存储器FM24CL04内部存储器测试使用到的变量
//------------------------------------------------------------
uint xdata Addr;
uchar xdata DatWR; //写入的数据
uchar xdata WRStore[512] = {0}; //写入数据存储的数组
uchar xdata RDStore[512] = {0}; //读取的数据存储殊组
//------------------------------------------------------------
Addr = 0x0000; //3104Mem的地址计数器
UART0_Printf("\n ->FM3104Mem test begin: \n");
//------------------------------------------------------------
//先将待写的数据存储,方便用写多字节的方法一次写入
//------------------------------------------------------------
for(Addr = 0x00; Addr < 512; Addr ++)
{
DatWR = (int)rand();
WRStore[Addr] = DatWR;
}
I2CNByteSend(SLA3104Mem, 0x00, WRStore, 512);
#ifdef FM3104MEMDATASHOW
UART0_Printf("\n\n Write to 0x:%x \n",0x0000);
for(Addr = 0x00; Addr < 512; Addr ++)
{
UART0_Printf(" %d ",(int)WRStore[Addr]);
}
#endif
//------------------------------------------------------------
//读出所有的数据并存起来,下面将其写入的数据挨个比较
//------------------------------------------------------------
I2CNByteRecv(SLA3104Mem, 0x00, RDStore, 512);
#ifdef FM3104MEMDATASHOW
UART0_Printf("\n\n Read from 0x:%x\n",0x0000);
for(Addr = 0x00; Addr < 512; Addr ++)
{
UART0_Printf(" %d ",(int)RDStore[Addr]);
}
#endif
for(Addr = 0x00; Addr < 512; Addr ++) //检查是否有错误
{
if(RDStore[Addr] == WRStore[Addr])
{;}
else
{
UART0_Printf("\n\n Data Err Occur at 0x:%x \n\n", Addr);
}
}
UART0_Printf("\n FM3104Mem test OK! \n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -