Files
HBshuiwuConcentrator/APP/bl24c512.c
2025-12-15 16:07:49 +08:00

674 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "bl24c512.h"
#include "include.h"
static u32 last_write_time;
bool I2C_eeprom_write_byte( u16 addr, u8 data);
bool I2C_eeprom_Read_byte(u16 addr, u8 *data);
void eeprom_da_mode(bool in_mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SDA_PIN;
GPIO_InitStructure.GPIO_Mode = (in_mode == TRUE) ? GPIO_Mode_IN_FLOATING : GPIO_Mode_Out_OD;
GPIO_Init(SDA_PIN_PORT, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SCL_PIN_PORT , &GPIO_InitStructure );
}
/*************************************************************
函数功能:延时连个指令周期
函数名称delayedus
函数返回:无返回值。
函数参数:延时时间
**************************************************************/
void delayed_ms(u8 n)
{
u32 dy;
u8 i;
for(i=0;i<n;i++)
{
dy=3200;
while(dy!=0)
{dy--;}
}
}
void delayedus(u8 n)
{
u8 i;
for(i=0;i<n;i++);
}
/*************************************************************
函数功能I2C总线复位。
函数名称I2C_Reset。
函数返回:无返回值。
函数参数:无参数
**************************************************************/
void I2C_Reset(void)
{
eeprom_da_mode(SDA_MODE_IN);
while(1)
{
SCL_LOW();
delayedus(1);
SCL_HIGH();
if( GET_SDA() ==1 )
{
break;
}
delayedus(1);
}
eeprom_da_mode(SDA_MODE_OUT);
}
void bl24c512_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(SDA_PIN_CLK | SCL_PIN_CLK , ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(SDA_PIN_PORT , &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SCL_PIN_PORT , &GPIO_InitStructure );
//I2C_Reset();
}
/*************************************************************
函数功能:产生起始位。
函数名称I2C_GenerateSTART。
函数返回:无返回值。
函数参数:无参数
**************************************************************/
void BL24C512I2C_GenerateSTART(void)
{
SDA_HIGH();//eeprom_da(1);
SCL_HIGH();//eeprom_clk(1);
delayedus(2);
SDA_LOW();//eeprom_da(0);
delayedus(2);
SCL_LOW();//eeprom_clk(0);
delayedus(2);
}
/*************************************************************
函数功能:产生停始位。
函数名称I2C_GenerateSTOP。
函数返回:无返回值。
函数参数:无参数
**************************************************************/
void BL24C512_I2C_GenerateSTOP(void)
{
SDA_LOW();//eeprom_da(0);
delayedus(2);
SCL_HIGH();//eeprom_clk(1);
SDA_LOW();//eeprom_da(0);
delayedus(2);
SDA_HIGH();//eeprom_da(1);
}
void self_test_eeprom(void)
{
char testBuf[] = "test eeprom";
char buf[15] = {0};
I2C_eeprom_write_buf(32896, (u8*)testBuf, sizeof(testBuf));
I2C_eeprom_read_buf( 32896, (u8*)buf, sizeof(testBuf));
if (cmp_datas((u8*)buf, (u8*)testBuf, sizeof(testBuf)))
{
printf("OK\r\n");
}
else
{
printf("ERROR\r\n");
}
}
/*************************************************************
函数功能:检测应答。
函数名称I2C_check_ack。
函数返回:返回值是应答状态。
函数参数:无参数。
**************************************************************/
unsigned char I2C_check_ack(void)
{
unsigned char ack=0;
eeprom_da_mode(SDA_MODE_IN);
SCL_HIGH();//eeprom_clk(1);
delayedus(1);
if(GET_SDA() ==1)
{
ack=0;
}
else
{
ack=1;
}
SCL_LOW();//eeprom_clk(0);
delayedus(1);
eeprom_da_mode(SDA_MODE_OUT);
return ack;
}
/*************************************************************
函数功能:发送一个应答位。
函数名称I2c_send_ack。
函数返回:无返回值。
函数参数:无。
**************************************************************/
void I2c_send_ack(void)
{
SDA_LOW();//eeprom_da(0);
delayedus(1);
SCL_LOW();//eeprom_clk(0);
delayedus(1);
SCL_HIGH();//eeprom_clk(1);
delayedus(1);
SCL_LOW();//eeprom_clk(0);
SDA_HIGH();//eeprom_da(1);
}
/*************************************************************
函数功能发送一个NO应答。
函数名称I2c_send_no_ack。
函数返回:无返回值。
函数参数:无。
*************************************************************/
void I2c_send_no_ack(void)
{
SDA_HIGH();//eeprom_da(1);
delayedus(1);
SCL_LOW();//eeprom_clk(0);
delayedus(1);
SCL_HIGH();//eeprom_clk(1);
delayedus(1);
SCL_LOW();//eeprom_clk(0);
}
/*************************************************************
函数功能I2C发送一个字节。
函数名称I2c_send_byte。
函数返回:无返回值。
函数参数:无。
*************************************************************/
void I2c_send_byte(unsigned char data )
{
unsigned char i;
SCL_LOW(); //eeprom_clk(0);//clk 0
for(i=0;i<8;i++)
{
if((data&0x80)==0x80)
{
SDA_HIGH();//eeprom_da(1);
}
else
{
SDA_LOW(); //eeprom_da(0);
}
SCL_HIGH(); //eeprom_clk(1);//clk 1
delayedus(1);
SCL_LOW(); //eeprom_clk(0);//clk 0
delayedus(1);
data<<=1;
}
delayedus(90);
}
/*************************************************************
函数功能I2C接收一个字节。
函数名称I2c_receive_byte。
函数返回:无返回值。
函数参数:无。
**************************************************************/
unsigned char I2c_receive_byte(void)
{
unsigned char i;
unsigned char rda=0;
eeprom_da_mode(SDA_MODE_IN);
SCL_LOW(); //eeprom_clk(0);//clk 0
delayedus(1);
for(i=0;i<8;i++)
{
rda<<=1;
SCL_HIGH(); //eeprom_clk(1);//clk 1
delayedus(1);
if(GET_SDA() ==1 )
{
rda|=0x01;
}
else
{
rda&=0xFE;
}
SCL_LOW(); //eeprom_clk(0);//clk 0
delayedus(1);
}
eeprom_da_mode(SDA_MODE_OUT);
return rda;
}
/*************************************************************
函数功能EEPROM检测EEPROM是否空闲可以进行读写
函数名称poll_busy。
函数返回:无返回值。
函数参数EEPROM的地址addr 对应写入数据data。
**************************************************************/
bool poll_busy(void)
{
BL24C512I2C_GenerateSTART();
I2c_send_byte(BL24C512ADDR);
if(I2C_check_ack()== 1)
{
BL24C512_I2C_GenerateSTOP();
return TRUE;
}
else
{
BL24C512_I2C_GenerateSTOP();
return FALSE;
}
}
void wait_eeprom_free(void)
{
while( last_write_time + 6/portTICK_RATE_MS > xTaskGetTickCount() );
while (1)
{
if (poll_busy())
{
break;
}
}
}
/*************************************************************
函数功能EEPROM任意地址写一字节。
函数名称I2C_eeprom_write_byte。
函数返回:无返回值。
函数参数EEPROM的地址addr 对应写入数据data。
**************************************************************/
bool I2C_eeprom_write_byte( u16 addr, u8 data)
{
unsigned char addrlow;
unsigned char addrhigh;
addrlow=(unsigned char)addr;
addrhigh=(unsigned char)(addr>>8);
wait_eeprom_free();
BL24C512I2C_GenerateSTART();
I2c_send_byte(BL24C512ADDR);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrhigh);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrlow);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(data);
if(I2C_check_ack()==0)
{
return FALSE;
}
BL24C512_I2C_GenerateSTOP();
last_write_time = xTaskGetTickCount();
return TRUE;
}
/*************************************************************
函数功能EEPROM任意地址读一字节。
函数名称I2C_eeprom_Read_byte。
函数返回:无返回值。
函数参数EEPROM的地址addr。
**************************************************************/
bool I2C_eeprom_Read_byte(u16 addr, u8 *data)
{
unsigned char devaddr=0;
unsigned char addrlow=0;
unsigned char addrhigh=0;
addrlow=(unsigned char)addr;
addrhigh=(unsigned char)(addr>>8);
wait_eeprom_free();
BL24C512I2C_GenerateSTART();
I2c_send_byte(BL24C512ADDR);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrhigh);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrlow);
if(I2C_check_ack()==0)
{
return FALSE;
}
devaddr=(BL24C512ADDR| 0X01);
BL24C512I2C_GenerateSTART();
I2c_send_byte(devaddr);
if(I2C_check_ack()==0)
{
return FALSE;
}
*data=I2c_receive_byte();
I2c_send_no_ack();
delayedus(1);
BL24C512_I2C_GenerateSTOP();
return TRUE;
}
/*************************************************************
函数功能EEPROM写入数组只能写入小于128byte数据并且不能超过页范围
函数名称I2C_eeprom_write_buf
函数返回:无返回值。
函数参数EEPROM的地址addr。
**************************************************************/
bool I2C_eeprom_write_page(u16 addr, u8 * buf, u8 length)
{
unsigned char addrlow;
unsigned char addrhigh;
addrlow=(unsigned char)addr;
addrhigh=(unsigned char)(addr>>8);
wait_eeprom_free();
BL24C512I2C_GenerateSTART();
I2c_send_byte(BL24C512ADDR);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrhigh);
if(I2C_check_ack()==0)
{
return FALSE;
}
I2c_send_byte(addrlow);
if(I2C_check_ack()==0)
{
return FALSE;
}
for (u8 i = 0; i < length; i++)
{
I2c_send_byte(buf[i]);
if(I2C_check_ack()==0)
{
return FALSE;
}
}
BL24C512_I2C_GenerateSTOP();
last_write_time = xTaskGetTickCount();
return TRUE;
}
/*************************************************************
函数功能EEPROM写入数组只能写入小于128byte数据并且不能超过页范围
函数名称I2C_eeprom_write_buf
函数返回:无返回值。
函数参数EEPROM的地址addr。
**************************************************************/
bool I2C_eeprom_write_buf(u16 startAddr, u8 * buf, u16 length)
{
bl24c512_init();
u16 current_startAddr = startAddr;
u8 first_page_byte = EEPROM_PAGE_SIZE - (startAddr % EEPROM_PAGE_SIZE);
u8 * current_data_ptr = buf;
u16 left_length = length;
u16 integrated_Pages;
u16 end_page_byte;
if (length > first_page_byte)
{
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, first_page_byte))
{
return FALSE;
}
current_startAddr = current_startAddr + first_page_byte;
current_data_ptr += first_page_byte;
left_length = length - first_page_byte;
integrated_Pages = left_length / EEPROM_PAGE_SIZE;
end_page_byte = left_length % EEPROM_PAGE_SIZE;
for (u16 i = 0; i < integrated_Pages; i++)
{
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, EEPROM_PAGE_SIZE))
{
return FALSE;
}
current_startAddr += EEPROM_PAGE_SIZE;
current_data_ptr += EEPROM_PAGE_SIZE;
}
if (end_page_byte > 0)
{
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, end_page_byte))
{
return FALSE;
}
}
}
else
{
if(!I2C_eeprom_write_page(startAddr, buf, length))
{
return FALSE;
}
}
return TRUE;
}
/*************************************************************
函数功能EEPROM读出数组
函数名称I2C_eeprom_write_buf
函数返回:无返回值。
函数参数EEPROM的地址addr。
**************************************************************/
bool I2C_eeprom_read_buf(u16 addr, u8 * buf, u16 length)
{
unsigned char devaddr;
if (length == 0)
{
return FALSE;
}
wait_eeprom_free();
bl24c512_init();
if (I2C_eeprom_Read_byte(addr, buf) == FALSE)
{
return FALSE;
}
length--;
if (length > 0)
{
devaddr=(BL24C512ADDR| 0X01);
BL24C512I2C_GenerateSTART();
I2c_send_byte(devaddr);
if(I2C_check_ack()==0)
{
return FALSE;
}
for (u16 i = 0; i < length; i++)
{
buf[i+ 1] = I2c_receive_byte();
if (i < length - 1)
{
I2c_send_ack();
}
}
I2c_send_no_ack();
BL24C512_I2C_GenerateSTOP();
}
return TRUE;
}