STM32学习之I2C协议(读写EEPROM)

关于STM32学习分享

第七章 I2C协议(读写EEPROM)

前言

单片机的I2C协议(读写EEPROM)。

一、I2C协议(读写EEPROM)

1、SCL
2、SDA

二、代码

1.i2c.c

代码如下(示例):

#include "i2c.h"

//IIC配置
void I2C_EE_Config(void)
{
	I2C_InitTypeDef 	I2C_InitStructure;
	GPIO_InitTypeDef 	GPIO_InitStructure;
	
	//打开串口GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	//打开外设IIC的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
		
	//将IIC SCL的GPIO配置为开漏复用模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
配置IIC的工作参数
	
	//使能应答
	I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;
	//使用7位地址模式
	I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;
	//配置SCL时钟频率
	I2C_InitStructure.I2C_ClockSpeed=400000;
	//占空1/2,9/16
	I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;
	//模式
	I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
	//STM32 IIC 自身设备地址,只要是总线上唯一即可
	I2C_InitStructure.I2C_OwnAddress1=I2C_ADDR;

	//把配置写到寄存器中,完成IIC的初始化配置
	I2C_Init(EEPROM_I2C,&I2C_InitStructure);
	// 使能IIC
	I2C_Cmd(EEPROM_I2C,ENABLE);	
}

//向EEPROM写一个字节
void EEPROM_Byte_Write(uint8_t addr,uint8_t data)
{
	I2C_GenerateSTART(EEPROM_I2C,ENABLE);
	//检测事件EV5
	while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)==ERROR);
	
	I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
	//检测事件EV6
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);
	
	I2C_SendData( EEPROM_I2C,addr);
	//检测EV8
	while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR);
	
	I2C_SendData( EEPROM_I2C,data);
	
	while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)==ERROR);
	//数据传输完成
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
}


//向EEPROM写入多个字节(页写入),每次写入不能超过8个字节

void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite)
{
	//产生起始信号
	I2C_GenerateSTART(EEPROM_I2C,ENABLE);
	
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
	
	//EV5事件被检测到,发送设备地址
	I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
	
  while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);

	//EV6事件被检测到,发送要操作的存储单元地址
	I2C_SendData (EEPROM_I2C,addr);
	
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);

	
	while(numByteToWrite)
	{
		//EV8事件被检测到,发送要存储的数据
		I2C_SendData (EEPROM_I2C,*data);
		
		while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);
		
		data++;
		numByteToWrite--;
			
	}
	//数据传输完成
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);	

}


//从EEPROM读取数据
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
{
	I2C_GenerateSTART(EEPROM_I2C,ENABLE);
	
	//检测事件EV5
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);

	I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
	//检测事件EV6
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);
	
	I2C_SendData( EEPROM_I2C,addr);

	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING)==ERROR);

	I2C_GenerateSTART(EEPROM_I2C,ENABLE);
	
	//检测事件EV5
	while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)==ERROR);
	//更改
	I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Receiver);
	
	//检测EV6
	while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);
	
	while(numByteToRead)
	{
		if(numByteToRead==1)
		{
			//最后一个字节
			I2C_AcknowledgeConfig(EEPROM_I2C,DISABLE);
		}
		//检测EV7
		while(I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)==ERROR);
		
		
		*data = I2C_ReceiveData(EEPROM_I2C);
		data++;
		
		numByteToRead--;	
	}
	
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
	
	I2C_AcknowledgeConfig(EEPROM_I2C,ENABLE);
}

void EEPROM_WaitForWriteEnd(void)
{
	do
	{
		I2C_GenerateSTART(EEPROM_I2C,ENABLE);
		
		//检测EV5
		while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_SB)==RESET);//不要忘记分号
			
		I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
	}
	while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_ADDR)==RESET);

	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);
}

2.i2c.h

代码如下(示例):

#ifndef _I2C_H_
#define _I2C_H_

#include "stm32f10x.h"

//EEPROM 设备地址(8位)
#define EEPROM_ADDR   	0xA0

/** 
* IIC EERPOM的引脚定义
*
*/
#define I2C_ADDR     		0x5E 

	
// IIC
#define  EEPROM_I2C                   I2C1
#define  EEPROM_I2C_CLK               RCC_APB1Periph_I2C1
#define  EEPROM_I2C_APBxClkCmd       	RCC_APB1PeriphClockCmd
#define  EEPROM_I2_BAUDRATE           400000

//IIC GPIO 引脚宏定义
#define  EEPROM_I2C_SCL_GPIO_CLK      	(RCC_APB2Periph_GPIOB)
#define  EEPROM_I2C_SDA_GPIO_CLK       	(RCC_APB2Periph_GPIOB)

#define  EEPROM_I2C_GPIO_APBxClkCmd    	RCC_APB2PeriphClockCmd
    
#define  EEPROM_I2C_SCL_GPIO_PORT       GPIOB  
#define  EEPROM_I2C_SCL_GPIO_PIN        GPIO_Pin_6

#define  EEPROM_I2C_SDA_GPIO_PORT       GPIOB
#define  EEPROM_I2C_SDA_GPIO_PIN        GPIO_Pin_7



void I2C_EE_Config(void);
void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
void EEPROM_WaitForWriteEnd(void);

#endif /*_I2C_H_*/

3.main.c

代码如下(示例):

#include "stm32f10x.h"   
#include "bsp_i2c.h"

uint16_t array[]={1,2,3,4,5,6,7,8,9,10};
uint8_t writeData[8]={4,5,6,7,8,9,10,11};
uint8_t readData[10]={0};
void Delay(uint32_t count)
{
	while(count--);
}	

int main(void)
{
	uint8_t i=0;
	I2C_EE_Config();
	printf("这是一个IIC通讯实验\n");

	//写入一个字节
	EEPROM_Byte_Write(11,55);
	
	//等待写入操作完成
	EEPROM_WaitForWriteEnd();
	
	//写入一个字节
	EEPROM_Byte_Write(12,52);
	
	//等待写入操作完成
	EEPROM_WaitForWriteEnd();
	
	//addr%8 == 0 ,即为地址对齐
	EEPROM_Page_Write(16,writeData,8);
	
	//等待写入操作完成
	EEPROM_WaitForWriteEnd();
	;
	//读取数据
	EEPROM_Read(16,readData,8);
	
	for(i=0;i<8;i++)
	{	
		printf("%d ",readData[i]);
	}
	printf("\nIIC 读取 EEPROM 实验\n");
	
  while(1)
	{		
	}	
	
}

该处使用的url网络请求的数据。
@https://blog.csdn.net/FuYYZ/article/details/114347180


总结

希望能给你有所收获!本文章知识点的学习来自野火教程,更多的知识在野火平台值得初学者去看看!一定有收获的!谢谢!

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图个吉利儿

欢迎大家一起学习!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值