当前位置: 首页 > news >正文

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

一、使用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 */

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • AI与自然语言处理(NLP):中秋诗词生成
  • OpenAI o1模型推理能力大幅提升的背后:重复采样如何提升AI推理能力
  • Clickhouse使用笔记
  • 了解 React 应用程序中的渲染和重新渲染:它们如何工作以及如何优化它们
  • 『功能项目』战士职业平A怪物掉血【44】
  • 动态规划---不同的子序列
  • 一次RPC调用过程是怎么样的?
  • NLP与文本生成:使用GPT模型构建自动写作系统
  • 软件无线电2:矢量信号器和HackRF实现FM调制解调
  • 32.递归、搜索、回溯之floodfill算法
  • com.microsoft.sqlserver:sqljdbc4:jar:4.0 was not found产生原因及解决步骤
  • Zabbix的安装与基本使用(主机群组、应用集、监控项、触发器、动作、媒介)
  • C++设计模式(更新中)
  • Linux 常用指令
  • 苹果Vision Pro曝出严重漏洞,黑客可通过用户眼动输入窃取信息
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Brief introduction of how to 'Call, Apply and Bind'
  • django开发-定时任务的使用
  • JS笔记四:作用域、变量(函数)提升
  • MobX
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Python_OOP
  • React-flux杂记
  • Service Worker
  • 彻底搞懂浏览器Event-loop
  • 程序员最讨厌的9句话,你可有补充?
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用common-codec进行md5加密
  • 使用docker-compose进行多节点部署
  • 【干货分享】dos命令大全
  • kubernetes资源对象--ingress
  • postgresql行列转换函数
  • 阿里云ACE认证之理解CDN技术
  • 数据可视化之下发图实践
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • ###C语言程序设计-----C语言学习(6)#
  • ###STL(标准模板库)
  • #pragma预处理命令
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (10)STL算法之搜索(二) 二分查找
  • (160)时序收敛--->(10)时序收敛十
  • (52)只出现一次的数字III
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Matlab)使用竞争神经网络实现数据聚类
  • (不用互三)AI绘画:科技赋能艺术的崭新时代
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (一)Mocha源码阅读: 项目结构及命令行启动