前面一篇写了软件模拟IIC读写EEPROM。

本篇介绍硬件IIC读写EEPROM。平台是STM32F103+AT24C04N。SDA和SCL接5K上拉电阻到3.3v。

首先介绍AT24C04N的基本特性。512byte。支持1.8v~5.5v供电。支持5种读写模式。BYTE WRITE(字节写),PAGE WRITE(按页写)。RANDOM READ(随机读),SEQUENTIAL READ(顺序读)和CURRENT ADDRESS READ .具体时序参考数据手册。

我用的是I2C1接口。

宏定义如下:

#define EEPROM_Block_ADDRESS 0xA0   /* Device Address */#define I2C1_SLAVE_ADDRESS7        0xA0
#define I2C_PageSize              16
#define I2C_BUF_LEN               256#define EEPROM_I2C                          I2C1
#define EEPROM_I2C_CLK                      RCC_APB1Periph_I2C1
#define EEPROM_I2C_SCL_PIN                  GPIO_Pin_6                 /* PB.6 */
#define EEPROM_I2C_SCL_GPIO_PORT            GPIOB                       /* GPIOB */
#define EEPROM_I2C_SCL_GPIO_CLK             RCC_APB2Periph_GPIOB
#define EEPROM_I2C_SDA_PIN                  GPIO_Pin_7                  /* PB.7 */
#define EEPROM_I2C_SDA_GPIO_PORT            GPIOB                       /* GPIOB */
#define EEPROM_I2C_SDA_GPIO_CLK             RCC_APB2Periph_GPIOB#define I2C_SPEED 200000extern uint8_t I2C_Buf[I2C_BUF_LEN];

配置和功能函数如下:

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>/* Private macro -------------------------------------------------------------*/
#define TIMEOUT 1000/* Private variables ---------------------------------------------------------*/
uint8_t EEPROM_ADDRESS = EEPROM_Block_ADDRESS;u32 I2C_Timeout =1000;static void delay_ms(u32 t)
{u16 i = 8000;while(t--){i = 8000;while(i--);}
}static void delay_us(u32 d)
{while(d--) ;
}/*** @brief  Configure the used I/O ports pin* @param  None* @retval : None*/
void GPIO_Configuration(void)
{
#if 1GPIO_InitTypeDef  GPIO_InitStructure; RCC_APB2PeriphClockCmd( EEPROM_I2C_SCL_GPIO_CLK | EEPROM_I2C_SDA_GPIO_CLK, ENABLE );/* Configure I2C1 pins: SCL and SDA */GPIO_InitStructure.GPIO_Pin        =   EEPROM_I2C_SCL_PIN | EEPROM_I2C_SDA_PIN;GPIO_InitStructure.GPIO_Speed  =  GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode       =  GPIO_Mode_AF_OD;//GPIO_Init(EEPROM_I2C_SCL_GPIO_PORT | EEPROM_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);GPIO_Init(EEPROM_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
#endif
}/*** @brief  I2C Configuration* @param  None* @retval : None*/
void I2C_Configuration(void)
{
#if 1I2C_InitTypeDef  I2C_InitStructure; RCC_APB1PeriphClockCmd( EEPROM_I2C_CLK, ENABLE );/* I2C configuration */I2C_InitStructure.I2C_Mode         = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle     = I2C_DutyCycle_2;//I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;I2C_InitStructure.I2C_Ack         = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed            = I2C_SPEED;/* Apply I2C configuration after enabling it */I2C_Init(EEPROM_I2C, &I2C_InitStructure);/* I2C Peripheral Enable */I2C_Cmd(EEPROM_I2C, ENABLE);#endif
}/*** @brief  Initializes peripherals used by the I2C EEPROM driver.* @param  None* @retval : None*/
void I2C_EE_Init()
{/* GPIO configuration */GPIO_Configuration();/* I2C configuration */I2C_Configuration();/* depending on the EEPROM Address selected in the i2c_ee.h file *//* Select the EEPROM Block0 to write on */EEPROM_ADDRESS = EEPROM_Block_ADDRESS;
}/*** @brief  Writes one byte to the I2C EEPROM.* @param pBuffer : pointer to the buffer  containing the data to be *   written to the EEPROM.* @param WriteAddr : EEPROM's internal address to write to.* @retval : None*/
void I2C_EE_ByteWrite(uint8_t* pBuffer, uint8_t WriteAddr)
{/* While the bus is busy */while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY));/* Send STRAT condition */I2C_GenerateSTART(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT))  {if(I2C_Timeout-- == 0) break;}/* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);I2C_Timeout = TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){if(I2C_Timeout-- == 0) break;}/* Send the EEPROM's internal address to write to */I2C_SendData(EEPROM_I2C, WriteAddr);I2C_Timeout = TIMEOUT;/* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if(I2C_Timeout-- == 0) break;}/* Send the byte to be written */I2C_SendData(EEPROM_I2C, *pBuffer); I2C_Timeout = TIMEOUT;/* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if(I2C_Timeout-- == 0) break;}/* Send STOP condition */I2C_GenerateSTOP(EEPROM_I2C, ENABLE);/* 延时不得小于5ms write cycle time*/delay_ms(15);
}/*** @brief  Writes more than one byte to the EEPROM with a single WRITE*   cycle. The number of byte can't exceed the EEPROM page size.* @param pBuffer : pointer to the buffer containing the data to be *   written to the EEPROM.* @param WriteAddr : EEPROM's internal address to write to.* @param NumByteToWrite : number of bytes to write to the EEPROM.* @retval : None*/
void I2C_EE_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr)
{
#if 1uint8_t NumByteToWrite;NumByteToWrite = I2C_PageSize;/* While the bus is busy */while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY));/* Send START condition */I2C_GenerateSTART(EEPROM_I2C, ENABLE);/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)); /* Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  /* Send the EEPROM's internal address to write to */    I2C_SendData(EEPROM_I2C, WriteAddr);  /* Test on EV8 and clear it */while(! I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));/* While there is data to be written */while(NumByteToWrite--)  {/* Send the current byte */I2C_SendData(EEPROM_I2C, *pBuffer); /* Point to the next byte to be written */pBuffer++; /* Test on EV8 and clear it */while (!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));}/* Send STOP condition */I2C_GenerateSTOP(EEPROM_I2C, ENABLE);/* 延时不得小于5ms write cycle time*/delay_ms(20);#endif
}void I2C_EE_RandomrRead(uint8_t* pBuffer, uint8_t ReadAddr)
{  /* While the bus is busy */while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY));/* step 1 Send START condition */I2C_GenerateSTART(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)){if(I2C_Timeout-- == 0) break;}/* step 2 Send EEPROM address for write */I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Transmitter);I2C_Timeout = TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){if(I2C_Timeout-- == 0) break;}/* Clear EV6 by setting again the PE bit */I2C_Cmd(EEPROM_I2C, ENABLE);//printf("\r\nstep 3:IIC reg addr   \r\n");/* step 3 Send the EEPROM's internal address to write to */I2C_SendData(EEPROM_I2C, ReadAddr);  I2C_Timeout = TIMEOUT;/* Test on EV8 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){if(I2C_Timeout-- == 0) break;}/* step 4 Send STRAT condition a second time */  I2C_GenerateSTART(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)){if(I2C_Timeout-- == 0) break;}/*step 5  Send EEPROM address for read */I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Receiver);I2C_Timeout = TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){if(I2C_Timeout-- == 0) break;}/*step 6  Disable Acknowledgement */I2C_AcknowledgeConfig(EEPROM_I2C, DISABLE);/*step 7 Send STOP Condition ,如果不在此处发stop信号, 而在接收数据后,会多收一个字节*/I2C_GenerateSTOP(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_RXNE) == RESET){if(I2C_Timeout-- == 0) break;}*pBuffer = I2C_ReceiveData(EEPROM_I2C);/*step 7 Send STOP Condition *///I2C_GenerateSTOP(EEPROM_I2C, ENABLE);//printf("\r\nIIC rec data  0x%x\r\n",*pBuffer);
}uint8_t I2C_EE_CurrentRead(void)
{  uint8_t recdata = 0x0;
#if 1/* While the bus is busy */while(I2C_GetFlagStatus(EEPROM_I2C, I2C_FLAG_BUSY));/* step 4 Send STRAT condition a second time */  I2C_GenerateSTART(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;/* Test on EV5 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_MODE_SELECT)){if(I2C_Timeout-- == 0) break;}/*step 5  Send EEPROM address for read */I2C_Send7bitAddress(EEPROM_I2C, EEPROM_ADDRESS, I2C_Direction_Receiver);I2C_Timeout = TIMEOUT;/* Test on EV6 and clear it */while(!I2C_CheckEvent(EEPROM_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){if(I2C_Timeout-- == 0) break;}/*step 6  Disable Acknowledgement */I2C_AcknowledgeConfig(EEPROM_I2C, DISABLE);/*step 7 Send STOP Condition ,如果不在此处发stop信号, 而在接收数据后,会多收一个字节*/I2C_GenerateSTOP(EEPROM_I2C, ENABLE);I2C_Timeout = TIMEOUT;while(I2C_GetFlagStatus(EEPROM_I2C,I2C_FLAG_RXNE) == RESET){if(I2C_Timeout-- == 0) break;}recdata = I2C_ReceiveData(EEPROM_I2C);/*step 7 Send STOP Condition *///I2C_GenerateSTOP(EEPROM_I2C, ENABLE);
#endif  return recdata;
}

代码参考了普中科技的ARM板子例程。板子例程里有很多bug不太好用。如果有源码大家可以对比研究。我实现了随机读,顺序读,按字节写,按页写等4种标准操作。请注意注释部分,这些代码都经过平台验证,可以直接使用,因为我的板子A0~A2都接到GND上了,所以,我的代码支持前256字节操作。

实际波形如下:

STM32硬件IIC读写EEPROM相关推荐

  1. STM32H7系列使用硬件IIC读写EEPROM(HAL库配置源码)

    记得在使用STM32F103系列时,好多人说其硬件IIC通讯不稳定.后来我们用到了STM32H743的单片机,使用了其硬件IIC对EEPROM进行读写.硬件IIC使用并不麻烦,而且相比于I/O模拟的I ...

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

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

  3. stm32 硬件IIC使用方法说明与示例---LIS3DH的IIC通信

    有时我们可能需要MCU进行速率较高的IIC总线通信,一般stm32的IIC默认传输速率是100kpbs,最大为400kpbs.现在大部分项目会使用程序IO模拟的IIC,使用方便,具体网上例子很多. 这 ...

  4. stm32 i2c/IIC读写HP303S气压传感器

    该款芯片的详细信息可以看其数据手册 ,这里不多做介绍. 读写HP303S的操作是基于IIC通讯的.本实验采用的是硬件IIC通讯,所以器件地址是0x77,值得注意的是,在stm32的硬件IIC 读写操作 ...

  5. STM32硬件IIC的BUG问题

    问题描述 大概是这样,使用STM32硬件IIC作为主机通讯,只要不发送错误的从机地址, 通讯一直都是没问题的,因为验证程序的关系,所以在程序中修改了一下从机地址, 这时候就出现了问题,下面直接看图把 ...

  6. mini2440----keil for AMR之IIC读写EEPROM(AT24C08)

    mini2440----keil for AMR之IIC读写EEPROM(AT24C08) 一:EEPROM芯片介绍 在这里分析AT24C02A/AT24C04A/AT24C08A,对于其他不同型号的 ...

  7. 12. STM32——硬件IIC驱动OLED屏幕显示

    STM32--硬件IIC驱动OLED屏幕显示 OLED屏幕 OLED屏幕特点 OLED屏幕接线说明 OLED屏幕显存 OLED屏幕原理 OLED屏幕常用指令 OLED屏幕字模软件的使用 写命令 写数据 ...

  8. 基于stm32硬件IIC的oled显示

    一 stm32硬件IIC 硬件IIC特性架构 ①通讯引脚 查看对应开发板芯片的原理图可以查看对应IIC外设引脚的位置 这里代码采用的是stm32f103c8t6,硬件IIC的外设引脚为PB6 PB7, ...

  9. 使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911)

    使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911) 初始化代码 /** @brief GT911 初始化程序* @param None* @retval None*/ void GT9 ...

最新文章

  1. 诡异!MyBatis的Insert方法一直返回-2147482646?
  2. ubuntu 16.04 中配置Eclipse c++开发环境
  3. java 注解的几大作用及使用方法详解(转载)
  4. Kafka解析之失效副本
  5. php 清除缓存的操作,注意 Laravel 清除缓存 PHP artisan cache:clear 的使用
  6. 【2017-02-19】数据类型、类型转换、常量、变量、转义符。
  7. 竞赛发布|100万奖金寻DT时代“最强大脑”!
  8. Prepo —— 图标转化器
  9. login组件的两种用法_Vue.js 组件该如何正确的复用和扩展
  10. 批处理Bat教程-第一章:前言
  11. 手机三十分钟熄屏如何一直亮_如何让手机屏幕常亮
  12. 读书笔记 | 国富论(卷一)
  13. Mysql中LENGTH()函数
  14. 思科痛失瑞士电信2.5亿法郎合同
  15. qimgv(图片视频浏览器)-小工具
  16. 打造一张万能Windows安装盘(转)
  17. APP安装与卸载测试点
  18. python3注释_python3的注释
  19. tio-websocket-server 源码浅析
  20. 常见厂家贴片电容电感电阻命名规则

热门文章

  1. Java调用阿里云OSS下载文件
  2. 硬件电路常用设计摘要
  3. 取消福昕阅读器的小手的向下的箭头
  4. 记一次UDP接入服务的性能测试
  5. HDOJ 2010 水仙花数
  6. 仿朋友圈图片查看功能
  7. sparknbsp;项目启动的时候报出如下错误
  8. no openvas scap database found. (tried /var/lib/openvas/scap-data/scap.db)错误
  9. stm32f407zgt6与stm32f407vet6的通用io口差别
  10. mysql事务回滚是什么意思_Mysql事务提交及事务回滚是什么意思