求救 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 );//软件延时
}
}
24c08 1个page 16个字节
所以最多写16个 那为什么我改下ADDRLEN_EE256 为0 的时候,我能写入24个数据呢。 sinychai 发表于 2021-4-10 15:49
那为什么我改下ADDRLEN_EE256 为0 的时候,我能写入24个数据呢。
写到其他地址去了吧,并不是你想要存的地址,如果是一个字节的地址,就用1个。 还有就是仔细看lc08的datasheet,搞清楚发送时的波形型。结合示波器。一次性弄清eeorom的原理.就是要严格按照eeprom手册上波形。 FM33L0xx系列产能有限,考虑到后面的供应链建议切换到LC0xx系列 好的,解决了,知道怎么回事了。 wangpeng 发表于 2021-4-12 08:52
FM33L0xx系列产能有限,考虑到后面的供应链建议切换到LC0xx系列
我是做电池类的产品的,升级LC0是可以,但是功耗没有L0系列的低。不要小看那3uA,很厉害的。
页:
[1]