上文:STM32:硬體IIC,實作EEPROM頁寫入和連續記憶體資料讀取,但是出現資料出錯(上)
https://blog.csdn.net/qq_45689790/article/details/113729858#comments_15148487
按照手冊內容實作連續資料的寫入(但是不能跨頁)和單個資料的寫入后,下面介紹硬體IIC跨頁寫入任意長度的資料,
基本思想:若一頁有8個資料
- 確定要寫入的地址WriteAddr ,OnePage = 8 - WriteAddr%8 得到的就是第一頁需要寫入的資料個數
- NumByteToWrite是一共要寫入的資料個數,End_page =(NumByteToWrite-OnePage)% 8 得到的是最后一頁需要寫入的資料個數,
- 確定OnePage 、End_page 后,(NumByteToWrite - OnePage - End_page )/ 8得到的就是中間需要連續寫入的資料頁數,
舉個例子
- WriteAddr = 17,OnePage = 8 - WriteAddr%8 = 7
- NumByteToWrite = 2,那么 End_page =(NumByteToWrite-OnePage)% 8 = 7
- 確定OnePage 、End_page后(NumByteToWrite - OnePage - End_page )% 8 = 1中間需要連續寫入1頁資料
圖示

連續寫入資料,大致分為三步,下面是參考代碼
void I2C_EE_WaitEepromStandbyState(void); //是等待回應的函式,不再展開
/**
* @brief 將緩沖區中的資料寫到 I2C EEPROM 中
* @param
* @arg pBuffer:緩沖區指標
* @arg WriteAddr:寫地址
* @arg NumByteToWrite:寫的位元組數
* @retval 無
*/
#define I2C_PageSize 8
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr,
u16 NumByteToWrite)
{
u8 NumOfPage=0,NumOfSingle=0,Addr =0,count=0,temp =0;
/*mod 運算求余,若 writeAddr 是 I2C_PageSize 整數倍,
運算結果 Addr 值為 0*/
Addr = WriteAddr % I2C_PageSize;
/*差 count 個資料值,剛好可以對齊到頁地址*/
count = I2C_PageSize - Addr;
/*計算出要寫多少整數頁*/
NumOfPage = NumByteToWrite / I2C_PageSize;
/*mod 運算求余,計算出剩余不滿一頁的位元組數*/
NumOfSingle = NumByteToWrite % I2C_PageSize;
// Addr=0,則 WriteAddr 剛好按頁對齊 aligned
// 這樣就很簡單了,直接寫就可以,寫完整頁后
// 把剩下的不滿一頁的寫完即可
if (Addr == 0) {
/* 如果 NumByteToWrite < I2C_PageSize */
if (NumOfPage == 0) {
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
/* 如果 NumByteToWrite > I2C_PageSize */
else {
/*先把整數頁都寫了*/
while (NumOfPage--) {
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
I2C_EE_WaitEepromStandbyState();
WriteAddr += I2C_PageSize;
pBuffer += I2C_PageSize;
}
/*若有多余的不滿一頁的資料,把它寫完*/
if (NumOfSingle!=0) {
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
}
}
// 如果 WriteAddr 不是按 I2C_PageSize 對齊
// 那就算出對齊到頁地址還需要多少個資料,然后
// 先把這幾個資料寫完,剩下開始的地址就已經對齊
// 到頁地址了,代碼重復上面的即可
else {
/* 如果 NumByteToWrite < I2C_PageSize */
if (NumOfPage== 0) {
/*若 NumOfSingle>count,當前面寫不完,要寫到下一頁*/
if (NumOfSingle > count) {
// temp 的資料要寫到寫一頁
temp = NumOfSingle - count;
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
I2C_EE_WaitEepromStandbyState();
WriteAddr += count;
pBuffer += count;
I2C_EE_PageWrite(pBuffer, WriteAddr, temp);
I2C_EE_WaitEepromStandbyState();
}
else { /*若 count 比 NumOfSingle 大*/
I2C_EE_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
I2C_EE_WaitEepromStandbyState();
}
}
/* 如果 NumByteToWrite > I2C_PageSize */
else {
/*地址不對齊多出的 count 分開處理,不加入這個運算*/
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / I2C_PageSize;
NumOfSingle = NumByteToWrite % I2C_PageSize;
/*先把 WriteAddr 所在頁的剩余位元組寫了*/
if (count != 0) {
I2C_EE_PageWrite(pBuffer, WriteAddr, count);
I2C_EE_WaitEepromStandbyState();
/*WriteAddr 加上 count 后,地址就對齊到頁了*/
WriteAddr += count;
pBuffer += count;
}
/*把整數頁都寫了*/
while (NumOfPage--) {
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
I2C_EE_WaitEepromStandbyState();
WriteAddr += I2C_PageSize;
pBuffer += I2C_PageSize;
}
/*若有多余的不滿一頁的資料,把它寫完*/
if (NumOfSingle != 0) {
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
I2C_EE_WaitEepromStandbyState();
}
}
}
}
參考書籍:《野火STM32庫函式開發指南》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/263901.html
標籤:其他
