STM32F103RC引脚模拟I2C操作EEPROM(24C16)的方法总结

3 篇文章 0 订阅
1 篇文章 0 订阅

要使用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。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是一个使用stm32f103模拟读取24c16的例子程序: #include "stm32f10x.h" #include "stm32f10x_i2c.h" #define EEPROM_ADDRESS 0xA0 // 24C16芯片的地址 void EEPROM_WriteByte(uint16_t address, uint8_t data) { // 初始化I2C模块 I2C_InitTypeDef i2c_init_struct; I2C_StructInit(&i2c_init_struct); i2c_init_struct.I2C_Mode = I2C_Mode_I2C; i2c_init_struct.I2C_DutyCycle = I2C_DutyCycle_2; i2c_init_struct.I2C_OwnAddress1 = 0x00; i2c_init_struct.I2C_Ack = I2C_Ack_Enable; i2c_init_struct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c_init_struct.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &i2c_init_struct); // 开启I2C模块 I2C_Cmd(I2C1, ENABLE); // 发送起始信号 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // 发送设备地址和写入模式 I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 发送要写入的地址 I2C_SendData(I2C1, address); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 发送要写入的数据 I2C_SendData(I2C1, data); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 发送停止信号 I2C_GenerateSTOP(I2C1, ENABLE); while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); } uint8_t EEPROM_ReadByte(uint16_t address) { // 初始化I2C模块 I2C_InitTypeDef i2c_init_struct; I2C_StructInit(&i2c_init_struct); i2c_init_struct.I2C_Mode = I2C_Mode_I2C; i2c_init_struct.I2C_DutyCycle = I2C_DutyCycle_2; i2c_init_struct.I2C_OwnAddress1 = 0x00; i2c_init_struct.I2C_Ack = I2C_Ack_Enable; i2c_init_struct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c_init_struct.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &i2c_init_struct); // 开启I2C模块 I2C_Cmd(I2C1, ENABLE); // 发送起始信号 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // 发送设备地址和写入模式 I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 发送要读取的地址 I2C_SendData(I2C1, address); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 重新产生起始信号,并发送设备地址和读取模式 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // 接收数据 while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t data = I2C_ReceiveData(I2C1); // 发送停止信号 I2C_GenerateSTOP(I2C1, ENABLE); while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); return data; } int main(void) { uint16_t address = 0x00; // 要读取的数据在EEPROM中的地址 uint8_t data; // 在某个地址写入数据 EEPROM_WriteByte(address, 0x55); // 从该地址读取数据 data = EEPROM_ReadByte(address); while (1) { // 你的其他代码 } } 这个例子程序演示了如何使用stm32f103I2C模块来模拟读取24C16 EEPROM芯片中的数据。首先,通过初始化I2C模块的相关配置,然后发送起始信号并将设备地址发送到I2C总线上。接着,通过I2C发送要读取的地址,并重新产生起始信号并发送设备地址和读取模式。最后,通过I2C进行数据的接收,并发送停止信号来结束通信。在主函数中,通过调用EEPROM_WriteByte函数和EEPROM_ReadByte函数来写入和读取EEPROM芯片中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值