使用CUBE_MX使用I2C通信,实现对EEPROM的读写

devtools/2024/9/24 15:28:58/

一、使用CUBE_MX配置

1.配置I2C

2.配置USART1

3.重中之重(在KEIL5打开串口使用的库)

二、KEIL5配置

#include "main.h"
#include "i2c.h"
#include "gpio.h"
#include "usart.h"#include <stdio.h>void SystemClock_Config(void);
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite);
uint32_t I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint8_t NumByteToWrite);#define  DATA_Size			256
#define  EEP_Firstpage      0x00
#define  EEPROM_ADDRESS     0xA0
//一个I2C从设备有两个地址,一个是写操作地址,另一个是读操作地址。例如,开发板上的EEPROM芯片24C02的写操作地址是0xA0,读操作地址是0xA1,也就是在写操作地址上加1。//在I2C的HAL库驱动中,传递从设备地址参数时,只需要设置写操作地址,函数内部会根据读写操作类型,自动使用写操作地址或读操作地址。但是在软件模拟I2C接口通信时,必须明确使用相应的地址。#define I2Cx_TIMEOUT_MAX                300
/* Maximum number of trials for HAL_I2C_IsDeviceReady() function */
#define EEPROM_MAX_TRIALS               300uint8_t I2C_pData[DATA_Size];
uint8_t I2c_Buf_Write[DATA_Size];
uint8_t I2c_Buf_Read[DATA_Size];int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_I2C1_Init();MX_USART1_UART_Init();for (int i=0; i<DATA_Size; i++ ) //填充要发送的数据{   I2C_pData[i] =i;}//作为主设备向某个地址的从设备发送一定长度的数据HAL_StatusTypeDef status = HAL_OK;printf("通过I2C,由I2C_pData向EEPROM发送数据\r\n");
/*status=HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS , EEP_Firstpage , I2C_MEMADD_SIZE_8BIT, (uint8_t*)(I2C_pData), DATA_Size, 100);	if(status == HAL_OK ){printf("通过I2C,由I2C_pData向EEPROM发送数据\r\n");status = HAL_OK;}
*/	//由于EEPROM每页只有八个字节,写入不定长的数据需要调用这个函数I2C_EE_BufferWrite( (uint8_t*)I2C_pData,EEP_Firstpage,DATA_Size);//读取写入EEPROM的数据//向某个从设备的指定存储地址开始读取一定长度的数据//将EEPROM读出数据顺序保持到I2c_Buf_Read中status= HAL_I2C_Mem_Read(&hi2c1,EEPROM_ADDRESS,EEP_Firstpage,I2C_MEMADD_SIZE_8BIT,I2c_Buf_Read,DATA_Size,1000);if(status == HAL_OK ){printf("通过I2C,读取EEPROM中的数据,并且保存到I2c_Buf_Read\r\n");status = HAL_OK;}for (int i=0; i<DATA_Size; i++ ) {   printf("数据是 0x%02X  \r\n",I2c_Buf_Read[i]);} while (1){}}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* AT24C01/02每页有8个字节 */
//#define EEPROM_PAGESIZE    8
#define EEPROM_PAGESIZE 	   8/*** @brief   将缓冲区中的数据写到I2C EEPROM中* @param   *		@arg pBuffer:缓冲区指针*		@arg WriteAddr:写地址*     @arg NumByteToWrite:写的字节数* @retval  无*/
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;Addr = WriteAddr % EEPROM_PAGESIZE;count = EEPROM_PAGESIZE - Addr;NumOfPage =  NumByteToWrite / EEPROM_PAGESIZE;NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;/* If WriteAddr is I2C_PageSize aligned  */if(Addr == 0) {/* If NumByteToWrite < I2C_PageSize */if(NumOfPage == 0) {I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);}/* If NumByteToWrite > I2C_PageSize */else  {while(NumOfPage--){I2C_EE_PageWrite(pBuffer, WriteAddr, EEPROM_PAGESIZE); WriteAddr +=  EEPROM_PAGESIZE;pBuffer += EEPROM_PAGESIZE;}if(NumOfSingle!=0){I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}}/* If WriteAddr is not I2C_PageSize aligned  */else {/* If NumByteToWrite < I2C_PageSize */if(NumOfPage== 0) {I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);}/* If NumByteToWrite > I2C_PageSize */else{NumByteToWrite -= count;NumOfPage =  NumByteToWrite / EEPROM_PAGESIZE;NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;	if(count != 0){  I2C_EE_PageWrite(pBuffer, WriteAddr, count);WriteAddr += count;pBuffer += count;} while(NumOfPage--){I2C_EE_PageWrite(pBuffer, WriteAddr, EEPROM_PAGESIZE);WriteAddr +=  EEPROM_PAGESIZE;pBuffer += EEPROM_PAGESIZE;  }if(NumOfSingle != 0){I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); }}}  
}/*** @brief   在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数*          不能超过EEPROM页的大小,AT24C02每页有8个字节* @param   *		@arg pBuffer:缓冲区指针*		@arg WriteAddr:写地址*     @arg NumByteToWrite:写的字节数* @retval  无*/
uint32_t I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint8_t NumByteToWrite)
{HAL_StatusTypeDef status = HAL_OK;/* Write EEPROM_PAGESIZE */status=HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS,WriteAddr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(pBuffer),NumByteToWrite, 100);while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){}/* Check if the EEPROM is ready for a new operation */while (HAL_I2C_IsDeviceReady(&hi2c1, EEPROM_ADDRESS, EEPROM_MAX_TRIALS, I2Cx_TIMEOUT_MAX) == HAL_TIMEOUT);/* Wait for the end of the transfer */while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){}return status;
}//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{/* 发送一个字节数据到串口DEBUG_USART */HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	return (ch);
}///重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{int ch;HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	return (ch);
}/* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


http://www.ppmy.cn/devtools/116561.html

相关文章

html实现好看的多种风格手风琴折叠菜单效果合集(附源码)

文章目录 1.设计来源1.1 风格1 -图文结合手风琴1.2 风格2 - 纯图片手风琴1.3 风格3 - 导航手风琴1.4 风格4 - 双图手风琴1.5 风格5 - 综合手风琴1.6 风格6 - 简描手风琴1.7 风格7 - 功能手风琴1.8 风格8 - 全屏手风琴1.9 风格9 - 全屏灵活手风琴 2.效果和源码2.1 动态效果2.2 源…

Elasticsearch在大数据处理中的优势

Elasticsearch 在大数据处理中的优势主要体现在以下几个方面&#xff1a; 1. 分布式架构 水平扩展&#xff1a;Elasticsearch 设计为分布式系统&#xff0c;可以轻松地通过增加节点来水平扩展&#xff0c;处理 PB 级别的数据。数据分片和复制&#xff1a;数据自动分片并跨多个…

我们一般使用的家庭宽带支持udp吗

大多数家庭宽带服务通常支持UDP协议&#xff0c;因为UDP是互联网协议套件中的一个重要部分&#xff0c;广泛应用于视频会议、在线游戏、实时语音通话等实时应用中。以下是一些常见情况&#xff1a; 1. 家庭宽带服务 大部分ISP&#xff08;互联网服务提供商&#xff09;&#…

【大语言模型_1】VLLM部署Qwen模型

1、模型下载&#xff1a; 魔塔社区&#xff1a;魔搭社区 huggingface&#xff1a;https://huggingface.co/Qwen 2、安装python环境 1、python官网安装python 【推荐要3.8以上版本】 2、安装vllm模块 3、启动模型 CUDA_VISIBLE_DEVICES0,1 /root/vendor/Python3.10.12/bin/pytho…

基于BERT的文本分类模型,结合了TextCNN网络结构

一个基于BERT的文本分类模型,并结合了TextCNN网络结构来进一步增强特征提取能力。代码的主要组件包括BERT模型的加载、卷积神经网络(CNN)部分的定义、特征融合以及最终的分类层。以下是代码的详细解析: 1. 导入必要的库和函数 from bert4keras.backend import keras, set…

加固与脱壳01 - 环境搭建

虚拟机 VMWare 多平台可用&#xff0c;而且可以直接激活&#xff0c;需要先注册一个账号 https://support.broadcom.com/group/ecx/productdownloads?subfamilyVMwareWorkstationPro KALI 类Ubuntu系统&#xff0c;官方提供了 vmware 版本&#xff0c;直接下载就可以使用。…

【代码随想录训练营第42期 Day59打卡 - 图论Part9 - Bellman-Ford算法

目录 一、Bellman-Ford算法 定义 特性 伪代码实现 二、经典题目 题目&#xff1a;卡码网 94. 城市间货物运输 I 题目链接 题解&#xff1a; Bellman-Ford算法 三、小结 一、Bellman-Ford算法 定义 Bellman-Ford算法是一个迭代算法&#xff0c;它可以处理包含负权边的…

前端常用的设计模式

一、工厂模式 工厂模式&#xff08;Factory Pattern&#xff09;是 程序中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。通过…