目录

1、I2C总线

2、I2C驱动编写

3、24C02

4、EEPROM读写函数编写

5、验证


1、I2C总线

I2C总线有两根线:时钟线SCL、数据线SDA,当总线空闲时,两根线都处于高电平。

I2C的数据传输规范:

①当SCL为高电平的时候,SDA必须保持稳定;只有SCL为低电平时SDA才可以发生变化。

②在数据传输的开始和结束需要定义开始信号和停止信号:

开始信号:SCL为高时,SDA高->低。

停止信号:SCL为高时,SDA低->高。

④I2C数据先传高位,在开始信号和结束信号之间有多少字节数据不限定,但每字节必须是8位,每一字节后面都有一个“应答/非应答位”(由接受方提供)。

在第9个时钟周期,接收方将SDA线拉低,产生“应答”

在第9个时钟周期,接收方将SDA线拉高,产生“非应答”

2、I2C驱动编写

在STM32CubeMX配置I2C引脚:

i2c.h:

#ifndef _I2C_H
#define _I2C_H#include "main.h"//IO 操作函数
#define IIC_SDA_GPIO_MODE_Pos    GPIO_CRL_MODE7_Pos                           #define I2C_SDA_IN {IIC_SDA_GPIO_Port->CRL&=0X0FFFFFFF;GPIOB->CRL|=(uint32_t)8<<IIC_SDA_GPIO_MODE_Pos;}
#define I2C_SDA_OUT {IIC_SDA_GPIO_Port->CRL&=0X0FFFFFFF;GPIOB->CRL|=(uint32_t)3<<IIC_SDA_GPIO_MODE_Pos;}#define I2C_SCL_LOW      HAL_GPIO_WritePin(IIC_SCL_GPIO_Port,IIC_SCL_Pin,GPIO_PIN_RESET)
#define I2C_SCL_HIGH     HAL_GPIO_WritePin(IIC_SCL_GPIO_Port,IIC_SCL_Pin,GPIO_PIN_SET)
#define I2C_SDA_LOW      HAL_GPIO_WritePin(IIC_SDA_GPIO_Port,IIC_SDA_Pin,GPIO_PIN_RESET)
#define I2C_SDA_HIGH     HAL_GPIO_WritePin(IIC_SDA_GPIO_Port,IIC_SDA_Pin,GPIO_PIN_SET)#define I2C_SDA_READ     HAL_GPIO_ReadPin(IIC_SDA_GPIO_Port,IIC_SDA_Pin)#define I2C_ACK          0//应答
#define I2C_NOACK        1//非应答void I2C_Start(void);
void I2C_Stop(void);
void I2C_PutAck(uint8_t Ack);
uint8_t I2C_GetAck(void);uint8_t I2C_WriteByte(uint8_t Data);
uint8_t I2C_ReadByte(uint8_t ack);#endif 

i2c.c:

#include "i2c.h"static void I2C_Delay(void)
{uint8_t i=10; while(i){i--;}
}/*开始信号,SCL高时,SDA高->低*/
void I2C_Start(void)
{I2C_SCL_HIGH;//SCL高I2C_Delay();I2C_SDA_HIGH;//SDA高I2C_Delay();I2C_SDA_LOW;//SDA低  I2C_Delay();I2C_SCL_LOW;//SCL低I2C_Delay();
}/*停止信号,SCL高时,SDA低->高*/
void I2C_Stop(void)
{I2C_SDA_LOW;//SDA低I2C_Delay();I2C_SCL_HIGH;//SCL高I2C_Delay();I2C_SDA_HIGH;//SDA高I2C_Delay();
}/*第9个时钟周期时输出应答/非应答信号,SCL高时,接收方将SDA拉低/高*/
void I2C_PutAck(uint8_t Ack)
{I2C_SCL_LOW;//SCL低I2C_Delay();if(I2C_ACK == Ack)I2C_SDA_LOW;//应答elseI2C_SDA_HIGH;//非应答I2C_Delay();I2C_SCL_HIGH;//SCL高,第9个时钟周期I2C_Delay();I2C_SCL_LOW;//SCL低I2C_Delay();
}/*第9个时钟周期时获得应答/非应答信号*/
uint8_t I2C_GetAck(void)
{uint8_t ack;I2C_SCL_LOW;//SCL低I2C_Delay();I2C_SDA_IN;//SDA配置为输入模式I2C_SCL_HIGH;//SCL高,第9个时钟周期I2C_Delay();if(I2C_SDA_READ)ack = I2C_NOACK;//非应答elseack = I2C_ACK;//应答I2C_SCL_LOW;  //SCL低I2C_Delay();I2C_SDA_OUT;//SDA配置为输出模式return ack;//返回应答位
}/*I2C写1字节,SCL低->SDA写1位->SCL高(循环8次),然后获得应答位*/
uint8_t I2C_WriteByte(uint8_t Data)
{uint8_t cnt;for(cnt=0; cnt<8; cnt++){I2C_SCL_LOW;//SCL低I2C_Delay();if(Data & 0x80)I2C_SDA_HIGH;//SDA高elseI2C_SDA_LOW;//SDA低Data <<= 1;I2C_Delay();I2C_SCL_HIGH;//SCL高I2C_Delay();}I2C_SCL_LOW;//SCL低I2C_Delay();return I2C_GetAck();//获得应答位
}/*I2C读一字节,SCL高->SDA读1位->SCL低(循环8次),然后发送应答位*/
uint8_t I2C_ReadByte(uint8_t ack)
{uint8_t cnt;uint8_t data;I2C_SCL_LOW;//SCL低I2C_Delay();I2C_SDA_IN;//SDA配置为输入模式for(cnt=0; cnt<8; cnt++){I2C_SCL_HIGH;//SCL高I2C_Delay();data <<= 1;if(I2C_SDA_READ)data |= 0x01;//SDA为高I2C_SCL_LOW;//SCL低I2C_Delay();}I2C_SDA_OUT;//SDA配置为输出模式I2C_PutAck(ack); //产生应答(或者非应答)位return data;  //返回数据
}

3、24C02

①容量:2K bits = 2048 bits = 256 bytes。

②每页8 bytes,共32页。

③地址长度为8位。

④设备地址,开始信号之后,是8位的设备地址如下:

⑤向EEPROM写一字节步骤:

⑥从EEPROM读取一字节数据步骤:

4、EEPROM读写函数编写

eeprom.h

#ifndef _EEPROM_H
#define _EEPROM_H#include "main.h"#define EEPROM_DEV_ADDR           0xA0//地址1010000#define EEPROM_WR                 0x00//写(地址的最后1位)
#define EEPROM_RD                 0x01//读(地址的最后1位)uint8_t EEPROM_WriteByte(uint8_t Addr, uint8_t Data);
uint8_t EEPROM_ReadByte(uint8_t Addr, uint8_t *Data);#endif 

eeprom.c

#include "eeprom.h"
#include "i2c.h"/*EEPROM写1字节*/
uint8_t EEPROM_WriteByte(uint8_t Addr, uint8_t Data)
{uint8_t  ack;/*开始*/I2C_Start();/*设备地址/写*/ack = I2C_WriteByte(EEPROM_DEV_ADDR | EEPROM_WR);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*数据地址*/ack = I2C_WriteByte(Addr);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*写1字节数据*/ack = I2C_WriteByte(Data);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*停止*/I2C_Stop();return I2C_ACK;
}/*EEPROM读1字节*/
uint8_t EEPROM_ReadByte(uint8_t Addr, uint8_t *Data)
{uint8_t  ack;/*开始*/I2C_Start();/*设备地址/写*/ack = I2C_WriteByte(EEPROM_DEV_ADDR | EEPROM_WR);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*数据地址*/ack = I2C_WriteByte(Addr);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*重新开始*/I2C_Start();/*设备地址/读*/ack = I2C_WriteByte(EEPROM_DEV_ADDR | EEPROM_RD);if(I2C_NOACK == ack){I2C_Stop();return I2C_NOACK;}/*读一字节数据*/*Data = I2C_ReadByte(I2C_NOACK);   //读取1字节,产生非应答/*停止*/I2C_Stop();return I2C_ACK;
}

5、验证

在main.c文件添加 #include "eeprom.h" #include "i2c.h"

在main函数里加入下面代码:

  /* USER CODE BEGIN 2 */uint8_t  ACK;uint8_t  WRITE_DATA = 0;uint8_t  READ_DATA;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */WRITE_DATA++;ACK = EEPROM_WriteByte(0, WRITE_DATA);//0地址写1字节数据if(I2C_ACK == ACK){printf("Write Data=%d\r\n",WRITE_DATA);}else printf("Write Data Erro\r\n");Delay_Ms(100);ACK = EEPROM_ReadByte(0, &WRITE_DATA);//0地址读一字节数据if(I2C_ACK == ACK){printf("Read Data=%d\r\n",WRITE_DATA);}else printf("Write Data Erro\r\n");}/* USER CODE END 3 */

打印结果如下:

【STM32CubeMX学习】I2C读写24C02相关推荐

  1. STM32CubeMX(5)——IIC读写24c02

    0.序 我用的一个PCA9536老是出问题,怀疑是IIC应答或者停止位出问题了,所以特地来仔细看看IIC的原理和操作. (已经排除软件问题,是硬件电路问题) 本文使用软件模拟IIC,没有使用硬件自带I ...

  2. STM32CubeMX学习笔记(9)——I2C接口使用(读写EEPROM AT24C02)

    一.I2C简介 I2C(Inter-Integrated Circuit ,内部集成电路) 总线是一种由飞利浦 Philip 公司开发的串行总线.是两条串行的总线,它由一根数据线(SDA)和一根 时钟 ...

  3. STM32CubeMX学习笔记——STM32H743_硬件I2C

    STM32CubeMX学习笔记--STM32H743_硬件I2C Github STM32CubeMX配置 Pinout配置 GPIO Clock Configuration配置 代码部分 main. ...

  4. STM32CubeMX学习系列教程目录

    1. STM32CubeMX学习教程之一:GPIO输出之跑马灯 - SimonLiu的博客 - CSDN博客 2. STM32CubeMX学习教程之二:GPIO输入之外部中断 3. STM32Cube ...

  5. STM32F10x_硬件I2C读写EEPROM(标准外设库版本)

    Ⅰ.写在前面 上一篇文章是"STM32F10x_模拟I2C读写EEPROM",讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要 ...

  6. 解决一个I2C读写问题

    之前写关于I2C相关的文章 排查一个触摸屏驱动问题 MTK 平台TP调试遇坑 1.问题 今天遇到一个问题,我们有一个芯片,I2C读写失败,导致录音有问题,而且是偶现的. log提示看到是返回 -6 & ...

  7. STM32CubeMX学习笔记(25)——FatFs文件系统使用(操作SPI Flash)

    一.FatFs简介 FatFs 是面向小型嵌入式系统的一种通用的 FAT 文件系统.它完全是由 ANSI C 语言编写并且完全独立于底层的 I/O 介质.因此它可以很容易地不加修改地移植到其他的处理器 ...

  8. STM32CubeMX学习笔记(38)——FSMC接口使用(TFT-LCD屏显示)

    一.TFT-LCD简介 TFT-LCD(Thin Film Transistor-Liquid Crystal Display) 即薄膜晶体管液晶显示器.TFT-LCD 与无源 TN-LCD. STN ...

  9. STM32F030 IIC2通用读写24C02、24C16、24C32、24C64等例程

    前言: 咱们做嵌入式开发经常用到EEPROM,但是EEPROM的大小不同会需要不同代码来适配,这不利于快捷开发.在此本人分享自己优化总结后一段代码给大家,该代码通用读写24C02.24C16.24C3 ...

最新文章

  1. android 手机推荐,2018年安卓机皇推荐,这几款是真的不错
  2. c语言e怎么表示_C语言程序设计(山东联盟)
  3. 阿里专家张磊:云原生为什么对云计算生态充满吸引力?
  4. 配置Yarn-Resourcemanager HA
  5. 用cxf公布和调用web service
  6. WSARecv() 函数使用解析
  7. UC为什么一直开发html游戏,为什么很多人都喜欢用UC浏览器?老玩家告诉你原因...
  8. Oracle环境变量
  9. 微信支付id出现的重复支付解决方法和app应用中多种支付方式之间的对比
  10. python立体匹配误匹配率_立体匹配算法(Stereo Matching)及其在OpenCV中的应用
  11. java获取专辑封面_从MP3中读取专辑封面图片
  12. C# Asp.net 制作一个windows服务
  13. ANSI, unicode, UTF-8编码详解
  14. H5页面在自己APP中图标显示正常,接入钉钉请求.woff图标字体报错
  15. 以太网交换机如何工作以及MAC和PHY
  16. python环境下数据操作_数据分析环境搭建和Python基础知识
  17. 二层交换机,三层交换机及四层交换机的区别
  18. 计算机图形图像学 ar,一种实现增强现实的方法及其应用、计算设备与流程
  19. 自定义的毛玻璃效果,高斯模糊
  20. DPC(Defect Pixel Correction)——坏点检测

热门文章

  1. JDBC:PreparedStatement 插入BLOB类型的数据,PreparedStatement 批量处理,Connection 事务处理
  2. I2S和I2C分别如何连接pad
  3. android 开发环境ppt,Android开发环境简介.ppt
  4. 08.数据结构:第一个动态结构-链表
  5. Unity jobsystem 和 burst编译器代码演示及效率测试
  6. net core3.1 版本 解决错误 ConfigurationBuilder”未包含“SetBasePath”的定义
  7. position中absolute和fixed的区别
  8. ise 时钟约束_ISE 约束文件完整讲解
  9. 电脑如何创建html文件夹,如何在电脑上创建自己的隐私文件夹
  10. c语言书面作业,华软C语言书面作业14