I2C_EEPROM

一、編程要點

1、I2C相關GPIO以及外設使能

2、初始化I2C結構體(模式、地址、速率等參數)

3、編寫I2C讀寫函數

4、對EEPROM進行讀寫

二、結構體&庫函數

1、I2C初始化結構 ( I2C_InitTypeDef 

typedef struct
{
  uint32_t I2C_ClockSpeed;          /*!< I2C通訊速率 不高於400 000 */

  uint16_t I2C_Mode;                /*!< 模式 I2C and  */

  uint16_t I2C_DutyCycle;           /*!<設置佔空比 2   16/9 */

  uint16_t I2C_OwnAddress1;         /*!< 設置STM32自身地址  在總線上唯一即可*/

  uint16_t I2C_Ack;                 /*!<產生應答信號 */

  uint16_t I2C_AcknowledgedAddress; /*!< 7位地址模式 */

}I2C_InitTypeDef;

2、起始 停止 信號產生函數

I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
I2C_GenerateSTART(EEPROM_I2C,ENABLE);
@brief 產生起始信號
@param1:使能或使能

I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
I2C_GenerateSTOP(EEPROM_I2C,ENABLE);	
@brief 產生停止信號
@param1:使能或使能

3、標誌位檢查函數

I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
@brief 檢查I2C相應標誌位
@param1:i2c端口號 
@param2:要檢查的相應標誌位(EV5  EV6 等)
4、廣播設備地址函數
I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
I2C_Send7bitAddress(EEPROM_I2C,EEPROM_ADDR,I2C_Direction_Transmitter);
@brief 廣播要通訊的設備地址(7位)
@param1:i2c端口號 
@param2:設備地址
@param2:讀寫方向

5、發送 讀取數據函數

I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
I2C_SendData (EEPROM_I2C,data);
@brief 向數據緩存寄存器發送數據
@param1:i2c端口號 
@param2:要發送的數據(8位)

uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
data = I2C_ReceiveData(EEPROM_I2C);
@brief 從數據緩存寄存器讀取數據
@param1:i2c端口號 
@retval:讀取到的數據

6、產生應答信號

I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
@brief 產生應答或不產生應答信號
@param1:i2c端口號 
@retval:使能或失能  (應答  非應答)

7、判斷EEPROM內部時序完成函數

void EE_Await(void)
{
	do
	{
		I2C_GenerateSTART(I2C1,ENABLE);		//發送起始信號
		while((I2C_GetFlagStatus(I2C1, I2C_FLAG_SB))==RESET);	//檢測EV5時間並清除標誌

		
		I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter);//廣播要發送的設備地址
	}
	while((I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))==RESET);          //檢測EV6時間並清除標誌
	I2C_GenerateSTOP(I2C1,ENABLE);					 //產生結束信號
}

三、I2C通訊時序

發送數據時序:
S ->      ->  EEPROM地址 ->        ->  Addr  ->        ->  data  ->      ->   data n  ->    data(p) ->      ->p
    EV5                    EV6                 EV8                  EV8                 EV8           EV8_2
讀數據時序:
S ->      ->  EEPROM地址 ->        ->  Addr  ->        ->
    EV5                    EV6                 EV8
S ->      ->  EEPROM地址(讀方向)  ->               (判斷是否最後一個方向)                ->read()->p
    EV5                               EV6(讀方向)       (是則使能應答)  EV7(有新數據到來)     

四、程序源碼

1、eeprom.c文件

#include "eeprom.h"


void I2C_EE_config(void)	
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	I2C_InitTypeDef I2C_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	//打開GPIO時鐘
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;						//選擇SCL線
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	      //開漏輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//輸出速率
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;						//選擇SDA線
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	      //開漏輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			//輸出速率
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	I2C_InitStructure.I2C_ClockSpeed = 400000;
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x5f;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_Init(I2C1, &I2C_InitStructure);

	I2C_Cmd(I2C1,ENABLE);

}

void I2C_WriteByte(uint8_t Addr,uint8_t *pBuffer,uint8_t num)
{
	//uint32_t i=0x1000;	
	//延時等待時間
	I2C_GenerateSTART(I2C1,ENABLE);						//發送起始信號
	
	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)== ERROR);		//檢測EV5時間並清除標誌
	
	I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter);			//廣播要發送的設備地址
	

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)== ERROR);//檢測EV6時間並清除標誌


	I2C_SendData(I2C1,Addr);							//發送寫入設備內存地址

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)== ERROR);	//檢測EV8時間並清除標誌

	
	while(num)
	{
		num--;
		I2C_SendData(I2C1,*pBuffer);					//發送寫入數據
		while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)== ERROR);	//檢測EV8時間並清除標誌

		pBuffer++;
	
	}
	
	

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)== ERROR);		//檢測EV8-2時間並清除標誌

	I2C_GenerateSTOP(I2C1,ENABLE);						//產生結束信號
	
	
}


void I2C_ReadByte(u8 Addr,uint8_t *data,uint8_t num)
{	
	
	I2C_GenerateSTART(I2C1,ENABLE);						//發送起始信號
	
	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)== ERROR);	//檢測EV5時間並清除標誌
	
	I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter);		//廣播要發送的設備地址
	

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)== ERROR);//檢測EV6時間並清除標誌


	I2C_SendData(I2C1,Addr);							//發送寫入設備內存地址

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)== ERROR);	//檢測EV8時間並清除標誌


	I2C_GenerateSTART(I2C1,ENABLE);						//第二次發送起始信號
	
	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)== ERROR);		//檢測EV5時間並清除標誌
	
	I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Receiver);				//廣播要發送的設備地址
	

	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)== ERROR);    //檢測EV6時間並清除標誌
	
	while(num)
	{
		if(num==1)I2C_AcknowledgeConfig(I2C1,DISABLE);
		
		while(I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR); //檢測到EV7事件 表示有新的數據到來

		*data=I2C_ReceiveData(I2C1);
		
		data++;
		num--;
	}

	
	//數據傳輸完成
	I2C_GenerateSTOP(EEPROM_I2C,ENABLE);	
	
	//重新配置ACK使能,以便下次通訊
	I2C_AcknowledgeConfig (EEPROM_I2C,ENABLE);
}

void EE_Await(void)
{
	do
	{
		I2C_GenerateSTART(I2C1,ENABLE);						//發送起始信號
		while((I2C_GetFlagStatus(I2C1, I2C_FLAG_SB))==RESET);			//檢測EV5時間並清除標誌

		
		I2C_Send7bitAddress(I2C1,0XA0,I2C_Direction_Transmitter);		//廣播要發送的設備地址
	}
	while((I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))==RESET); //檢測EV6時間並清除標誌
	I2C_GenerateSTOP(I2C1,ENABLE);				 //產生結束信號
}

2、eeprom.h 文件

#ifndef __EEPROM_H
#define __EEPROM_H

#include "stm32f10x.h"

#define EEPROM_I2C    I2C1

void I2C_EE_config(void);
void I2C_WriteByte(uint8_t Buffer,uint8_t Addr);
void I2C_ReadByte(u8 Addr,uint8_t *data,uint8_t num);
void EE_Await(void);

#endif		//__EEPROM_H
3、main.c 文件
#include "stm32f10x.h"   
#include "bsp_led.h"
#include "usart.h"
#include "eeprom.h"

#define GPIOB_ODR_Addr      (GPIOB_BASE+0X0C)
#define PBout(n)   *(unsigned int *)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr&0x00FFFFFF)<<5)+(n<<2))

uint8_t ReadData[10]={0};
uint8_t writeData[8]={0,1,2,3,4,5,6,7};

int main(void)
{	
    u8 i;
    LED_GPIO_Config();
    PBout(0)=1;
    USART_config();
    I2C_EE_config();    

    I2C_WriteByte(8,writeData,8);	//數據  地址  數量

    EE_Await();
    I2C_ReadByte(8,ReadData,8);	//地址  數據數量

    for(i=0;i<8;i++)                //循環通過串口發送讀取到的數據
    {
        printf("%2d",ReadData[i]);
        PBout(0)=0;
    }
  while(1);
}



 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章