历史上的今天
今天是:2025年08月14日(星期四)
2019年08月14日 | STM32:I2C接口读写EEPROM(AT24C02)试验例程
2019-08-14 来源:eefocus
硬件平台:stm32f10xZET6
开发环境:keil MDK uVisionv4.10
开发语言:C、ST_lib_3.5固件库
EEPROM:电可擦可编程只读存储器。
【stm32f10xZET6开发板的I2C外设物理层特点】
(1)两条串行总线:一条双向数据线(SDA),一条时钟线(SCL);
(2)从设备地址唯一;
(3)支持总线仲裁;
(4)三种速率传输模式:
标准模式100kbit/s
快速模式400kbit/s
高速模式3.4Mbit/s (目前大多I2C设备尚不支持高速模式)
(5)片上的滤波器可以滤去总线数据线上的毛刺波保证数据完整;
(6)连接到相同总线的IC数量受到总线的最大电容400pF限制;
【I2C接口特性】
(1) STM32 中和大容量型号芯片均有多达 2 个I2C总线接口;
(2) 能够工作于多主机或多从机模式,主从均可收发;
(3) 支持标准模式 100Kbit/s 和快速模式 400Kbit/s,不支持高
速模式;
(4) 支持 7 位或 10 位从设备地址寻址;
(5) 内置了硬件 CRC 发生器/ 校验器;
(6) I2C 的接收和发送都可以使用 DMA 操作;
(7) 支持系统管理总线(SMBus)总线 2.0 版;
typedef struct
{
uint32_t I2C_ClockSpeed; /*!< 指定时钟总线速率,100/400kHz */
uint16_t I2C_Mode; /*!< 指定为I2C通信模式 */
uint16_t I2C_DutyCycle; /*!< 指定I2C快速模式 */
uint16_t I2C_OwnAddress1; /*!< 指定从设备自身地址,7/10bit(地址0x0A对应宏) */
uint16_t I2C_Ack; /*!< 使能或禁止ack */
uint16_t I2C_AcknowledgedAddress; /*!< 指定7/10bit从设备地址下的ack */
} I2C_InitTypeDef;
在 stm32 如何建立与 EEPROM 的通讯步骤:
(1) 配置 I/O 端口,确定并配置 I2C 的模式,使能 GPIO 和 I2C
时钟。
(2) 写:
1) 检测 SDA 是否空闲;
2) 按 I2C 协议发出起始信号;
3) 发出 7 位器件地址和写模式;
4) 要写入的存储区首地址;
5) 用页写入方式或字节写入方式写入数据;
6) 发送 I2C 通讯结束讯信号
每个操作之后要检测“事件”确定是否成功。写完后检测 EEPROM 是否进
入 standby 状态。
(3) 读:
1) 检测 SDA 是否空闲;
2) 按 I2C 协议发出起始讯号;
3) 发出 7 位器件地址和写模式(伪写);
4) 发出要读取的存储区首地址;
5) 重发起始讯号;第 260 页 共 729 页
6) 发出 7 位器件地址和读模式;
7) 接收数据;
类似写操作,每个操作之后要检测“事件”确定是否成功。
I2C_GenerateSTART(); // 产生 I2C 的通讯起始信号 S
I2C_Send7bitAddress(); // 发送7位从设备地址
I2C_SendData(); // 发送一个数据字节(8bit)
I2C_GenerateSTOP(); // 产生 I2C 的通讯停止信号 P
I2C_CheckEvent (); // I2C 传输时的事件监测
/* 代码演示 - mian.c */
/**
******************************************************************************
* @file main.c
* @author fire
* @version V1.0
* @date 2013-xx-xx
* @brief I2C EEPROM(AT24C02)测试,测试信息通过USART1打印在电脑的超级终端
******************************************************************************
*/
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "bsP_i2c_ee.h"
#include "bsP_led.h"
#include #define EEP_Firstpage 0x00 u8 I2c_Buf_Write[256]; u8 I2c_Buf_Read[256]; void I2C_Test(void); /** * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { /* 串口1初始化 */ USART1_Config(); printf("rn 这是一个I2C外设(AT24C02)读写测试例程 rn"); //LED_GPIO_Config(); /* I2C 外设初(AT24C02)始化 */ I2C_EE_Init(); printf("rn 这是一个I2C外设(AT24C02)读写测试例程 rn"); I2C_Test(); while (1) { } } /** * @brief I2C(AT24C02)读写测试 * @param 无 * @retval 无 */ void I2C_Test(void) { u16 i; printf("写入的数据nr"); for ( i=0; i<=255; i++ ) // 填充缓冲 { I2c_Buf_Write[i] = i; printf("0x%02X ", I2c_Buf_Write[i]); if(i%16 == 15) printf("nr"); } //将I2c_Buf_Write中顺序递增的数据写入EERPOM中 //LED1(ON); I2C_EE_BufferWrite (I2c_Buf_Write, EEP_Firstpage, 256); //LED1(OFF); printf("nr写成功nr"); printf("nr读出的数据nr"); //将EEPROM读出数据顺序保持到I2c_Buf_Read中 //LED2(ON); I2C_EE_BufferRead(I2c_Buf_Read, EEP_Firstpage, 256); //LED2(OFF); //将I2c_Buf_Read中的数据通过串口打印 for (i=0; i<256; i++) { if(I2c_Buf_Read[i] != I2c_Buf_Write[i]) { printf("0x%02X ", I2c_Buf_Read[i]); printf("错误:I2C EEPROM写入与读出的数据不一致nr"); return; } printf("0x%02X ", I2c_Buf_Read[i]); if(i%16 == 15) printf("nr"); } printf("I2C(AT24C02)读写测试成功nr"); } /* 代码演示 - bsp_i2c_ee模块 */ #ifndef __I2C_EE_H #define __I2C_EE_H #include "stm32f10x.h" /* * AT24C02 2kb = 2048bit = 2048/8 B = 256 B * 32 pages of 8 bytes each * * Device Address * 1 0 1 0 A2 A1 A0 R/W * 1 0 1 0 0 0 0 0 = 0XA0 * 1 0 1 0 0 0 0 1 = 0XA1 */ /* EEPROM Addresses defines */ #define EEPROM_Block0_ADDRESS 0xA0 /* E2 = 0 */ //#define EEPROM_Block1_ADDRESS 0xA2 /* E2 = 0 */ //#define EEPROM_Block2_ADDRESS 0xA4 /* E2 = 0 */ //#define EEPROM_Block3_ADDRESS 0xA6 /* E2 = 0 */ void I2C_EE_Init(void); void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite); void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr); void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite); void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead); void I2C_EE_WaitEepromStandbyState(void); #endif /* __I2C_EE_H */ //-------------------------------------------------------- /** ****************************************************************************** * @file bsp_i2c_ee.c * @author STMicroelectronics * @version V1.0 * @date 2013-xx-xx * @brief i2c EEPROM(AT24C02)应用函数bsp ****************************************************************************** */ #include "bsp_i2c_ee.h" /* STM32 I2C 快速模式 */ #define I2C_Speed 400000 /* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */ #define I2C1_OWN_ADDRESS7 0X0A /* AT24C01/02每页有8个字节 */ #define I2C_PageSize 8 /* AT24C04/08A/16A每页有16个字节 */ //#define I2C_PageSize 16 uint16_t EEPROM_ADDRESS; /** * @brief I2C1 I/O配置 * @param 无 * @retval 无 */ static void I2C_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能与 I2C1 有关的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); /* PB6-I2C1_SCL、PB7-I2C1_SDA*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出 GPIO_Init(GPIOB, &GPIO_InitStructure); } /** * @brief I2C 工作模式配置 * @param 无 * @retval 无 */ static void I2C_Mode_Configu(void) { I2C_InitTypeDef I2C_InitStructure; /* I2C 配置 */ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; /* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */ I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = I2C1_OWN_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ; /* I2C的寻址模式 */ I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* 通信速率 */ I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; /* I2C1 初始化 */ I2C_Init(I2C1, &I2C_InitStructure); /* 使能 I2C1 */ I2C_Cmd(I2C1, ENABLE); } /** * @brief I2C 外设(EEPROM)初始化 * @param 无 * @retval 无 */ void I2C_EE_Init(void) { I2C_GPIO_Config(); I2C_Mode_Configu(); /* 根据头文件i2c_ee.h中的定义来选择EEPROM要写入的地址 */ #ifdef EEPROM_Block0_ADDRESS /* 选择 EEPROM Block0 来写入 */ EEPROM_ADDRESS = EEPROM_Block0_ADDRESS; #endif #ifdef EEPROM_Block1_ADDRESS /* 选择 EEPROM Block1 来写入 */ EEPROM_ADDRESS = EEPROM_Block1_ADDRESS; #endif #ifdef EEPROM_Block2_ADDRESS /* 选择 EEPROM Block2 来写入 */ EEPROM_ADDRESS = EEPROM_Block2_ADDRESS; #endif #ifdef EEPROM_Block3_ADDRESS /* 选择 EEPROM Block3 来写入 */ EEPROM_ADDRESS = EEPROM_Block3_ADDRESS; #endif } /** * @brief 将缓冲区中的数据写到I2C EEPROM中 * @param * @arg pBuffer:缓冲区指针 * @arg WriteAddr:写地址 * @arg NumByteToWrite:写的字节数 * @retval 无 */ void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite) { u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0; Addr = WriteAddr % I2C_PageSize; // addr = 8bit % 8 count = I2C_PageSize - Addr; // 8 - addr NumOfPage = NumByteToWrite / I2C_PageSize; NumOfSingle = NumByteToWrite % I2C_PageSize; /* If WriteAddr is I2C_PageSize aligned */ if(Addr == 0) { /* If NumByteToWrite < I2C_PageSize */ if(NumOfPage == 0) { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); I2C_EE_WaitEepromStandbyState(); } /* If NumByteToWrite > I2C_PageSize */ else { while(NumOfPage--) { I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); I2C_EE_WaitEepromStandbyState(); WriteAddr += I2C_PageSize;
史海拾趣
|
复印机打印控制器使用的是VxWorks系统,机器配置如下: CPU:PⅢ 866MHz 硬盘:61G(C,D,E三分区) 内存:256M 软驱:1.44M 网卡:10M/100M 其它:1394接口卡 无显示器及输入设备。 现C盘系统损坏,无法启动,需恢复D盘备份系统至C盘: ...… 查看全部问答> |
|
arm中断疑惑: 当中断产生时,通过中断向量表 b ResetHandler b HandlerUndef ;handler for Undefined mode b Handler ...… 查看全部问答> |
|
我装了LIBXML2,用ARM-ELF-GCC编译程序时提示错误: attempted to include iconv.h when uclibc built local support 编译用的命令如下: arm-elf-gcc cmld.c -o cmld -lm -I /boot/xml/include/libxml2 -L /boot/xml/lib -l ...… 查看全部问答> |
|
用vs2005(C++)写一个程序,在mobile5中能把数据按通讯录的格式导入数据到通讯录里。 请教各位大虾,如何实现,有哪些函数或方法… 查看全部问答> |
|
最近小弟我在研究usb固件编程,有一个疑惑,就是定义usb configuration descriptor的时候,其中的wTotalLength字段关于配置描述符的总长度时,为什么要进行高低字节交换。… 查看全部问答> |
|
谁有这两个补丁 make3_80.gvk_patches make3_80.tor2_2.new_dependency_rules 需要用。 谢谢! 原文地址:http://www.dre.vanderbilt.edu/~schmidt/DOC_ROOT/ACE/ACE-INSTALL.html#VxWorks/NT NOTE:The make (version 3.74) that is provide ...… 查看全部问答> |
|
大家谈谈SHT21应该怎么焊接?https://bbs.eeworld.com.cn/thread-153506-1-1.html看来这个芯片焊接很需要功夫哦!… 查看全部问答> |




