⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 单片机开发列程
💻 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 + -