AT24Cxx移植第三方庫到裸機中使用

簡介

MCU : STM32F103C8T6
庫: HAL庫裸機開發
EEPROM : AT24C02, 256Byte容量,I2C接口

電路圖

AT24C02 電路圖

電路圖引用
在這里插入圖片描述

裸機直接讀寫

// 寫入數據到 EEPROM
HAL_StatusTypeDef EEPROM_WriteByte(uint16_t MemAddress, uint8_t Data)
{// 發送數據uint8_t dataToSend[2] = { (uint8_t)(MemAddress & 0xFF), Data };return HAL_I2C_Master_Transmit(&hi2c1, (EEPROM_I2C_ADDRESS << 1), dataToSend, 2, 100);
}// 讀取數據從 EEPROM
HAL_StatusTypeDef EEPROM_ReadByte(uint16_t MemAddress, uint8_t *Data)
{// 發送存儲地址uint8_t addressToSend = (uint8_t)(MemAddress & 0xFF);if (HAL_I2C_Master_Transmit(&hi2c1, (EEPROM_I2C_ADDRESS << 1), &addressToSend, 1, 100) != HAL_OK){return HAL_ERROR;}// 讀取數據return HAL_I2C_Master_Receive(&hi2c1, (EEPROM_I2C_ADDRESS << 1), Data, 1, 100);
}// 調用
uint8_t dat = 100;EEPROM_WriteByte(0, dat);
HAL_Delay(10);
EEPROM_ReadByte(0&dat);

移植第三方AT24Cxx庫

引用庫

AT24CXX庫源碼
AT24CXX系列讀寫算法

修改庫

只需要 _24cxx_dev.c 和 _24cxx_dev.h即可

  1. 將代碼中的地址修改如下
    slave_addr = pdev->slave_addr | (addr>>8);
    改為
    slave_addr = pdev->slave_addr << 1;

  2. 增加寫pageBuffer

/*24cxx eeprom devcie struct*/
typedef struct 
{int (*i2c_send_thend_recv)(uint8_t slave_addr, const void *send_buff, 	/* i2c bus fun */uint32_t send_size, void *recv_buff, uint32_t recv_size);int (*i2c_send_thend_send)(uint8_t slave_addr, const void *send_buff1,	/* i2c bus fun */uint32_t send_size1,const void *send_buff2, uint32_t send_size2);uint8_t	slave_addr;	/*eeprom i2c addr*///uint8_t	type;		/*eeprom type, 0:eeprom;1:fram*/_24_model_t	model;		/*eeprom model*/void(*wp)(uint8_t ctrl);		/*protect of write function*/void(*page_write_delay)(void);	/*there is a delay in continuous writin for EEPROM,FRAM not need*/uint8_t *pageBuffer;
}_24cxx_dev_t;/*extern function*/
extern void __24cxx_dev_init(_24cxx_dev_t *pdev) ;
  1. pageBuffer 初始化
void __24cxx_dev_init(_24cxx_dev_t *pdev)
{uint16_t ee_page_size = get_eeprom_pagesize(pdev->model);if (pdev->model > _24C16_E)pdev->pageBuffer = (uint8_t*)malloc(ee_page_size+2);elsepdev->pageBuffer = (uint8_t*)malloc(ee_page_size+1);
}
  1. 將寫的部分合并之后發送
    寫時序的問題,不合并無法正常寫
/*** @brief  write one page. * @param  pdev pointer to the eeprom device struct.* @param  addr the address of write to.* @param  pbuf the data to write.* @param  size number of bytes to write..* @retval return 0 if 0k,anything else is considered an error.*/
static int16_t _24cxx_write_page(_24cxx_dev_t *pdev, uint32_t addr, uint8_t *pbuf, uint32_t size)
{
//	uint8_t	buf[2];
//	uint8_t	buf_size = 0;uint8_t slave_addr = 0;uint16_t ee_page_size = 0;int16_t	ret = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}ee_page_size = get_eeprom_pagesize(pdev->model);	if (((addr % ee_page_size) + size) > ee_page_size) /*the over flow of page size*/{return _24CXX_ERR_PAGE_SIZE;}if (pdev->model > _24C16_E){/*24c32-24c1024*/slave_addr = pdev->slave_addr;
//		buf[0] = (addr >>8)& 0xff;
//		buf[1] = addr & 0xff;pdev->pageBuffer[0] = (addr >>8)& 0xff;pdev->pageBuffer[1] = addr & 0xff;memcpy(&pdev->pageBuffer[2], pbuf, size);size += 2;}else{/*24c01-24c16*/slave_addr = pdev->slave_addr << 1;
//		buf[0] = addr & 0xff;pdev->pageBuffer[0] = addr & 0xff;memcpy(&pdev->pageBuffer[1], pbuf, size);size += 1;}if (pdev->wp)		/*release write protect*/{pdev->wp(0);}//	ret = pdev->i2c_send_thend_send(slave_addr, buf, buf_size, pbuf, size);ret = pdev->i2c_send_thend_send(slave_addr, pdev->pageBuffer, size, 0, 0);if (pdev->wp){pdev->wp(1);	/*write protect*/}return ret;
}
  1. 新增
.h 中新增
extern uint16_t _24cxx_pages(_24cxx_dev_t *pdev); // 設備有多少頁
extern int16_t _24cxx_erase_page(_24cxx_dev_t *pdev, uint16_t pageNum, uint8_t val); // 按頁擦除, val是寫入值
extern int16_t _24cxx_erase(_24cxx_dev_t *pdev, uint8_t val); // 全部擦除int16_t _24cxx_erase(_24cxx_dev_t *pdev, uint8_t val)
{uint16_t pages = 0;int16_t ret = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}pages = _24cxx_pages(pdev);for (int i = 0; i < pages; ++i){ret = _24cxx_erase_page(pdev, i, val);if (_24CXX_OK != ret)break ;if (pdev->page_write_delay){pdev->page_write_delay();		/*eeprom need wait*/}}return ret;
}
int16_t _24cxx_erase_page(_24cxx_dev_t *pdev, uint16_t pageNum, uint8_t val)
{uint16_t pages = 0;uint16_t page_size = 0;int16_t ret = 0;uint16_t slave_addr = 0;uint32_t addr = 0;uint32_t size = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}pages = _24cxx_pages(pdev);page_size = get_eeprom_pagesize(pdev->model);addr = pageNum * page_size;size = page_size;if (pages <= pageNum){return _24CXX_ERR_CHIP_SIZE;}if (pdev->model > _24C16_E){/*24c32-24c1024*/slave_addr = pdev->slave_addr;size += 2;memset(pdev->pageBuffer, val, size);pdev->pageBuffer[0] = (addr >>8)& 0xff;pdev->pageBuffer[1] = addr & 0xff;}else{/*24c01-24c16*/slave_addr = pdev->slave_addr << 1;size += 1;memset(pdev->pageBuffer, val, size);pdev->pageBuffer[0] = addr & 0xff;}ret = pdev->i2c_send_thend_send(slave_addr, pdev->pageBuffer, size, 0, 0);return ret;
}
  1. 代碼使用
int hw_i2c_send_then_recv(uint8_t slave_addr, const void *send_buff, uint32_t send_size, void *recv_buff, uint32_t recv_size)
{// 發送數據if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff, send_size, 10)){return _24CXX_ERR_I2C_WR;	}if (HAL_OK != HAL_I2C_Master_Receive(&hi2c1, slave_addr, (uint8_t*)recv_buff, recv_size, 1000)){return _24CXX_ERR_I2C_WR;	}return _24CXX_OK;
}int hw_i2c_send_then_send(uint8_t slave_addr, const void *send_buff1, uint32_t send_size1,const void *send_buff2, uint32_t send_size2)
{if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff1, send_size1, 2000)){return _24CXX_ERR_I2C_WR;	}if (0 != send_size2){if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff2, send_size2, 1000)){return _24CXX_ERR_I2C_WR;	}}return _24CXX_OK;
}static void page_write_delay(void) 
{uint16_t i;i = 0xFFFF;while(i--);
}_24cxx_dev_t at24cxx_dev =
{.i2c_send_thend_recv=hw_i2c_send_then_recv,.i2c_send_thend_send=hw_i2c_send_then_send,.slave_addr=0x51,						/* eeprom address */.model=_24C02_E,					.wp=0,					/* no write protect */.page_write_delay=page_write_delay,
};uint8_t buffer[256];
uint16_t size = 0;
uint8_t readBuffer[256];
uint16_t readSize = 256;
void readWriteBufferInit()
{int writeSize = 256;for (int i = 0; i < writeSize; ++i){buffer[i] = 255-i;}size = readSize = writeSize;memset(readBuffer, 0, sizeof(readBuffer));
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */static int ret = _24CXX_OK;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C1_Init();__24cxx_dev_init(&at24cxx_dev);/* USER CODE BEGIN 2 */readWriteBufferInit();ret = _24cxx_write(&at24cxx_dev, 0, (uint8_t*)buffer, size); if (ret != _24CXX_OK){}else{}HAL_Delay(100);ret = _24cxx_read(&at24cxx_dev, 0, (uint8_t*)readBuffer, readSize); if (ret != _24CXX_OK){}else{}
//for (int i = 0; i < size; ++i)
//{
//		ret = EEPROM_WriteByte(i, buffer[i]);
//	HAL_Delay(5);
//}
//	HAL_Delay(50);
//for (int i = 0; i < size; ++i)
//{
//		ret = EEPROM_ReadByte(i, &readBuffer[i]);
//	HAL_Delay(5);
//}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

注意

1. HAL函數

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) 
及
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
中的Timeout需要根據你的Tick時間來設置, 系統默認是1ms, 但是你如果修改了就需要重新設置;

2. 關于讀寫的Timeout

  1. 按照數據手冊, 寫是按字節寫/按頁寫, 所以超時時間按照頁進行設置, 5+(寫周期時間)~10ms;
  2. 讀是可以連續讀的,所以需要按照需求進行設置,如果一次性讀取太多設置的Timeout少的話,導致接收超時, 會失敗, 這里需要注意;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73895.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73895.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73895.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

算法刷題記錄——LeetCode篇(1.3) [第21~30題](持續更新)

更新時間&#xff1a;2025-03-29 LeetCode題解專欄&#xff1a;實戰算法解題 (專欄)技術博客總目錄&#xff1a;計算機技術系列目錄頁 優先整理熱門100及面試150&#xff0c;不定期持續更新&#xff0c;歡迎關注&#xff01; 21. 合并兩個有序鏈表 將兩個升序鏈表合并為一個…

常用數據庫

模式的定義于刪除 1.定義模式 CREATE SCHEMA [ <模式名> ] AUTHORIZATION < 用戶名 >;要創建模式&#xff0c;調用該命令的用戶必須擁有數據庫管理員權限&#xff0c;或者獲得了DBA授權 eg:為用戶WANG定義一個模式S-C-SC CREATE SCHEMA "S-C-SC" AUT…

Processor System Reset IP 核 v5.0(vivado)

這個IP的作用&#xff0c;我的理解是&#xff0c;比普通按鍵復位更加高效靈活&#xff0c;可以配置多個復位輸出&#xff0c;可以配置復位周期。 1、輸入信號&#xff1a; 重要的信號有時鐘clk信號&#xff0c;一般連接到系統時鐘&#xff1b;輸入復位信號&#xff0c;一般是外…

3月29日星期六今日早報簡報微語報早讀

3月29日星期六&#xff0c;農歷三月初一&#xff0c;早報#微語早讀。 1、全國公立醫療機構自3月31日起全面停止收取門診預交金&#xff1b; 2、永輝超市“胖東來調改店”已達47家店 一線員工薪酬漲幅50%以上&#xff1b; 3、兩孩家庭補10萬&#xff0c;三孩家庭補20萬&#…

pyinstaller 對 pyexecjs模塊打包老會有終端框閃爍

解決辦法&#xff1a; 修改 execjs 源代碼 具體步驟 1. 在 execjs 源文件中&#xff0c;找到 _external_runtime.py 文件中的以下代碼 p Popen(cmd, startupinfostartupinfo, stdinPIPE, stdoutPIPE, stderrPIPE, cwdself._cwd,universal_newlinesTrue)2. 修改為&#xff…

代碼隨想錄day2 數組總結

1.二分查找 2.快慢 雙指針 代碼隨想錄day1-CSDN博客 3.滑動窗口 滑動窗口就是有一個起始位置&#xff0c;一個終止位置&#xff0c;通過調節起始位置和終止位置得到我們想要的結果。 外面一層for循環 用來更新終止位置 不滿足條件 終止位置右移 里面一層while循環 …

MAC安裝docker 后提示com.docker.vmnetd”將對您的電腦造成傷害

出現“com.docker.vmnetd”將對您的電腦造成傷害的提示&#xff0c;通常是由于文件簽名問題導致 macOS 的安全系統誤判 Docker 為惡意軟件。以下是解決方法&#xff1a; 停止相關服務并刪除文件 運行以下命令停止相關服務并刪除有問題的文件 停止 Docker 服務 sudo pkill ‘…

Redis-常用命令

目錄 1、Redis數據結構 2、命令簡介 2.1、通用命令 DEL EXISTS EXPIRE 2.2、String命令 SET和GET MSET和MGET INCR和INCRBY和DECY SETNX SETEX 2.3、Key的層級結構 2.4、Hash命令 HSET和HGET HMSET和HMGET HGETALL HKEYS和HVALS HINCRBY HSETNX 2.5、List命…

每日一題之既約分數

題目描述 本題為填空題&#xff0c;只需要算出結果后&#xff0c;在代碼中使用輸出語句將所填結果輸出即可。 如果一個分數的分子和分母的最大公約數是 1&#xff0c;這個分數稱為既約分數。 例如 3/4,1/8,7/1?&#xff0c; 都是既約分數。 請問&#xff0c;有多少個既約分…

Java 圖片壓縮:高效壓縮方案解析

目錄 一、基于OpenCV的智能尺寸壓縮(一)代碼示例(二)技術亮點(三)適用場景二、WebP高效格式轉換(一)代碼示例(二)核心優勢(三)性能對比三、基于Thumbnailator的簡單壓縮(一)代碼示例(二)技術亮點(三)適用場景四、方案選型建議一、基于OpenCV的智能尺寸壓縮 …

鴻蒙Next-集成HmRouter的路由模式

第一步&#xff1a;全局安裝hmrouter依賴 ohpm install hadss/hmrouter第二步&#xff1a;修改全局的hvigor-config.json5(加入hm-router插件) hvigor/hvigor-config.json5 {"modelVersion": "5.0.1","dependencies": {"hadss/hmrouter-…

uni-app:指引蒙層

組件說明 指引蒙層組件: 通過id標簽,突出對應id中的模塊; 可以自定義提示詞。 點擊任意位置關閉蒙層 效果展示和使用示例 切換id之后的效果: 代碼實現 <template><view class="guide-mask" v-if="showMask" @click="hideMask"&g…

基于Java與Go的下一代DDoS防御體系構建實戰

引言:混合云時代的攻防對抗新格局 2024年某金融平臺遭遇峰值2.3Tbps的IPv6混合攻擊,傳統WAF方案在新型AI驅動攻擊面前全面失效。本文將以Java與Go為技術棧,揭示如何構建具備智能決策能力的防御系統。 一、攻擊防御技術矩陣重構 1.1 混合攻擊特征識別 攻擊類型Java檢測方案…

大數據Spark(五十五):Spark框架及特點

文章目錄 Spark框架及特點 一、Spark框架介紹 二、Spark計算框架具備以下特點 Spark框架及特點 一、Spark框架介紹 Apache Spark 是一個專為大規模數據處理而設計的快速、通用的計算引擎。最初由加州大學伯克利分校的 AMP 實驗室&#xff08;Algorithms, Machines, and Pe…

ubuntu 升級補丁,備份備份備份

一、常規軟件包更新&#xff08;安全補丁和軟件升級&#xff09; 更新軟件包列表 從軟件源服務器獲取最新的軟件包信息&#xff1a; sudo apt update升級已安裝的軟件包 安裝所有可用的更新&#xff08;安全補丁、功能更新&#xff09;&#xff1a; sudo apt upgrade處理依賴…

CubeMx——串口與 printf 打印

CubeMx 配置 fputc 實現 /* USER CODE BEGIN 0 */ #include <stdio.h> /* USER CODE END 0 *//* USER CODE BEGIN 1 */ int fputc(int ch, FILE *f) {/* Place your implementation of fputc here *//* e.g. write a character to the USART */uint8_t send_data ch;HA…

多線程 -- Thread類

Thread 的常見構造方法 最后一個構造方法中的 ThreadGroup 線程組是 Java 中的概念&#xff0c;和系統內核中的線程組不是一個東西。我們自己創建的線程&#xff0c;默認是按照 Thread- 0 1 2 3 4...命名。但我們也可以給不同的線程&#xff0c;起不同的名字&#xff08;不同的…

Java基礎關鍵_032_反射(二)

目 錄 一、反射 Class 的 Method 1.反編譯 String 類的方法簽名 2.通過反射調用方法 3.反編譯 String 類的構造方法簽名 4.通過反射調用構造方法 二、類加載過程 1.裝載&#xff08;Loading&#xff09; &#xff08;1&#xff09;說明 &#xff08;2&#xff09;雙親委…

《數據結構:單鏈表》

“希望就像星星&#xff0c;或許光芒微弱&#xff0c;但永不熄滅。” 博主的個人gitee&#xff1a;https://gitee.com/friend-a188881041351 一.概念與結構 鏈表是一種物理存儲上非連續、非順序的存儲結構&#xff0c;數據元素的順序邏輯是通過鏈表中的指針鏈接次序實現的。 單…

藍橋杯 - 中等 - 絕美宋詞

介紹 “今宵酒醒何處&#xff0c;楊柳岸曉風殘月”&#xff0c;“驀然回首&#xff0c;那人卻在燈火闌珊處”&#xff0c;“試問閑愁都幾許&#xff1f;一川煙草&#xff0c;滿城風絮&#xff0c;梅子黃時雨” ...... 宋詞可謂是古代文學桂冠上一顆璀璨的明珠&#xff0c;本題…