NUC140之I2C和AT24C32
阿新 • • 發佈:2019-01-12
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。