要使用24C16,首先了解一下它。
1、24C16的总容量是16K bit,转换成字节除以8,即为 2K byte。
2、DEVICE ADDRESS的前四位固定为1010,紧跟着的三位,范围是 000-111(对应十进制0-7),代表着总共有8页。
3、WORD ADDRESS是每一页的字节数,范围是00000000-11111111(十进制0-255),每一页有256个字节,0-255是对应的地址索引。
4、序号2说明了有8页,序号3说明了每一页有256个字节,因此 8*256 = 2048 byte,和序号1的说明是吻合的。
在给出代码之前,先看一张图
测试代码如下:
#ifndef __STM32F10X_H
#define __STM32F10X_H
#include "stm32f10x.h"
#endif
#ifndef __Z_HARDWARE_EEPROM_H
#define __Z_HARDWARE_EEPROM_H
#include "z_hardware_eeprom.h"
#endif
#ifndef __Z_HARDWARE_USART2_H
#define __Z_HARDWARE_USART2_H
#include "z_hardware_usart2.h"
#endif
#ifndef __Z_UTIL_TIME_H
#define __Z_UTIL_TIME_H
#include "z_util_time.h"
#endif
#ifndef __Z_HARDWARE_LED_H
#define __Z_HARDWARE_LED_H
#include "z_hardware_led.h"
#endif
int main(void)
{
u16 i;
// u16 flag;
u8 buf[256];
init_eeprom();
init_led();
init_hardware_usart2_dma(9600);
delay_ms(1000);
buf[0] = 00;
func_usart2_dma_send_bytes(buf, 1);
delay_ms(1000);
//TESTOK
for(i = 0; i < 256; i ++)
{
// buf[i] = 0xff - i;
buf[i] = i;
}
func_i2c_writebytes(buf, 1536, 256);
func_usart2_dma_send_bytes(buf, 256);
delay_ms(1000);
// memset(buf, 0, 256);
// if(func_i2c_readbytes(buf, 256, 0) == ENABLE)
// {
// func_usart2_dma_send_bytes(buf, 256);
// delay_ms(1000);
// }
//
// memset(buf, 0, 256);
// if(func_i2c_readbytes(buf, 256, 256) == ENABLE)
// {
// func_usart2_dma_send_bytes(buf, 256);
// delay_ms(1000);
// }
// memset(buf, 0, 256);
// if(func_i2c_readbytes(buf, 256, 512) == ENABLE)
// {
// func_usart2_dma_send_bytes(buf, 256);
// delay_ms(1000);
// }
// memset(buf, 0, 256);
// if(func_i2c_readbytes(buf, 200, 128) == ENABLE)
// {
// func_usart2_dma_send_bytes(buf, 200);
// delay_ms(1000);
// }
memset(buf, 0, 256);
if(func_i2c_readbytes(buf, 256, 1536) == ENABLE)
{
func_usart2_dma_send_bytes(buf, 256);
delay_ms(1000);
}
for(;;)
{
func_led_a_toggle();
delay_ms(1000);
}
}
测试效果如下:
eeprom的驱动代码如下(仅供参考):
z_hardware_eeprom.h
#ifndef __STM32F10X_H
#define __STM32F10X_H
#include "stm32f10x.h"
#endif
#define EEPROM_HOST_ADDR 0xA0
#define EEPROM_I2C_WR 0
#define EEPROM_I2C_RD 1
void init_eeprom(void);
void func_i2c_delay_us(uint16_t time_us);
u8 func_i2c_start(void);
void func_i2c_stop(void);
void func_i2c_ack(void);
void func_i2c_noack(void);
u8 func_get_i2c_waitack(void);
void func_i2c_sendbyte(uint8_t sendyyte);
u8 func_i2c_receivebyte(void);
u8 func_i2c_writebyte(uint8_t writebyte, uint16_t writeaddr);
u8 func_i2c_writebytes(uint8_t *_pwritebuf, uint16_t _usaddr, uint16_t _ussize);
u8 func_i2c_readbytes(uint8_t* pbuffer, uint16_t len, uint16_t addr_read);
z_hardware_eeprom.c
#ifndef __Z_HARDWARE_EEPROM_H
#define __Z_HARDWARE_EEPROM_H
#include "z_hardware_eeprom.h"
#endif
void init_eeprom(void)
{
GPIO_InitTypeDef GPIO_InitStructure_A;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure_A.GPIO_Pin = GPIO_Pin_4;//WP
GPIO_InitStructure_A.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure_A.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure_A);
GPIO_InitStructure_A.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;//GPIO_Pin_5 GPIO_Pin_6
GPIO_InitStructure_A.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure_A.GPIO_Mode = GPIO_Mode_Out_OD;//GPIO_Mode_AF_OD
GPIO_Init(GPIOA, &GPIO_InitStructure_A);
GPIO_ResetBits(GPIOA , GPIO_Pin_4);//write protection disable
}
void func_i2c_delay_us(uint16_t time_us)
{
uint16_t i,j;
for( i=0;i<time_us;i++ )
{
for( j=0;j<10;j++ );
}
}
void func_wp_enable(void)
{
GPIO_SetBits(GPIOA , GPIO_Pin_4);
}
void func_wp_disable(void)
{
GPIO_ResetBits(GPIOA , GPIO_Pin_4);
}
void func_set_scl_high(void)
{
GPIO_SetBits(GPIOA , GPIO_Pin_5);
}
void func_set_scl_low(void)
{
GPIO_ResetBits(GPIOA , GPIO_Pin_5);
}
void func_set_sda_high(void)
{
GPIO_SetBits(GPIOA , GPIO_Pin_6);
}
void func_set_sda_low(void)
{
GPIO_ResetBits(GPIOA , GPIO_Pin_6);
}
u8 func_get_scl(void)
{
return GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_5);
}
u8 func_get_sda(void)
{
return GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6);
}
u8 func_i2c_start(void)
{
func_set_sda_high();
func_set_scl_high();
func_i2c_delay_us(5);
if(!func_get_sda())
{
return DISABLE;
}
func_set_sda_low();
func_i2c_delay_us(1);
if(func_get_sda())
{
return DISABLE;
}
func_set_sda_low();
func_i2c_delay_us(4);
return ENABLE;
}
void func_i2c_stop(void)
{
func_set_scl_low();
func_i2c_delay_us(1);
func_set_sda_low();
func_i2c_delay_us(1);
func_set_scl_high();
func_i2c_delay_us(5);
func_set_sda_high();
func_i2c_delay_us(5);
}
void func_i2c_ack(void)
{
func_set_scl_low();
func_i2c_delay_us(1);
func_set_sda_low();
func_i2c_delay_us(1);
func_set_scl_high();
func_i2c_delay_us(5);
func_set_scl_low();
func_i2c_delay_us(5);
}
void func_i2c_noack(void)
{
func_set_scl_low();
func_i2c_delay_us(1);
func_set_sda_high();
func_i2c_delay_us(1);
func_set_scl_high();
func_i2c_delay_us(5);
func_set_scl_low();
func_i2c_delay_us(5);
}
u8 func_get_i2c_waitack(void)
{
func_set_scl_low();
func_i2c_delay_us(1);
func_set_sda_high();
func_i2c_delay_us(1);
func_set_scl_high();
func_i2c_delay_us(5);
if(func_get_sda())
{
func_set_scl_low();
return DISABLE;
}
func_set_scl_low();
return ENABLE;
}
void func_i2c_sendbyte(uint8_t sendyyte)
{
uint8_t i = 8;
while(i--)
{
func_set_scl_low();
func_i2c_delay_us(5);
if(sendyyte & 0x80)
{
func_set_sda_high();
}
else
{
func_set_sda_low();
}
sendyyte <<= 1;
func_i2c_delay_us(5);
func_set_scl_high();
func_i2c_delay_us(10);
}
func_set_scl_low();
}
u8 func_i2c_receivebyte(void)
{
uint8_t i = 8;
uint8_t receivebyte = 0;
func_set_sda_high();
while(i--)
{
receivebyte <<= 1;
func_set_scl_low();
func_i2c_delay_us(5);
func_set_scl_high();
func_i2c_delay_us(5);
if(func_get_sda())
{
receivebyte |= 0x01;
}
}
func_set_scl_low();
return receivebyte;
}
u8 func_i2c_writebyte(uint8_t writebyte, uint16_t writeaddr)
{
//24C16 MAX 2048(256*8) bytes(0-2047)
u8 cur_page;
if(writeaddr > 2048 - 1)
{
return DISABLE;
}
cur_page = writeaddr / 256;
if(!func_i2c_start())
{
return DISABLE;
}
func_i2c_sendbyte(EEPROM_HOST_ADDR | (cur_page << 1) | EEPROM_I2C_WR);
if(!func_get_i2c_waitack())
{
func_i2c_stop();
return DISABLE;
}
func_i2c_sendbyte((uint8_t)(writeaddr & 0x00FF));
func_get_i2c_waitack();
func_i2c_sendbyte(writebyte);
func_get_i2c_waitack();
func_i2c_stop();
return ENABLE;
}
u8 func_i2c_writebytes(uint8_t *_pwritebuf, uint16_t _usaddr, uint16_t _ussize)
{
uint16_t i;
uint16_t cur_addr, end_addr;
int8_t cur_page = -1;
cur_addr = _usaddr;
end_addr = _usaddr + _ussize;
if(_usaddr > 2048 - 1)
{
return DISABLE;
}
if(_ussize == 0 || _ussize > 2048)
{
return DISABLE;
}
if(end_addr > 2048 - 1)// read overflow
{
return DISABLE;
}
for(i = cur_addr; i < end_addr; i++)
{
if(cur_page != i / 256 || i % 16 == 0)
{
cur_page = i / 256;
func_i2c_stop();
func_i2c_delay_us(10000);
if(!func_i2c_start())
{
return DISABLE;
}
func_i2c_sendbyte(EEPROM_HOST_ADDR | (cur_page << 1) | EEPROM_I2C_WR);
if(!func_get_i2c_waitack())
{
func_i2c_stop();
return DISABLE;
}
func_i2c_sendbyte((uint8_t)(i & 0x00FF));
func_get_i2c_waitack();
}
func_i2c_sendbyte(*_pwritebuf ++);
func_get_i2c_waitack();
if(i >= end_addr - 1)
{
func_i2c_stop();
func_i2c_delay_us(10000);
}
}
func_i2c_stop();
return ENABLE;
}
u8 func_i2c_readbytes(uint8_t* pbuffer, uint16_t len, uint16_t addr_read)
{
uint16_t cur_addr, end_addr, i;
int8_t cur_page = -1;
cur_addr = addr_read;
end_addr = addr_read + len;
if(addr_read > 2048 - 1)
{
return DISABLE;
}
if(len == 0 || len > 2048)
{
return DISABLE;
}
if(end_addr > 2048 - 1)// read overflow
{
return DISABLE;
}
for(i = cur_addr; i < end_addr; i++)
{
if(cur_page != i / 256)
{
cur_page = i / 256;
if(!func_i2c_start())
{
return DISABLE;
}
func_i2c_sendbyte(EEPROM_HOST_ADDR | (cur_page << 1) | EEPROM_I2C_WR);
if(!func_get_i2c_waitack())
{
func_i2c_stop();
return DISABLE;
}
func_i2c_sendbyte((uint8_t)(i & 0x00FF));
func_get_i2c_waitack();
func_i2c_start();
func_i2c_sendbyte(EEPROM_HOST_ADDR | (cur_page << 1) | EEPROM_I2C_RD);
func_get_i2c_waitack();
}
*pbuffer = func_i2c_receivebyte();
if(i >= end_addr - 1)
{
func_i2c_noack();
}
else
{
func_i2c_ack();
}
pbuffer++;
}
func_i2c_stop();
return ENABLE;
}
补充的是,我使用 PA5->SCL,PA6->SDA。