STM32F103固件库编程(6)—I2C

STM32F103固件库编程(6)—I2C

(一)I2C时序表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(二) STM32的I2C特性及架构

在这里插入图片描述
在这里插入图片描述

(三)寄存器映射

在这里插入图片描述在这里插入图片描述

(四)代码(CV工程师)

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

uint8_t readData[10]={0};
uint8_t writeData[8]={4,5,6,7,8,9,10,11};

int main(void)
{	
	
	uint8_t i=0;
  USART_Config();
	printf("IIC\n");
	
	I2C_EE_Config();

	EEPROM_Byte_Write(11,55);
	
	EEPROM_WaitForWriteEnd();
	
	EEPROM_Byte_Write(12,52);
	
	EEPROM_WaitForWriteEnd();
	
	EEPROM_Page_Write(16,writeData,8);
	
	EEPROM_WaitForWriteEnd();
	
	EEPROM_Read(16,readData,8);
	
	for(i=0;i<8;i++)
	{	
		printf("%d ",readData[i]);	
	}
	printf("111111111111111111");
	
  while(1)
	{	
	}	
}
#ifndef __BSP_I2C_H
#define	__BSP_I2C_H

#include "stm32f10x.h"

#define EEPROM_ADDR   0xA0
#define STM32_I2C_OWN_ADDR     0x5f 

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

#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 /* __BSP_I2C_H */
#include "bsp_i2c.h"

 /**
  * @brief  IIC EEPROM  配置,工作参数配置
  * @param  无
  * @retval 无
  */
void I2C_EE_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef  I2C_InitStructure; 

	// 打开IIC GPIO的时钟
	EEPROM_I2C_GPIO_APBxClkCmd(EEPROM_I2C_SCL_GPIO_CLK|EEPROM_I2C_SDA_GPIO_CLK, ENABLE);
	
	// 打开IIC 外设的时钟
	EEPROM_I2C_APBxClkCmd(EEPROM_I2C_CLK, ENABLE);

	// 将IIC SCL的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(EEPROM_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);

  // 将IIC SDA的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SDA_GPIO_PIN;
	GPIO_Init(EEPROM_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置IIC的工作参数
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable  ;//使能应答
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//使用7位地址模式
	I2C_InitStructure.I2C_ClockSpeed = EEPROM_I2_BAUDRATE; //配置SCL时钟频率
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;
	I2C_InitStructure.I2C_OwnAddress1 = STM32_I2C_OWN_ADDR; //这是STM32 IIC自身设备地址,只要是总线上唯一即可
	
	I2C_Init(EEPROM_I2C,&I2C_InitStructure);
	
	// 使能串口
	I2C_Cmd (EEPROM_I2C, ENABLE);	    
}
//向EEPROM写入一个字节

void EEPROM_Byte_Write(uint8_t addr,uint8_t data)
{
	//产生起始信号
	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);

  //EV8事件被检测到,发送要存储的数据
	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);
	
	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);

	
	//第二次起始信号
	//产生起始信号
	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_Receiver);
	
  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);

		//EV7事件被检测到,即数据寄存器有新的有效数据	
		*data = I2C_ReceiveData(EEPROM_I2C);
		
		data++;
		
		numByteToRead--;
	}
	//数据传输完成
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);	
	
	//重新配置ACK使能,以便下次通讯
	I2C_AcknowledgeConfig (EEPROM_I2C,ENABLE);

}


//等待EEPROM内部时序完成
void EEPROM_WaitForWriteEnd(void)
{
	
	do
	{
		//产生起始信号
		I2C_GenerateSTART(EEPROM_I2C,ENABLE);
		
		while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_SB) == RESET);
		
		//EV5事件被检测到,发送设备地址
		I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
	}  
	while(I2C_GetFlagStatus (EEPROM_I2C,I2C_FLAG_ADDR) == RESET );

	//EEPROM内部时序完成传输完成
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);	
}

(五)问题

1.高阻态咋回事
在这里插入图片描述2.CCR寄存器——时钟频率的计算

发布了35 篇原创文章 · 获赞 4 · 访问量 4025

猜你喜欢

转载自blog.csdn.net/qq_42589654/article/details/104165447