1. 程式人生 > >NUC140之I2C和AT24C32

NUC140之I2C和AT24C32

I2C匯流排一根資料線,一根時鐘線,起始和終止條件如下:

AT24C32是一款4K位元組的EEPROM,它的位元組寫如下圖:

具體的文字描述結合我的程式一看就明白了,我的程式註釋非常豐富

/*****************************************
*檔名:at24c32.c                       *
*功能:EEPROM讀寫程式      	             *
******************************************/
#include "at24c32.h"

void at24c32_write (uint8_t device_address, uint8_t data_high_address, uint8_t data_low_address, uint8_t data_);
uint8_t at24c32_read (uint8_t device_address, uint8_t data_high_address, uint8_t data_low_address);

/**************************************************
*函式名:at24c32_initialize 					  *
*功能:	 EEPROM初始化      	                      *
*出口引數:無									  *
*入口引數:無									  *
**************************************************/


void at24c32_initialize (void)
{
	uint8_t temp_data = 0;
	DrvGPIO_InitFunction (E_FUNC_I2C1);    //PA.10,PA.11設定為I2C
	DrvSYS_UnlockProtectedReg ();          //解鎖受保護的系統暫存器
	DrvSYS_SetIPClock (E_SYS_I2C1_CLK, 1); //使能I2C埠1的核心時鐘    
	DrvSYS_LockProtectedReg ();            //對系統暫存器上鎖
	DrvI2C_Open (I2C_PORT1, 100000);       //使能I2C埠1,時鐘為100KHz
										   //由於所有I2C埠共用一個時鐘分頻器,所以每個I2C埠的時鐘頻率必須設為一致,且不能超過1MHz
	delay (100);                           //延遲使時鐘穩定

	temp_data = at24c32_read (DEVICE_ADDRESS, EEPROM_INITIALIZED_HIGH_ADDRESS, EEPROM_INITIALIZED_LOW_ADDRESS);
	if (temp_data != 0xfe)
	{
		at24c32_write(DEVICE_ADDRESS, EEPROM_INITIALIZED_HIGH_ADDRESS, EEPROM_INITIALIZED_LOW_ADDRESS, 0xfe);                 //對最後一個地址寫資料表明EEPROM已被初始化
		at24c32_write(DEVICE_ADDRESS, RADIO_MAIN_HIGH_ADDRESS, RADIO_MAIN_LOW_ADDRESS, RADIO_MAIN_DEFAULT);                   
		at24c32_write(DEVICE_ADDRESS, ENABLE_PTT_LIMIT_HIGH_ADDRESS, ENABLE_PTT_LIMIT_LOW_ADDRESS, ENABLE_PTT_LIMIT_DEFAULT); 
		at24c32_write(DEVICE_ADDRESS, PTT_LIMIT_TIME_HIGH_ADDRESS, PTT_LIMIT_TIME_LOW_ADDRESS, PTT_LIMIT_TIME_DEFAULT);     
		at24c32_write(DEVICE_ADDRESS, POWER_VALUE_HIGH_ADDRESS, POWER_VALUE_LOW_ADDRESS, POWER_VALUE_DEFAULT);             
		at24c32_write(DEVICE_ADDRESS, MODULATION_VALUE_HIGH_ADDRESS, MODULATION_VALUE_LOW_ADDRESS, MODULATION_VALUE_DEFAULT);
		at24c32_write(DEVICE_ADDRESS, ENABLE_ERROR_HIGH_ADDRESS, ENABLE_ERROR_LOW_ADDRESS, ENABLE_ERROR_DEFAULT);          
		at24c32_write(DEVICE_ADDRESS, FREQUENCY_HIGH_ADDRESS, FREQUENCY_LOW_ADDRESS, FREQUENCY_DEFAULT);                  
		at24c32_write(DEVICE_ADDRESS, CHANNEL_SPACE_HIGH_ADDRESS, CHANNEL_SPACE_LOW_ADDRESS, CHANNEL_SPACE_DEFAULT);          
	}
}

/**************************************************
*函式名:at24c32_write     					      *
*功能:  EEPROM寫程式       	                  *
*出口引數:無									  *
*入口引數:裝置8位地址,寫資料高8位地址,		  *
*            低8位地址,8位資料	                  *
**************************************************/

void at24c32_write (uint8_t device_address, uint8_t data_high_address, uint8_t data_low_address, uint8_t data_)
{
 	DrvI2C_Ctrl (I2C_PORT1, 1, 0, 0, 0);             //I2C埠1傳送一個起始標誌(註釋若有不明白的,參晶片手冊中文版216頁起好好看看)
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)     //查詢中斷標誌位SI,當起始已被髮送時,SI為0x08
	{
	}

	DrvI2C_WriteData (I2C_PORT1, device_address);    //將at24c32裝置地址(高7位)+寫命令(0)存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);		     //清除中斷標誌位,準備傳送地址+寫命令(0)
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)     //查詢中斷標誌位,當從機地址+W已被髮送且收到ACK時SI 不為0,為0x18
	{
	}

	DrvI2C_WriteData (I2C_PORT1, data_high_address); //將資料高8位地址(前四位任意)存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			 //清除中斷標誌位,準備傳送資料高8位地址
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)	 //查詢中斷標誌位,當高8位地址已被髮送且收到ACK時SI 不為0,為0x28
	{
	}

	DrvI2C_WriteData (I2C_PORT1, data_low_address);   //將資料低8位地址存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除中斷標誌位,準備傳送資料低8位地址
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)	  //查詢中斷標誌位,當高8位地址已被髮送且收到ACK時SI 不為0,為0x28
	{
	}

	DrvI2C_WriteData (I2C_PORT1, data_);              //將要寫的資料存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除中斷標誌位,準備傳送要寫入的資料
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)	  //查詢中斷標誌位,當高8位地址已被髮送且收到ACK時SI 不為0,為0x28
	{
	}

	DrvI2C_Ctrl (I2C_PORT1, 0, 1, 1, 0);              //I2C埠1傳送一個結束標誌且清除SI
	delay(MINIMUM_DELAY);							              //at24c32寫資料之後要給至少10ms才能再寫一個數據,在此給40ms延遲
}

 /**************************************************
 *函式名:	at24c32_read     					  *
 *功能:	EEPROM讀程式       	                  *
 *出口引數:讀取的8位資料						  *
 *入口引數:讀資料高8位地址,低8位地址			  *
 *************************************************/

uint8_t at24c32_read (uint8_t device_address, uint8_t data_high_address, uint8_t data_low_address)
{
	uint8_t data_read;
	DrvI2C_Ctrl (I2C_PORT1, 1, 0, 0, 0);              //I2C埠1傳送一個起始標誌
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0)	  //查詢中斷標誌位SI,當起始已被髮送時,SI為0x08
	{
	}
	DrvI2C_WriteData (I2C_PORT1, device_address);	  //將at24c32裝置地址(高7位)+寫命令(0)存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除中斷標誌位,準備傳送地址+寫命令(0)
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	  //查詢中斷標誌位,當從機地址+W已被髮送且收到ACK時SI 不為0,為0x18
	{
	}

	DrvI2C_WriteData (I2C_PORT1, data_high_address);  //將資料高8位地址(前四位任意)存入I2CDAT中
 	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除中斷標誌位,準備傳送資料高8位地址
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	  //查詢中斷標誌位,當高8位地址已被髮送且收到ACK時SI 不為0,為0x28
	{
	}

	DrvI2C_WriteData (I2C_PORT1, data_low_address);   //將資料低8位地址存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除中斷標誌位,準備傳送資料低8位地址
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	  //查詢中斷標誌位,當高8位地址已被髮送且收到ACK時SI 不為0,為0x28
	{
	}
	
	DrvI2C_Ctrl (I2C_PORT1, 1, 0, 1, 0);              //傳送一個再開始標誌並清SI
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	  //查詢中斷標誌位SI,當再開始起始已被髮送時,SI為0x10
	{
	}
	
	DrvI2C_WriteData (I2C_PORT1, device_address+1);   //將at24c32裝置地址+讀命令(1),+1表示讀存入I2CDAT中
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);			  //清除SI準備傳送從機地址+讀命令
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	  //查詢中斷標誌位,當從機地址+讀命令已傳送且收到ACK時,SI不為0,為0x40
	{
	}
	
	DrvI2C_Ctrl (I2C_PORT1, 0, 0, 1, 0);		       //清除中斷標誌位,不設定ACK,因為24C32讀資料不會回傳ACK應答
	while ((DrvI2C_GetIntFlag (I2C_PORT1)) == 0);	   //查詢中斷標誌位,若已收到資料且無ACK時,SI不為0,為0x58
	{
	}

	data_read = DrvI2C_ReadData (I2C_PORT1);           //讀取資料
	DrvI2C_Ctrl (I2C_PORT1, 0, 1, 1, 0);			   //清除SI且發生結束標誌
	return (data_read); 
}











標頭檔案如下:

#ifndef at24c32_h
#define at24c32_h

#include "stdint.h"
#include "common_variables.h"
#include "DrvGPIO.h"
#include "DrvI2C.h"
#include "DrvSYS.h"
#include "delay.h"
#define MINIMUM_DELAY 150	 //at24c32寫資料最低延遲時間10ms,在此給15ms

//定義AT24C32的地址單元
#define DEVICE_ADDRESS 0xa0                     //EEPROM地址,1010 0000,前四位固定,地址為000,最後一位寫是0,讀是1

#define EEPROM_INITIALIZED_HIGH_ADDRESS 0xff	//判斷EEPROM是否以及被初始化的地址單元
#define EEPROM_INITIALIZED_LOW_ADDRESS  0xff

#define RADIO_MAIN_HIGH_ADDRESS         0xf0   
#define RADIO_MAIN_LOW_ADDRESS          0x01
#define	RADIO_MAIN_DEFAULT              0x00	

#define ENABLE_PTT_LIMIT_HIGH_ADDRESS   0xf0   
#define ENABLE_PTT_LIMIT_LOW_ADDRESS    0x02
#define ENABLE_PTT_LIMIT_DEFAULT        0x01    

#define PTT_LIMIT_TIME_HIGH_ADDRESS     0xf0    
#define PTT_LIMIT_TIME_LOW_ADDRESS      0x03   
#define PTT_LIMIT_TIME_DEFAULT          0x01	

#define POWER_VALUE_HIGH_ADDRESS        0xf0	
#define POWER_VALUE_LOW_ADDRESS         0x04
#define POWER_VALUE_DEFAULT             0x32    

#define MODULATION_VALUE_HIGH_ADDRESS   0xf0	
#define MODULATION_VALUE_LOW_ADDRESS    0x05
#define MODULATION_VALUE_DEFAULT        0x5a 

#define ENABLE_ERROR_HIGH_ADDRESS       0xf0   
#define ENABLE_ERROR_LOW_ADDRESS        0x06
#define ENABLE_ERROR_DEFAULT            0x01   

#define FREQUENCY_HIGH_ADDRESS          0xf0  
#define FREQUENCY_LOW_ADDRESS           0x07
#define FREQUENCY_DEFAULT               0x76   

#define CHANNEL_SPACE_HIGH_ADDRESS      0xf0   
#define CHANNEL_SPACE_LOW_ADDRESS       0x08
#define CHANNEL_SPACE_DEFAULT           0x01    

extern void at24c32_initialize (void); //初始化at24c32
extern void at24c32_write (uint8_t device_address,    //EEPROM地址
						   uint8_t data_high_address, //寫資料高8為地址,前四位任意 
					       uint8_t data_low_address,  //寫資料低8位地址
					       uint8_t data_); 		      //8位資料
extern uint8_t at24c32_read (uint8_t device_address,	 //EEPROM地址
							 uint8_t data_high_address,  //讀資料高8位地址
				             uint8_t data_low_address);  //讀資料低8為地址
#endif

注意!!!

對AT24C32連續寫資料時,每寫一個位元組要等待10ms,否則會寫入失敗,這是由晶片特性決定的,

可以參看DATASHEET。