一、應用簡介
I2C 通訊協議(Inter-Integrated Circuit)是由 Phiilps 公司開發的,由于它引腳少,硬體實作簡單,可擴展性強,不需要 USART、CAN 等通訊協議的外部收發設備,現在被廣泛地使用在系統內多個集成電路(IC)間的通訊,
在計算機科學里,大部分復雜的問題都可以通過分層來簡化,如芯片被分為內核層和片上外設;STM32 標準庫則是在暫存器與用戶代碼之間的軟體層,對于通訊協議,我們也以分層的方式來理解,最基本的是把它分為物理層和協議層,物理層規定通訊系統中具有機械、電子功能部分的特性,確保原始資料在物理媒體的傳輸,協議層主要規定通訊邏輯,統一收發雙方的資料打包、解包標準,簡單來說物理層規定我們用嘴巴還是用肢體來交流,協議層則規定我們用中文還是英文來交流,
下面我們分別對 I2C 協議的物理層及協議層進行講解,
1.1 物理層

它的物理層有如下特點:
(1) 它是一個支持設備的總線,“總線”指多個設備共用的信號線,在一個 I2C 通訊總線中,可連接多個 I2C 通訊設備,支持多個通訊主機及多個通訊從機,
(2) 一個 I2C 總線只使用兩條總線線路,一條雙向串行資料線(SDA) ,一條串行時鐘線(SCL),資料線即用來表示資料,時鐘線用于資料收發同步,
(3) 每個連接到總線的設備都有一個獨立的地址,主機可以利用這個地址進行不同設備之間的訪問,
(4) 總線通過上拉電阻接到電源,當 I2C 設備空閑時,會輸出高阻態,而當所有設備都空閑,都輸出高阻態時,由上拉電阻把總線拉成高電平,
(5) 多個主機同時使用總線時,為了防止資料沖突,會利用仲裁方式決定由哪個設備占用總線,
(6) 具有三種傳輸模式:標準模式傳輸速率為 100kbit/s ,快速模式為 400kbit/s ,高速模式下可達 3.4Mbit/s,但目前大多 I2C 設備尚不支持高速模式,
(7) 連接到相同總線的 IC 數量受到總線的最大電容 400pF 限制 ,
1.2 協議層
I2C 的協議定義了通訊的起始和停止信號、資料有效性、回應、仲裁、時鐘同步和地址廣播等環節,
1.2.1 I2C基本讀寫程序
先看看 I2C 通訊程序的基本結構,它的通訊程序見下圖,

S : 傳輸開始信號
SLAVE_ADDRESS: 從機地址
R/W: 傳輸方向選擇位,1 為讀,0 為寫
A/ A: 應答(ACK)或非應答(NACK)信號
P : 停止傳輸信號
1.2.2 I2C頁寫

1.2.3 I2C隨機讀

1.2.4 I2C起始停止信號

前文中提到的起始(S)和停止§信號是兩種特殊的狀態,見上圖,當 SCL 線是高電平時 SDA 線從高電平向低電平切換,這個情況表示通訊的起始,當 SCL 是高電平時 SDA 線由低電平向高電平切換,表示通訊的停止,起始和停止信號一般由主機產生,
1.2.5 I2C應答非應答信號

I2C 的資料和地址傳輸都帶回應,回應包括“應答(ACK)”和“非應答(NACK)”兩種信號,作為資料接收端時,當設備(無論主從機)接收到 I2C 傳輸的一個位元組資料或地址后,若希望對方繼續發送資料,則需要向對方發送“應答(ACK)”信號,發送方會繼續發送下一個資料;若接收端希望結束資料傳輸,則向對方發送“非應答(NACK)”信號,發送方接收到該信號后會產生一個停止信號,結束信號傳輸,見上圖,
2.2 配置代碼
示例直接采用野火的軟體I2C,這里串口列印我就不貼了,自己翻看以前的文章,
board_i2c.h
/**===========================================================================
@file board_i2c.h
@brief 本檔案是用于I2C驅動
@author 青梅煮久
@version r0.1
@date 2021/01/13
----------------------------------------------------------------------------
Remark: (備注描述)
使用野火的軟體I2C
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/13 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
#ifndef _BOARD_I2C_H
#define _BOARD_I2C_H
/*********************************************************************
* INCLUDES
*/
#include <inttypes.h>
/*********************************************************************
* DEFINITIONS
*/
#define EEPROM_I2C_WR 0 /* 寫控制bit */
#define EEPROM_I2C_RD 1 /* 讀控制bit */
/* 定義I2C總線連接的GPIO埠, 用戶只需要修改下面4行代碼即可任意改變SCL和SDA的引腳 */
#define EEPROM_GPIO_PORT_I2C GPIOB /* GPIO埠 */
#define EEPROM_RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO埠時鐘 */
#define EEPROM_I2C_SCL_PIN GPIO_Pin_6 /* 連接到SCL時鐘線的GPIO */
#define EEPROM_I2C_SDA_PIN GPIO_Pin_7 /* 連接到SDA資料線的GPIO */
/* 定義讀寫SCL和SDA的宏,已增加代碼的可移植性和可閱讀性 */
#if 0 /* 條件編譯: 1 選擇GPIO的庫函式實作IO讀寫 */
#define EEPROM_I2C_SCL_1() GPIO_SetBits(EEPROM_GPIO_PORT_I2C, EEPROM_I2C_SCL_PIN) /* SCL = 1 */
#define EEPROM_I2C_SCL_0() GPIO_ResetBits(EEPROM_GPIO_PORT_I2C, EEPROM_I2C_SCL_PIN) /* SCL = 0 */
#define EEPROM_I2C_SDA_1() GPIO_SetBits(EEPROM_GPIO_PORT_I2C, EEPROM_I2C_SDA_PIN) /* SDA = 1 */
#define EEPROM_I2C_SDA_0() GPIO_ResetBits(EEPROM_GPIO_PORT_I2C, EEPROM_I2C_SDA_PIN) /* SDA = 0 */
#define EEPROM_I2C_SDA_READ() GPIO_ReadInputDataBit(EEPROM_GPIO_PORT_I2C, EEPROM_I2C_SDA_PIN) /* 讀SDA口線狀態 */
#else /* 這個分支選擇直接暫存器操作實作IO讀寫 */
/* 注意:如下寫法,在IAR最高級別優化時,會被編譯器錯誤優化 */
#define EEPROM_I2C_SCL_1() EEPROM_GPIO_PORT_I2C->BSRR = EEPROM_I2C_SCL_PIN /* SCL = 1 */
#define EEPROM_I2C_SCL_0() EEPROM_GPIO_PORT_I2C->BRR = EEPROM_I2C_SCL_PIN /* SCL = 0 */
#define EEPROM_I2C_SDA_1() EEPROM_GPIO_PORT_I2C->BSRR = EEPROM_I2C_SDA_PIN /* SDA = 1 */
#define EEPROM_I2C_SDA_0() EEPROM_GPIO_PORT_I2C->BRR = EEPROM_I2C_SDA_PIN /* SDA = 0 */
#define EEPROM_I2C_SDA_READ() ((EEPROM_GPIO_PORT_I2C->IDR & EEPROM_I2C_SDA_PIN) != 0) /* 讀SDA口線狀態 */
#endif
/*********************************************************************
* API FUNCTIONS
*/
void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(void);
uint8_t i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);
uint8_t i2c_CheckDevice(uint8_t _Address);
#endif /* _BOARD_I2C_H */
board_i2c.c
/**===========================================================================
@file board_i2c.c
@brief 本檔案是用于I2C驅動
@author 青梅煮久
@version r0.1
@date 2021/01/13
----------------------------------------------------------------------------
Remark: (備注描述)
應用說明:
在訪問I2C設備前,請先呼叫 i2c_CheckDevice() 檢測I2C設備是否正常,該函式會配置GPIO
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/13 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
/*********************************************************************
* INCLUDES
*/
#include "board_i2c.h"
#include "stm32f10x.h"
static void i2c_CfgGpio(void);
static void i2c_Delay(void);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief CPU發起I2C總線啟動信號
@param 無
@return 無
*/
void i2c_Start(void)
{
/* 當SCL高電平時,SDA出現一個下跳沿表示I2C總線啟動信號 */
EEPROM_I2C_SDA_1();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SDA_0();
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
}
/**
@brief CPU發起I2C總線停止信號
@param 無
@return 無
*/
void i2c_Stop(void)
{
/* 當SCL高電平時,SDA出現一個上跳沿表示I2C總線停止信號 */
EEPROM_I2C_SDA_0();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SDA_1();
}
/**
@brief CPU向I2C總線設備發送8bit資料
@param ucByte -[in] 等待發送的位元組
@return 無
*/
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先發送位元組的高位bit7 */
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
EEPROM_I2C_SDA_1();
}
else
{
EEPROM_I2C_SDA_0();
}
i2c_Delay();
EEPROM_I2C_SCL_1();
i2c_Delay();
EEPROM_I2C_SCL_0();
if (i == 7)
{
EEPROM_I2C_SDA_1(); // 釋放總線
}
_ucByte <<= 1; /* 左移一個bit */
i2c_Delay();
}
}
/**
@brief CPU從I2C總線設備讀取8bit資料
@param 無
@return 讀到的資料
*/
uint8_t i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
/* 讀到第1個bit為資料的bit7 */
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
EEPROM_I2C_SCL_1();
i2c_Delay();
if (EEPROM_I2C_SDA_READ())
{
value++;
}
EEPROM_I2C_SCL_0();
i2c_Delay();
}
return value;
}
/**
@brief CPU產生一個時鐘,并讀取器件的ACK應答信號
@param 無
@return 回傳0表示正確應答,1表示無器件回應
*/
uint8_t i2c_WaitAck(void)
{
uint8_t re;
EEPROM_I2C_SDA_1(); /* CPU釋放SDA總線 */
i2c_Delay();
EEPROM_I2C_SCL_1(); /* CPU驅動SCL = 1, 此時器件會回傳ACK應答 */
i2c_Delay();
if (EEPROM_I2C_SDA_READ()) /* CPU讀取SDA口線狀態 */
{
re = 1;
}
else
{
re = 0;
}
EEPROM_I2C_SCL_0();
i2c_Delay();
return re;
}
/**
@brief CPU產生一個ACK信號
@param 無
@return 無
*/
void i2c_Ack(void)
{
EEPROM_I2C_SDA_0(); /* CPU驅動SDA = 0 */
i2c_Delay();
EEPROM_I2C_SCL_1(); /* CPU產生1個時鐘 */
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
EEPROM_I2C_SDA_1(); /* CPU釋放SDA總線 */
}
/**
@brief CPU產生1個NACK信號
@param 無
@return 無
*/
void i2c_NAck(void)
{
EEPROM_I2C_SDA_1(); /* CPU驅動SDA = 1 */
i2c_Delay();
EEPROM_I2C_SCL_1(); /* CPU產生1個時鐘 */
i2c_Delay();
EEPROM_I2C_SCL_0();
i2c_Delay();
}
/**
@brief 檢測I2C總線設備,CPU向發送設備地址,然后讀取設備應答來判斷該設備是否存在
@param _Address -[in] 設備的I2C總線地址
@return 0 表示正確, 回傳1表示未探測到
*/
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_CfgGpio(); /* 配置GPIO */
i2c_Start(); /* 發送啟動信號 */
/* 發送設備地址+讀寫控制bit(0 = w, 1 = r) bit7 先傳 */
i2c_SendByte(_Address | EEPROM_I2C_WR);
ucAck = i2c_WaitAck(); /* 檢測設備的ACK應答 */
i2c_Stop(); /* 發送停止信號 */
return ucAck;
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 配置I2C總線的GPIO,采用模擬IO的方式實作
@param 無
@return 無
*/
static void i2c_CfgGpio(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(EEPROM_RCC_I2C_PORT, ENABLE); /* 打開GPIO時鐘 */
GPIO_InitStructure.GPIO_Pin = EEPROM_I2C_SCL_PIN | EEPROM_I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 開漏輸出 */
GPIO_Init(EEPROM_GPIO_PORT_I2C, &GPIO_InitStructure);
/* 給一個停止信號, 復位I2C總線上的所有設備到待機模式 */
i2c_Stop();
}
/**
@brief I2C總線位延遲,最快400KHz
@param 無
@return 無
*/
static void i2c_Delay(void)
{
uint8_t i;
/*
下面的時間是通過邏輯分析儀測驗得到的,
作業條件:CPU主頻72MHz ,MDK編譯環境,1級優化
回圈次數為10時,SCL頻率 = 205KHz
回圈次數為7時,SCL頻率 = 347KHz, SCL高電平時間1.5us,SCL低電平時間2.87us
回圈次數為5時,SCL頻率 = 421KHz, SCL高電平時間1.25us,SCL低電平時間2.375us
*/
for (i = 0; i < 10; i++);
}
board_eeprom.h
/**===========================================================================
@file board_eeprom.h
@brief 本檔案是用于EEPROM(AT24C02)驅動
@author 青梅煮久
@version r0.1
@date 2021/01/14
----------------------------------------------------------------------------
Remark: (備注描述)
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/14 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
#ifndef __I2C_EE_H
#define __I2C_EE_H
/*********************************************************************
* INCLUDES
*/
#include "stm32f10x.h"
/*********************************************************************
* DEFINITIONS
*/
/*
* AT24C02 2kb = 2048bit = 2048/8 B = 256 B
* 32 pages of 8 bytes each
*
* Device Address
* 1 0 1 0 A2 A1 A0 R/W
* 1 0 1 0 0 0 0 0 = 0XA0
* 1 0 1 0 0 0 0 1 = 0XA1
*/
/* AT24C01/02每頁有8個位元組
* AT24C04/08A/16A每頁有16個位元組
*/
#define EEPROM_DEV_ADDR 0xA0 /* 24xx02的設備地址 */
#define EEPROM_PAGE_SIZE 8 /* 24xx02的頁面大小 */
#define EEPROM_SIZE 256 /* 24xx02總容量 */
/*********************************************************************
* API FUNCTIONS
*/
uint8_t ee_CheckOk(void);
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize);
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize);
void ee_Erase(void);
uint8_t ee_Test(void);
#endif /* __I2C_EE_H */
board_eeprom.c
/**===========================================================================
@file board_eeprom.c
@brief 本檔案是用于EEPROM(AT24C02)驅動
@author 青梅煮久
@version r0.1
@date 2021/01/14
----------------------------------------------------------------------------
Remark: (備注描述)
----------------------------------------------------------------------------
History
----------------------------------------------------------------------------
<Date> | <Version> | <Author> | <Description>
-------------|-----------|----------------|---------------------------------
2021/01/14 | r0.1 | 青梅煮久 | 創建
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
-------------|-----------|----------------|---------------------------------
| | |
============================================================================*/
/*********************************************************************
* INCLUDES
*/
#include "main.h"
#include "board_eeprom.h"
#include "board_i2c.h"
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief 判斷串行EERPOM是否正常
@param 無
@return 1 表示正常, 0 表示不正常
*/
uint8_t ee_CheckOk(void)
{
if (i2c_CheckDevice(EEPROM_DEV_ADDR) == 0)
{
return 1;
}
else
{
/* 失敗后,切記發送I2C總線停止信號 */
i2c_Stop();
return 0;
}
}
/**
@brief 從串行EEPROM指定地址處開始讀取若干資料
@param _pReadBuf -[in] 存放讀到的資料的緩沖區指標
@param _usAddress -[in] 起始地址
@param _usSize -[in] 資料長度,單位為位元組
@return 0 表示失敗,1表示成功
*/
uint8_t ee_ReadBytes(uint8_t *_pReadBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint16_t i;
/* 采用串行EEPROM隨即讀取指令序列,連續讀取若干位元組 */
/* 第1步:發起I2C總線啟動信號 */
i2c_Start();
/* 第2步:發起控制位元組,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR); /* 此處是寫指令 */
/* 第3步:等待ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第4步:發送位元組地址,24C02只有256位元組,因此1個位元組就夠了,如果是24C04以上,那么此處需要連發多個地址 */
i2c_SendByte((uint8_t)_usAddress);
/* 第5步:等待ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第6步:重新啟動I2C總線,前面的代碼的目的向EEPROM傳送地址,下面開始讀取資料 */
i2c_Start();
/* 第7步:發起控制位元組,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_RD); /* 此處是讀指令 */
/* 第8步:發送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
/* 第9步:回圈讀取資料 */
for (i = 0; i < _usSize; i++)
{
_pReadBuf[i] = i2c_ReadByte(); /* 讀1個位元組 */
/* 每讀完1個位元組后,需要發送Ack, 最后一個位元組不需要Ack,發Nack */
if (i != _usSize - 1)
{
i2c_Ack(); /* 中間位元組讀完后,CPU產生ACK信號(驅動SDA = 0) */
}
else
{
i2c_NAck(); /* 最后1個位元組讀完后,CPU產生NACK信號(驅動SDA = 1) */
}
}
/* 發送I2C總線停止信號 */
i2c_Stop();
return 1; /* 執行成功 */
cmd_fail: /* 命令執行失敗后,切記發送停止信號,避免影響I2C總線上其他設備 */
/* 發送I2C總線停止信號 */
i2c_Stop();
return 0;
}
/**
@brief 向串行EEPROM指定地址寫入若干資料,采用頁寫操作提高寫入效率
@param _pWriteBuf -[in] 存放寫資料的緩沖區指標
@param _usAddress -[in] 起始地址
@param _usSize -[in] 資料長度,單位為位元組
@return 0 表示失敗,1表示成功
*/
uint8_t ee_WriteBytes(uint8_t *_pWriteBuf, uint16_t _usAddress, uint16_t _usSize)
{
uint16_t i,m;
uint16_t usAddr;
/*
寫串行EEPROM不像讀操作可以連續讀取很多位元組,每次寫操作只能在同一個page,
對于24xx02,page size = 8
簡單的處理方法為:按位元組寫操作模式,沒寫1個位元組,都發送地址
為了提高連續寫的效率: 本函式采用page wirte操作,
*/
usAddr = _usAddress;
for (i = 0; i < _usSize; i++)
{
/* 當發送第1個位元組或是頁面首地址時,需要重新發起啟動信號和地址 */
if ((i == 0) || (usAddr & (EEPROM_PAGE_SIZE - 1)) == 0)
{
/* 第0步:發停止信號,啟動內部寫操作 */
i2c_Stop();
/* 通過檢查器件應答的方式,判斷內部寫操作是否完成, 一般小于 10ms
CLK頻率為200KHz時,查詢次數為30次左右
*/
for (m = 0; m < 1000; m++)
{
/* 第1步:發起I2C總線啟動信號 */
i2c_Start();
/* 第2步:發起控制位元組,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */
i2c_SendByte(EEPROM_DEV_ADDR | EEPROM_I2C_WR); /* 此處是寫指令 */
/* 第3步:發送一個時鐘,判斷器件是否正確應答 */
if (i2c_WaitAck() == 0)
{
break;
}
}
if (m == 1000)
{
goto cmd_fail; /* EEPROM器件寫超時 */
}
/* 第4步:發送位元組地址,24C02只有256位元組,因此1個位元組就夠了,如果是24C04以上,那么此處需要連發多個地址 */
i2c_SendByte((uint8_t)usAddr);
/* 第5步:等待ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
}
/* 第6步:開始寫入資料 */
i2c_SendByte(_pWriteBuf[i]);
/* 第7步:發送ACK */
if (i2c_WaitAck() != 0)
{
goto cmd_fail; /* EEPROM器件無應答 */
}
usAddr++; /* 地址增1 */
}
/* 命令執行成功,發送I2C總線停止信號 */
i2c_Stop();
return 1;
cmd_fail: /* 命令執行失敗后,切記發送停止信號,避免影響I2C總線上其他設備 */
/* 發送I2C總線停止信號 */
i2c_Stop();
return 0;
}
/**
@brief 擦除EEPROM
@param 無
@return 無
*/
void ee_Erase(void)
{
uint16_t i;
uint8_t buf[EEPROM_SIZE];
/* 填充緩沖區 */
for (i = 0; i < EEPROM_SIZE; i++)
{
buf[i] = 0x00;
}
/* 寫EEPROM, 起始地址 = 0,資料長度為 256 */
if (ee_WriteBytes(buf, 0, EEPROM_SIZE) == 0)
{
printf("擦除eeprom出錯!\r\n");
return;
}
else
{
printf("擦除eeprom成功!\r\n");
}
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief 延時函式
@param 無
@return 無
*/
static void ee_Delay(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
/**
@brief eeprom AT24C02 讀寫測驗
@param 無
@return 正常回傳1,例外回傳0
*/
uint8_t ee_Test(void)
{
uint16_t i;
uint8_t write_buf[EEPROM_SIZE];
uint8_t read_buf[EEPROM_SIZE];
/*-----------------------------------------------------------------------------------*/
if (ee_CheckOk() == 0)
{
/* 沒有檢測到EEPROM */
printf("沒有檢測到串行EEPROM!\r\n");
return 0;
}
/*------------------------------------------------------------------------------------*/
/* 填充測驗緩沖區 */
for (i = 0; i < EEPROM_SIZE; i++)
{
write_buf[i] = i;
}
/*------------------------------------------------------------------------------------*/
if (ee_WriteBytes(write_buf, 0, EEPROM_SIZE) == 0)
{
printf("寫eeprom出錯!\r\n");
return 0;
}
else
{
printf("寫eeprom成功!\r\n");
}
/*寫完之后需要適當的延時再去讀,不然會出錯*/
ee_Delay(0x0FFFFF);
/*-----------------------------------------------------------------------------------*/
if (ee_ReadBytes(read_buf, 0, EEPROM_SIZE) == 0)
{
printf("讀eeprom出錯!\r\n");
return 0;
}
else
{
printf("讀eeprom成功,資料如下:\r\n");
}
/*-----------------------------------------------------------------------------------*/
for (i = 0; i < EEPROM_SIZE; i++)
{
if(read_buf[i] != write_buf[i])
{
printf("0x%02X ", read_buf[i]);
printf("錯誤:EEPROM讀出與寫入的資料不一致");
return 0;
}
printf(" %02X", read_buf[i]);
if ((i & 15) == 15)
{
printf("\r\n");
}
}
printf("eeprom讀寫測驗成功\r\n");
return 1;
}
/*********************************************END OF FILE**********************/
main.c
int main(void)
{
ee_Test();
return 0;
}
? 由 青梅煮久 寫于 2021 年 02 月 04 日
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/256875.html
標籤:其他
上一篇:8張撲克牌問題
