STM32入门开发: 采用IIC硬件时序读写AT24C08(EEPROM)

发布者:theta18最新更新时间:2022-10-13 来源: csdn关键字:STM32  时序  EEPROM 手机看文章 扫描二维码
随时随地手机看文章

一、环境介绍

编程软件: keil5


操作系统: win10


MCU型号: STM32F103ZET6


STM32编程方式: 寄存器开发 (方便程序移植到其他单片机)


IIC总线:  STM32本身支持IIC硬件时序的,上篇文章已经介绍了采用IIC模拟时序读写AT24C02,这篇文章介绍STM32的硬件IIC配置方法,并读写AT24C08。


文章地址: https://xiaolong.blog.csdn.net/article/details/117586108


模拟时序更加方便移植到其他单片机,通用性更高,不分MCU;硬件时序效率更高,每个MCU配置方法不同,依赖硬件本身支持。


器件型号: 采用AT24C08  EEPROM存储芯片


完整的工程源码下载地址,下载即可编译运行测试(包含了模拟IIC时序、STM32硬件IIC时序分别驱动AT24C02和AT24C08):  https://download.csdn.net/download/xiaolong1126626497/19399945


二、AT24C08存储芯片介绍

2.1 芯片功能特性介绍

AT24C08 是串行CMOS类型的EEPROM存储芯片,AT24C0x这个系列包含了AT24C01、AT24C02、AT24C04、AT24C08、AT24C16这些具体的芯片型号。


他们容量分别是:1K (128 x 8)、2K (256 x 8)、8K (1024 x 8)、16K (2048 x 8)  ,其中的8表示8位(bit)


它们的管脚功能、封装特点如下:

芯片功能描述:


AT24C08系列支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器;数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式。


芯片特性介绍:


1. 低压和标准电压运行

          –2.7(VCC=2.7伏至5.5伏)

          –1.8(VCC=1.8伏至5.5伏)


2. 两线串行接口(SDA、SCL)


3. 有用于硬件数据保护的写保护引脚


4. 自定时写入周期(5毫秒~10毫秒),因为内部有页缓冲区,向AT24C0x写入数据之后,还需要等待AT24C0x将缓冲区数据写入到内部EEPROM区域.


5. 数据保存可达100年


6. 100万次擦写周期


7. 高数据传送速率为400KHz、低速100KHZ和IIC总线兼容。 100 kHz(1.8V)和400 kHz(2.7V、5V)


8. 8字节页写缓冲区

这个缓冲区大小与芯片具体型号有关: 8字节页(1K、2K)、16字节页(4K、8K、16K)

      

2.2 芯片设备地址介绍

因为IIC协议规定,每次传递数据都是按8个字节传输的,AT24C08是1024字节,地址的选择上与AT24C02有所区别;


IIC设备的标准地址位是7位。上面这个图里AT24C08的1010是芯片内部固定值,A2 是硬件引脚、由硬件决定电平;P1、P0是空间存储块选择,每个存储块大小是256字节,寻址范围是0~255,AT24C08相当于是4块AT24C02的构造;最后一位是读/写位(1是读,0是写),读写位不算在地址位里,但是根据IIC的时序顺序,在操作设备前,都需要先发送7位地址,再发送1位读写位,才能启动对芯片的操作,我们在写模拟时序为了方便统一写for循环,按字节发送,所以一般都是将7地址位与1位读写位拼在一起,组合成1个字节,方便按字节传输数据。


我现在使用的开发板上AT24C08的原理图是这样的:

那么这个AT24C08的标准设备地址分别是:


第一块区域:  0x50(十六进制),对应的二进制就是: 1010000


第二块区域:  0x51(十六进制),对应的二进制就是: 1010001


第三块区域:  0x52(十六进制),对应的二进制就是: 1010010


第四块区域:  0x53(十六进制),对应的二进制就是: 1010011


如果将读写位组合在一起,读权限的设备地址: 


第一块区域:  0xA1(十六进制),对应的二进制就是: 10100001


第二块区域:  0xA3(十六进制),对应的二进制就是: 10100011


第三块区域:  0xA5(十六进制),对应的二进制就是: 10100101


第四块区域:  0xA7(十六进制),对应的二进制就是: 10100111


如果将读写位组合在一起,写权限的设备地址: 


第一块区域:  0xA0(十六进制),对应的二进制就是: 10100000


第二块区域:  0xA2(十六进制),对应的二进制就是: 10100010


第三块区域:  0xA4(十六进制),对应的二进制就是: 10100100


第四块区域:  0xA6(十六进制),对应的二进制就是: 10100110


2.3  对AT24C08 按字节写数据的指令流程(时序)

详细解释:


1.  先发送起始信号


2.  发送设备地址(写权限)


3. 等待AT24C08应答、低电平有效


4. 发送存储地址、AT24C08内部一共有256个字节空间,寻址是从0开始的,范围是(0~255);发送这个存储器地址就是告诉AT24C08接下来的数据改存储到哪个地方。


5. 等待AT24C08应答、低电平有效


6. 发送一个字节的数据,这个数据就是想存储到AT24C08里保存的数据。


7. 等待AT24C08应答、低电平有效


8. 发送停止信号


2.3  对AT24C08 按页写数据的指令流程(时序)

详细解释:


1.  先发送起始信号


2.  发送设备地址(写权限)


3. 等待AT24C08应答、低电平有效


4. 发送存储地址、AT24C08内部一共有256个字节空间,寻址是从0开始的,范围是(0~255);发送这个存储器地址就是告诉AT24C08接下来的数据改存储到哪个地方。


5. 等待AT24C08应答、低电平有效


6. 可以循环发送8个字节的数据,这些数据就是想存储到AT24C08里保存的数据。


    AT24C08的页缓冲区是16个字节,所有这里的循环最多也只能发送16个字节,多发送的字节会将前面的覆盖掉。


   需要注意的地方:  这个页缓冲区的寻址也是从0开始,比如:  0~15算第1页,16~32算第2页......依次类推。 如果现在写数据的起始地址是3,那么这一页只剩下13个字节可以写;并不是说从哪里都可以循环写16个字节。


      详细流程: 这里程序里一般使用for循环实现 


     (1).  发送字节1


     (2). 等待AT24C08应答,低电平有效


     (3). 发送字节2


     (4). 等待AT24C08应答,低电平有效


     .........


     最多8次.   


7. 等待AT24C08应答、低电平有效


8. 发送停止信号


2.4  从AT24C08任意地址读任意字节数据(时序)

AT24C08支持当前地址读、任意地址读,最常用的还是任意地址读,因为可以指定读取数据的地址,比较灵活,上面这个指定时序图就是任意地址读。


 详细解释:


1.  先发送起始信号


2.  发送设备地址(写权限)


3. 等待AT24C08应答、低电平有效


4. 发送存储地址、AT24C08内部一共有2048个字节空间,寻址是从0开始的,范围是(0~1024);发送这个存储器地址就是告诉AT24C08接下来应该返回那个地址的数据给单片机。


5. 等待AT24C08应答、低电平有效


6.  重新发送起始信号(切换读写模式)


7. 发送设备地址(读权限)


8.  等待AT24C08应答、低电平有效


9. 循环读取数据:  接收AT24C08返回的数据.


   读数据没有字节限制,可以第1个字节、也可以连续将整个芯片读完。


10. 发送非应答(高电平有效)


11. 发送停止信号


三、IIC总线介绍

2.1 IIC总线简介

I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。


I2C规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。


I2C 总线通过串行数据(SDA)线和串行时钟(SCL)线在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别,而且都可以作为一个发送器或接收器(由器件的功能决定)。


I2C有四种工作模式:

       1.主机发送

       2.主机接收

       3.从机发送

       4.从机接收


I2C总线只用两根线:串行数据SDA(Serial Data)、串行时钟SCL(Serial Clock)。


总线必须由主机(通常为微控制器)控制,主机产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。


SDA线上的数据状态仅在SCL为低电平的期间才能改变。


2.2 IIC总线上的设备连接图

I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。


其中上拉电阻范围是4.7K~100K。


2.3 I2C总线特征

I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个从设备都会对应一个唯一的地址(可以从I2C器件的数据手册得知)。主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。

1. 总线上能挂接的器件数量

I2C总线上可挂接的设备数量受总线的最大电容400pF 限制,如果所挂接的是相同型号的器件,则还受器件地址的限制。


一般I2C设备地址是7位地址(也有10位),地址分成两部分:芯片固化地址(生产芯片时候哪些接地,哪些接电源,已经固定),可编程地址(引出IO口,由硬件设备决定)。


例如: 某一个器件是7 位地址,其中10101 xxx  高4位出厂时候固定了,低3位可以由设计者决定。


则一条I2C总线上只能挂该种器件最少8个。


如果7位地址都可以编程,那理论上就可以达到128个器件,但实际中不会挂载这么多。


2. 总线速度传输速度:

I2C总线数据传输速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。一般通过I2C总线接口可编程时钟来实现传输速率的调整。


3. 总线数据长度

I2C总线上的主设备与从设备之间以字节(8位)为单位进行双向的数据传输。


2.4 I2C总线协议基本时序信号

空闲状态:SCL和SDA都保持着高电平。

起始条件:总线在空闲状态时,SCL和SDA都保持着高电平,当SCL为高电平期间而SDA由高到低的跳变,表示产生一个起始条件。在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线。


停止条件:当SCL为高而SDA由低到高的跳变,表示产生一个停止条件。


答应信号:每个字节传输完成后的下一个时钟信号,在SCL高电平期间,SDA为低,则表示一个应答信号。


非答应信号:每个字节传输完成后的下一个时钟信号,在SCL高电平期间,SDA为高,则表示一个应答信号。应答信号或非应答信号是由接收器发出的,发送器则是检测这个信号(发送器,接收器可以从设备也可以主设备)。


注意:起始和结束信号总是由主设备产生。


2.5  起始信号与停止信号

起始信号就是:  时钟线SCL处于高电平的时候,数据线SDA由高电平变为低电平的过程。SCL=1;SDA=1;SDA=0;


停止信号就是: 时钟线SCL处于低电平的时候,  数据线SDA由低电平变为高电平的过程。SCL=1;SDA=0;SDA=1;

2.6  应答信号

数据位的第9位就时应答位。 读取应答位的流程和读取数据位是一样的。示例:   SCL=0;SCL=1;ACK=SDA;       这个ACK就是读取的应答状态。

2.7 数据位传输时序

通过时序图了解到,SCL处于高电平的时候数据稳定,SCL处于低电平的时候数据不稳定。


那么对于写一位数据(STM32--->AT24C08): SCL=0;SDA=data; SCL=1; 


那么对于读一位数据(STM32<-----AT24C08): SCL=0;SCL=1;data=SDA;  

2.8 总线时序

四、IIC总线时序代码、AT24C08读写代码

在调试IIC模拟时序的时候,可以在淘宝上买一个24M的USB逻辑分析仪,时序出现问题,使用逻辑分析仪一分析就可以快速找到问题。

4.1 iic.c  这是STM32的IIC硬件时序完整代码

/*

函数功能: 初始化IIC总线

硬件连接: 

SCL---PB6

SDA---PB7

*/

void IIC_Init(void)

{

/*1. 时钟配置*/

RCC->APB2ENR|=1<<3; //PB

 

  /*2. GPIO口模式配置*/

GPIOB->CRL&=0x00FFFFFF;

GPIOB->CRL|=0xFF000000; //复用开漏输出

GPIOB->ODR|=0x3<<6;

/*3. GPIO口时钟配置(顺序不能错)*/

RCC->APB1ENR|=1<<21; //I2C1时钟

RCC->APB1RSTR|=1<<21; //开启复位时钟

RCC->APB1RSTR&=~(1<<21);//关闭复位时钟

/*4. 配置IIC的核心寄存器*/

I2C1->CR2=0x24<<0;  //配置主机频率为36MHZ

I2C1->CCR|=0x2D<<0; //配置主机频率是400KHZ

I2C1->CR1|=1<<0;    //开启IIC模块

/*

CCR=主机时钟频率/2/IIC总线的频率

45=36MHZ/2/400KHZ  ---0x2D

*/

}

 

 

/*

函数功能: 发送起始信号

当时钟线为高电平的时候,数据线由高电平变为低电平的过程

*/

void IIC_SendStart(void)

{

I2C1->CR1|=1<<8; //产生起始信号

while(!(I2C1->SR1&1<<0)){} //等待起始信号完成

I2C1->SR1=0; //清除状态位

}

 

/*

函数功能: 停止信号

当时钟线为高电平的时候,数据线由低电平变为高电平的过程

*/

void IIC_SendStop(void)

{

I2C1->CR1|=1<<9;

}

 

/*

函数功能: 发送地址数据

*/

void IIC_SendAddr(u8 addr)

{

u32 s1,s2;

I2C1->DR=addr; //发送数据

while(1)

{

s1=I2C1->SR1;

s2=I2C1->SR2;

  if(s1&1<<1) //判断地址有没有发送成功

{

break;

}

}

}

 

/*

函数功能: 发送数据

*/

void IIC_SendOneByte(u8 addr)

{

u32 s1,s2;

I2C1->DR=addr; //发送数据

while(1)

{

s1=I2C1->SR1;

s2=I2C1->SR2;

if(s1&1<<2) //判断数据有没有发送成功

{

break;

}

}

}

 

/*

函数功能: 接收一个字节数据

*/

u8 IIC_RecvOneByte(void)

{

u8 data=0;

I2C1->CR1|=1<<10; //使能应答

while(!(I2C1->SR1&1<<6)){} //等待数据

data=I2C1->DR;

I2C1->CR1&=~(1<<10); //关闭应答使能

return data;

}


4.2 AT24C08.c 这是AT24C08完整的读写代码

*

函数功能: 写一个字节

函数参数:

u8 addr 数据的位置(0~1023)

u8 data 数据范围(0~255)

*/

void AT24C08_WriteOneByte(u16 addr,u8 data)

{

    u8 read_device_addr=AT24C08_READ_ADDR;

u8 write_device_addr=AT24C08_WRITE_ADDR;

    if(addr<256*1) //第一个块

    {

        write_device_addr|=0x0<<1;

        read_device_addr|=0x0<<1;

    }

    else if(addr<256*2) //第二个块

    {

        write_device_addr|=0x1<<1;

        read_device_addr|=0x1<<1;

    }

    else if(addr<256*3) //第三个块

    {

        write_device_addr|=0x2<<1;

        read_device_addr|=0x2<<1;

    }

    else if(addr<256*4) //第四个块

    {

        write_device_addr|=0x3<<1;

        read_device_addr|=0x3<<1;

    }

    addr=addr%256; //得到地址范围

 

    

    IIC_SendStart();//起始信号

    IIC_SendAddr(write_device_addr);//发送设备地址

    IIC_SendOneByte(addr); //数据存放的地址

    IIC_SendOneByte(data); //发送将要存放的数据

    IIC_SendStop(); //停止信号

    DelayMs(10); //等待写

}

 

 

/*

函数功能: 读一个字节

函数参数:

u8 addr 数据的位置(0~1023)

返回值: 读到的数据

*/

u8 AT24C08_ReadOneByte(u16 addr)

{

    u8 data=0;

    u8 read_device_addr=AT24C08_READ_ADDR;

u8 write_device_addr=AT24C08_WRITE_ADDR;

    if(addr<256*1) //第一个块

    {

        write_device_addr|=0x0<<1;

        read_device_addr|=0x0<<1;

    }

    else if(addr<256*2) //第二个块

    {

        write_device_addr|=0x1<<1;

        read_device_addr|=0x1<<1;

    }

    else if(addr<256*3) //第三个块

    {

        write_device_addr|=0x2<<1;

        read_device_addr|=0x2<<1;

    }

    else if(addr<256*4) //第四个块

    {

        write_device_addr|=0x3<<1;

        read_device_addr|=0x3<<1;

    }

    addr=addr%256; //得到地址范围

 

    IIC_SendStart();//起始信号

    IIC_SendAddr(write_device_addr);//发送设备地址

    IIC_SendOneByte(addr); //将要读取数据的地址

    IIC_SendStart();//起始信号

    IIC_SendAddr(read_device_addr);//发送设备地址

    data=IIC_RecvOneByte();//读取数据

[1] [2]
关键字:STM32  时序  EEPROM 引用地址:STM32入门开发: 采用IIC硬件时序读写AT24C08(EEPROM)

上一篇:STM32入门开发: 介绍SPI总线、读写W25Q64(FLASH)(硬件+模拟时序)
下一篇:STM32入门开发: 介绍IIC总线、读写AT24C02(EEPROM)(采用模拟时序)

推荐阅读最新更新时间:2024-11-17 13:16

STM32程序中使用printf打印中文字符乱码
前言: 相信同我一样,有一部分同学在写单片机程序的时候喜欢用printf打印相关信息到串口,然后在串口调试助手看数据变化。 但是我之前在使用printf去打印中文字符的时候,出现了乱码,这种问题以前也碰到过,只是没去深究为什么,往往都是重新建工程,写代码。 但是时隔很久,又再次碰到这个问题,就想好好把这个问题修改完, 我是使用的IAR平台,使用的keil的小伙伴也可以用这个方法解决,都是一样的。 1、首先看一下错误。串口打印中文,串口助手出现乱码。经检查不是波特率的问题 因为每次用CubeMX配置完之后生成代码,IAR都是以默认编码UTF-8编码的,所以导致了中文乱码,如果设置成系统设置,也会乱码,错误设置如下(同
[单片机]
<font color='red'>STM32</font>程序中使用printf打印中文字符乱码
STM32基于固件库学习笔记(12)LCD5110显示
前不久使用cc2530写过LCD5110作显示,最近学习stm32就简单的写了,用stm32对lcd5110的初始化及显示功能。 还是和之前写了两种显示的方法: 万能显示(行数要/8,详细见后的数据手册) /* 这个函数可以自己设定显示的内容的大小,需用取模软件得到待显示的数据; 在取模时需注意取模方式,我这里所有的取模都设置是(纵向取模、字节倒序)方式 */ // 设置 X,Y起点; 行(/8)、列大小 数组地址名 void LCD_display(unsigned char X,unsigned char Y,unsigned char row,unsigned char col,unsigned char
[单片机]
<font color='red'>STM32</font>基于固件库学习笔记(12)LCD5110显示
STM32开发笔记67: 在keil中使用ST-Link不能成功下载的解决方法
单片机型号:STM32F091RCT6 在Keil中使用ST-Link对STM32F091RCT6单片机下载程序,第1次可下载成功,第2次就不可以成功下载,如下图所示,找不到单片机。 但是使用STVP进行程序下载是没有问题的,这就说明硬件线路板没有问题,问题出现在Keil中。 经反复测试,发现只需将connect连接方式更改为under Reset就可以正确解决,如下图所示。
[单片机]
<font color='red'>STM32</font>开发笔记67: 在keil中使用ST-Link不能成功下载的解决方法
STM32配置多个定时器同时为光电编码模式的注意事项
我在做一个小车项目中使用STM32f103中的3个定时器同时配置为编码器模式是出现的一个问题,作为一个STM32的入门者在使用编码器模式时可能出现这样的情况:按照网上的一些程序配置一个定时器为编码器模式时不会出现大问题,但是当你用同样的配置程序,同时去配置多个定时器为编码器模式是就会出现有些编码器不能计数。其实很多网上的程序都只是把定时器的配置程序提供给你,而没有把相关的中断配置程序放上去,如果你是一名初学者可能不会发现,就可能会出现上面的问题。
[单片机]
STM32之NVIC知识讲解
我们先来看一下Reference Datasheet中是如何说的: SCB- AIRCR中目前只用到4位,也就是最高能有16级中断嵌套,如果全使用的话可以达到256级 选用优先级分组(实际就是选几位用于主优先级几位用于辅优先级) 注意,我们在一个工程中只能用一种分组方式 The table below gives the allowed values of the pre-emption priority and subpriority according to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig fun
[单片机]
<font color='red'>STM32</font>之NVIC知识讲解
STM32L0 系列 EEPROM 读写,程序卡死?
前言 使用 STM32L051 和 STM32L071 替换 STM32 有一年多了,替换完成以后还根据自己产品的需求写了几篇记录博文: STM32L0 系列产品都自带了 EEPROM ,使用保存数据起来特别方便,因为写 EEPROM 并不需要删除一篇扇区,可以直接在指定地址写入。 但是最近有某个产品反馈,有时候会莫名其妙的“死机”,这是最直观的现象: 如果在初次配置完成(配置需要对 EEPROM 进行读写)后上电没问题,那么就一直没问题,如果断电重启,有可能遇到问题,遇到问题也是可以靠多重启几次解决(上电会读取 EEPROM 的数据)。 这个问题花了一些时间,其实就是 EEPROM 的读写问题。 我更新了好多次可以看出来,E
[单片机]
读写PIC16F877单片机內部EEPROM的实例
LIST P=16f877 #INCLUDE P16f877.INC ; ;- RAM LOC ATIONS------ ; ; Reserve RAM location 0x70 for IC D ; Data_EE_Addr equ 0X71 Data_EE_Data equ 0X72 ;--------VECTORS------------ org 0x0 nop goto START ;-------PROGRAM-------------- org 0X20 START call INIT ; ;---- Test the WRITE E
[单片机]
爱特梅尔带有唯一标识符的新型串行EEPROM产品系列
微控制器及触摸技术解决方案的领导厂商爱特梅尔公司(Atmel® Corporation)宣布推出两个新的串行EEPROM产品系列。AT24MAC系列器件具有预编程媒体存取控制(Media Access Control,MAC)/扩展唯一标识符(Extended Unique Identifier,EUI)的节点身份地址,缓减客户对自行对MAC/EUI地址进行编程和维护相关的复杂数据的需求,使得所有类型联网产品的开发更简单、更快速、和更廉宜。AT24CS系列器件包括工厂编程唯一只读序列号,可以帮助客户简化批量生产线的存货控制并增强产品的可追溯性。 爱特梅尔AT24MAC和AT24CS器件可用于各种细分市场,包括联网设备、消费品、白
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved