sinychai 发表于 2021-4-8 16:39:22

求救 FM33L026读取E2PROM的问题,

各位大神,本人小白在实例中使用的是24c256,本人用的是24c08,地址为0xA0,但是用里面的Test_I2C中的函数只能写入14个字节,吧Len改一下最多也是只能写入24字节。很奇怪。有没有好心的人帮助下。最好给中文批注。
#include "define_all.h"
#include <string.h>
#define SSP_TBIT         (8*clkmode)                //36us 注意根据cpu主频调整延时量
#define        I2CREAD                1        //I2C读操作
#define        I2CWRITE        0        //I2C写操作
#define        STARTBIT        0       
#define        RESTARTBIT        1
#define        STOPBIT                2
#define DEVICE_EE256        0xA0        //FM24C256的器件地址
#define ADDRLEN_EE256        0                //FM24C256的数据地址长度为2字节
uint08 I2C_Send_Bit( uint08 BIT_def )
{
        uint08 i;

        I2C_MSP_CFGR_MSPEN_Setable(ENABLE);//使能I2C电路
       
        switch(BIT_def)
        {
                case STARTBIT:
                        I2C_SEND_STARTBIT();
            for( i=0; i<2*SSP_TBIT; i++ )
      {
          if( SET == I2C_MSP_ISR_S_Chk() ) break;
       
      }
                        break;
               
                case RESTARTBIT:
                        I2C_SEND_RESTARTBIT();
            for( i=0; i<2*SSP_TBIT; i++ )
      {
          if( SET == I2C_MSP_ISR_S_Chk() ) break;

      }
                        break;
               
                case STOPBIT:
                        I2C_SEND_STOPBIT();
            for( i=0; i<2*SSP_TBIT; i++ )
      {
          if( SET == I2C_MSP_ISR_P_Chk() ) break;
      }
                        break;
       
               
                default:
                        break;
        }

        if( i < 2*SSP_TBIT )
        {
                i = I2C_MSP_ISR_S_Chk();
               
                return 0; //ok
        }
        else
        {
                return 1; //failure.
        }
}
uint08 I2C_Send_Byte( uint08 x_byte )
{
        uint16 i;

        I2C_MSP_BUF_Write(x_byte);//写发送缓冲寄存器

        for( i=0; i<18*SSP_TBIT; i++ )
        {
                if( SET == I2C_MSP_ISR_TXIF_Chk() ) break; //中断标志置位时跳出循环
        }
       
        if( i < 18*SSP_TBIT )
        {
                I2C_MSP_ISR_TXIF_Clr(); //clr int flag

                if( SET == I2C_MSP_ISR_ACKSTA_Chk() ) //从机无应答
                {
                        return 2; //失败
                }
                else
                {
                        return 0; //成功
                }
        }
        else
        {
                return 1; //failure.
        }
}
uint08 I2C_Receive_Byte( uint08 *x_byte )
{
        uint16 i;

        //i2c en, rcen
        I2C_MSP_CR_RCEN_Setable(ENABLE);

        for( i=0; i<18*SSP_TBIT; i++ )
        {
                if( SET == I2C_MSP_ISR_RXIF_Chk() ) break; //中断标志置位, 跳出循环
        }

        if( i < 18*SSP_TBIT )
        {
                *x_byte = I2C_MSP_BUF_Read();

                I2C_MSP_ISR_RXIF_Clr(); //clr int flag

                return 0;
        }
        else
        {
                return 1; //failure.
        }
}
uint08 Sendaddr( uint08 Device, uint16 Addr, uint08 AddrLen, uint08 Opt )
{
        uint08 result, Devi_Addr;
       
        Devi_Addr = Device;


        //-------------- start bit -------------
        result = I2C_Send_Bit( STARTBIT );//发送起始位
        if( result != 0 ) return 1; //failure.
       
        //-------------- disable read -------------
        I2C_MSP_CR_RCEN_Setable( DISABLE );

        //-------------- device addr -------------
        result = I2C_Send_Byte( Devi_Addr ); //发送器件地址
        if( result != 0 ) return 2; //failure.

        //--------------- data addr --------------

        result = I2C_Send_Byte( Addr>>0 ); //发送数据地址低8位
        if( result != 0 ) return 3; //failure.

        if( Opt == I2CREAD ) //读操作
        {
                result = I2C_Send_Bit( RESTARTBIT ); //发送重起始位
                if( result != 0 ) return 5; //failure.
               
                result = I2C_Send_Byte( Devi_Addr|1 ); //发送器件地址,读取
                if( result != 0 ) return 5; //failure.
        }
               
        return 0; //ok
}
uint08 Wait_for_end( uint08 Device )
{
        uint08 result, Devi_Addr;

        Devi_Addr = Device;
       
        Do_DelayStart(); //需要5ms的内部写周期, 循环一次所需时间: 42个Delay()。
        {
                I2C_Send_Bit( STARTBIT );        //发送起始位

                result = I2C_Send_Byte( Devi_Addr ); //发送器件地址

                I2C_Send_Bit( STOPBIT ); //发送停止位

                if( result == 0 ) return 0; //设置地址成功, 写周期结束

        }While_DelayMsEnd(5*clkmode);

        return 1; //设置地址失败
}

uint08 I2C_Write_Bottom(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint08 Len)
{
        uint08 k, n, status;
       
        if(Len > 128) return 0xFF;//一次最多操作128字节
       
        for( k=0; k<3; k++ )//每遍最多写3次
        {                                        
                status = 0;
                if( Sendaddr( Device, Addr, AddrLen, I2CWRITE ) )
    {
      status = 1; //写入失败
    }
                else
                {
                        for( n=0; n<Len; n++ )
                        {
                                //发送一个字节
                                if( I2C_Send_Byte( Buf ) )
      {
          status = 1;
          break;
      } //写入失败
                        }
                }
                //发送停止位
                if( I2C_Send_Bit( STOPBIT ) )
       status = 1;
               
                if( status == 0 )
    {
      Wait_for_end(Device);
      break;
    } //写正确
        }
       
        return( status );
}


/**
返回1 是失败
**/
uint08 I2C_Read_Bottom(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint08 Len)
{
        uint08 k, n, status;
       
        if(Len > 128) return 0xFF;//一次最多操作128字节
       
        for( k=0; k<3; k++ )//每遍最多读3次
        {
                status = 0;
                if( Sendaddr( Device, Addr, AddrLen, I2CREAD ) )
      status = 1; //写入失败
                else
                {
                        for( n=0; n<Len; n++ )
                        {
                                if( n < (Len-1) )
                                        I2C_SEND_ACK_0();        //主机将给从机的回应为0
                                else
                                        I2C_SEND_ACK_1();        //主机将给从机的回应为1
                               
                                //接收一个字节
                                if( I2C_Receive_Byte( Buf+n ) )
      {
          status = 1;
          break;
      }
       
                        }
                }
                //发送停止位
                if( I2C_Send_Bit( STOPBIT ) )
      status = 1;        //失败
               
                if( status == 0 ) break;//读正确
        }
       
        return( status );
}

void I2C_Init(void)
{
        I2C_Deinit(); //复位I2C
        RCC_PERCLK_SetableEx(I2CCLK, ENABLE);                //I2C总线时钟使能
        RCC_OPC_CR1_I2CCKE_Setable(ENABLE);          //I2C工作时钟使能
        //I2CIO口配置
        AltFunIO( GPIOA, GPIO_Pin_11, ALTFUN_OPENDRAIN );        //PA11;//SCL
        AltFunIO( GPIOA, GPIO_Pin_12, ALTFUN_OPENDRAIN );        //PA12;//SDA
       
        I2C_MSP_BGR_MSPBRGH_Set((I2C_BaudREG_Calc( 100000, 8000000))<<16);//100k@8M
        I2C_MSP_BGR_MSPBRGL_Set(I2C_BaudREG_Calc( 100000, 8000000));//100k@8M

       
        NVIC_DisableIRQ(I2C_IRQn);
//        NVIC_SetPriority(I2C_IRQn,2);
//        NVIC_EnableIRQ(I2C_IRQn);       
}

uint08 Test_I2C(void)
{
        uint08 Device = DEVICE_EE256;
        uint16 Addr;
        uint08 AddrLen = 0;
        uint08 Buf;
        uint08 Len = 0;
        uint08 Result = 0;
       
        uint08 TestData = {1,2,3,4,5,6,7};
       
//        IWDT_Clr();             //清系统看门狗       
       
        Addr = 0;
        Len = 24;
       
        //memset(Buf, 0, 64);
        Result = I2C_Read_Bottom(Device, Addr, AddrLen, Buf, Len);//读ee测试
        //Result = I2C_Write_Bottom(Device, Addr, AddrLen, Buf, Len);//写ee测试
       
        memset(Buf, 0xFA, 64);
        //memcpy(Buf, TestData, 7);
        Result = I2C_Write_Bottom(Device, Addr, AddrLen, Buf, Len);//写ee测试
        TicksDelayMs(10,NULL);
        memset(Buf, 0, 64);
        Result = I2C_Read_Bottom(Device, Addr, AddrLen, Buf, Len);//读ee测试
       
//        IWDT_Clr();             //清系统看门狗       
        return Result;
}

int main (void)
{       
        Init_System();                        //系统初始化
        I2C_Init();
        Test_I2C();

        for( ; ; )
{
//                IWDT_Clr();             //清系统看门狗                       
                LED0_ON;                    //LED0闪烁
                TicksDelayMs( 100, NULL );//软件延时


}       
}




复旦微刘浏 发表于 2021-4-9 16:59:58

24c08 1个page 16个字节
所以最多写16个

sinychai 发表于 2021-4-10 15:49:29

那为什么我改下ADDRLEN_EE256 为0 的时候,我能写入24个数据呢。

顾博文 发表于 2021-4-12 08:37:32

sinychai 发表于 2021-4-10 15:49
那为什么我改下ADDRLEN_EE256 为0 的时候,我能写入24个数据呢。

写到其他地址去了吧,并不是你想要存的地址,如果是一个字节的地址,就用1个。 还有就是仔细看lc08的datasheet,搞清楚发送时的波形型。结合示波器。一次性弄清eeorom的原理.就是要严格按照eeprom手册上波形。

wangpeng 发表于 2021-4-12 08:52:37

FM33L0xx系列产能有限,考虑到后面的供应链建议切换到LC0xx系列

sinychai 发表于 2021-4-12 10:48:25

好的,解决了,知道怎么回事了。

sinychai 发表于 2021-4-12 13:01:44

wangpeng 发表于 2021-4-12 08:52
FM33L0xx系列产能有限,考虑到后面的供应链建议切换到LC0xx系列

我是做电池类的产品的,升级LC0是可以,但是功耗没有L0系列的低。不要小看那3uA,很厉害的。
页: [1]
查看完整版本: 求救 FM33L026读取E2PROM的问题,