datasheet

IIC专题(二)——STM32驱动AT24C02

2019-01-09来源: eefocus关键字:IIC  STM32  驱动AT24C02

1.概述


MiniSTM32 开发板板载的 EEPROM 芯片型号为 24C02。该芯片的总容量是 256个字节,该芯片通过 IIC 总线与外部连接。这里直接采用原子板上的 AT24C02 ,主要是软件编程方面的学习。


2.硬件连接


这里写图片描述


A2、A1、A0 三个引脚直接接地。供电: (VCC = 2.7V to 5.5V)


器件地址设置:


这里写图片描述


对于AT24C02:Addr—>0xA0(写)/ 0xA1(读)。


单字节写入:


这里写图片描述


按页写入:


这里写图片描述


从当前地址读出数据;


这里写图片描述


随机读取:


这里写图片描述


顺序读出:


这里写图片描述


3.例程分析


(一)IIC 部分实现代码


包括 IIC 的初始化(IO 口)、 IIC 开始、 IIC 结束、 ACK、 IIC 读写等功能,在其他函数里面,只需要调用相关的 IIC 函数就可以和外部 IIC 器件通信了,这里并不局限于 24C02,该段代码可以用在任何 IIC 设备上。


IIC_SCL 和 IIC_SDA 分别连在 STM32 的 PC12 和 PC11。


1.IIC 初始化

//IO操作函数     

#define IIC_SCL    PCout(12) //SCL

#define IIC_SDA    PCout(11) //SDA   

#define READ_SDA   PCin(11)  //输入SDA


//初始化 IIC

void IIC_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);


    IIC_SCL=1;

    IIC_SDA=1;

}


2.产生 IIC 开始信号

//产生 IIC 起始信号

void IIC_Start(void)

{

    SDA_OUT(); //sda 线输出


    IIC_SDA=1;

    IIC_SCL=1;


    delay_us(4);


    IIC_SDA=0;//START:when CLK is high,DATA change form high to low


    delay_us(4);


    IIC_SCL=0;//钳住 I2C 总线, 准备发送或接收数据

}


3.产生停止IIC信号

//产生 IIC 停止信号

void IIC_Stop(void)

{

    SDA_OUT();//sda 线输出


    IIC_SCL=0;

    IIC_SDA=0;//STOP:when CLK is high , DATA change form low to high

    delay_us(4);


    IIC_SCL=1;


    IIC_SDA=1;//发送 I2C 总线结束信号

    delay_us(4);

}


4.等待应答信号

//等待应答信号到来

//返回值: 1,接收应答失败

// 0,接收应答成功

u8 IIC_Wait_Ack(void)

{

    u8 ucErrTime=0;


    SDA_IN(); //SDA 设置为输入


    IIC_SDA=1;

    delay_us(1);

    IIC_SCL=1;

    delay_us(1);


    while(READ_SDA)

    {

    ucErrTime++;

    if(ucErrTime>250)

    {

    IIC_Stop();

    return 1;

    }

    }

    IIC_SCL=0;//时钟输出 0

    return 0;

}



5.应答信号

//产生 ACK 应答

void IIC_Ack(void)

{

    IIC_SCL=0;


    SDA_OUT();


    IIC_SDA=0;

    delay_us(2);


    IIC_SCL=1;


    delay_us(2);

    IIC_SCL=0;

}


6.不产生应答

//不产生 ACK 应答

void IIC_NAck(void)

{

    IIC_SCL=0;

    SDA_OUT();


    IIC_SDA=1;


    delay_us(2);

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

}


7.IIC发送一个字节

//IIC 发送一个字节

//返回从机有无应答

//1,有应答

//0,无应答

void IIC_Send_Byte(u8 txd)

{

    u8 t;


    SDA_OUT();


    IIC_SCL=0;//拉低时钟开始数据传输


    for(t=0;t<8;t++)

    {

        IIC_SDA=(txd&0x80)>>7;//高位开始,一位一位的传数据

        txd<<=1;

        delay_us(2); //对 TEA5767 这三个延时都是必须的

        IIC_SCL=1;  //保持数据的稳定

        delay_us(2);

        IIC_SCL=0;   //下一位数据传输开始

        delay_us(2);

    }

}


8.IIC读一个字节

//读 1 个字节, ack=1 时,发送 ACK, ack=0,发送 nACK

u8 IIC_Read_Byte(unsigned char ack)

{

    unsigned char i,receive=0;


    SDA_IN();//SDA 设置为输入


    for(i=0;i<8;i++ )

    {

        IIC_SCL=0;

        delay_us(2);

        IIC_SCL=1;

        receive<<=1;

        if(READ_SDA)

            receive++;

        delay_us(1);

    }

    if (!ack)

    IIC_NAck();//发送 nACK

    else

    IIC_Ack(); //发送 ACK

    return receive;

}



(二)AT24C02 操作

直接通过寄存器操作设置 IO 口的模式为输入还是输出,代码如下:


#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}


#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}  


1.初始化 IIC 接口

//初始化 IIC 接口

void AT24CXX_Init(void)

{

    IIC_Init();

}


2.在 AT24CXX 指定地址读出一个数据

//在 AT24CXX 指定地址读出一个数据

//ReadAddr:开始读数的地址,24C02大小为2Kbit;ADDR:0x00---0x7FF

//返回值 :读到的数据


u8 AT24CXX_ReadOneByte(u16 ReadAddr)

{

    u8 temp=0;


    IIC_Start();

    if(EE_TYPE>AT24C16)

    /*宏定义有个选择芯片类型的,如果这个定义大于AT24C16的话就发送两个8bit地址,否则就发送一个8bit地址*/

    {

    IIC_Send_Byte(0XA0); //发送写命令,0XA0:器件的地址,7位地址+写(0)

    IIC_Wait_Ack();

    IIC_Send_Byte(ReadAddr>>8);//发送高地址

    }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址 0XA0,写数据

    IIC_Wait_Ack();

    IIC_Send_Byte(ReadAddr%256); //发送低地址

    IIC_Wait_Ack();

    IIC_Start();

    IIC_Send_Byte(0XA1); //进入接收模式,7位地址+读(1)

    IIC_Wait_Ack();

    temp=IIC_Read_Byte(0);

    IIC_Stop();//产生一个停止条件

    return temp;

}


3.在 AT24CXX 指定地址写入一个数据

//在 AT24CXX 指定地址写入一个数据

//WriteAddr :写入数据的目的地址

//DataToWrite:要写入的数据


void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)

{

    IIC_Start();

    if(EE_TYPE>AT24C16)

    {

    IIC_Send_Byte(0XA0); //发送写命令

    IIC_Wait_Ack();

    IIC_Send_Byte(WriteAddr>>8);//发送高地址

    }else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1)); //发送器件地址 0XA0,写数据

    IIC_Wait_Ack();

    IIC_Send_Byte(WriteAddr%256); //发送低地址

    IIC_Wait_Ack();

    IIC_Send_Byte(DataToWrite); //发送字节

    IIC_Wait_Ack();

    IIC_Stop(); //产生一个停止条件

    delay_ms(10); //对于 EEPROM 器件,每写一次要等待一段时间,否则写失败!

}


4.AT24CXX 里面的指定地址开始写入长度为 Len 的数据

//在 AT24CXX 里面的指定地址开始写入长度为 Len 的数据

//该函数用于写入 16bit 或者 32bit 的数据.

//WriteAddr :开始写入的地址

//DataToWrite:数据数组首地址

//Len :要写入数据的长度 2,4


void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)

{

    u8 t;

    for(t=0;t

        AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);

}


5.AT24CXX 里面的指定地址开始读出长度为 Len 的数据

//在 AT24CXX 里面的指定地址开始读出长度为 Len 的数据

//该函数用于读出 16bit 或者 32bit 的数据.

//ReadAddr :开始读出的地址

//返回值 :数据

//Len :要读出数据的长度 2,4


u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)

{

    u8 t; u32 temp=0;

    for(t=0;t

    {

        temp<<=8;

        temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);

    }

    return temp;

}


6.检查 AT24CXX 是否正常

//检查 AT24CXX 是否正常

//这里用了 24XX 的最后一个地址(255)来存储标志字.

//如果用其他 24C 系列,这个地址要修改

//返回 1:检测失败

//返回 0:检测成功

u8 AT24CXX_Check(void)

{

    u8 temp;

    temp=AT24CXX_ReadOneByte(255);//避免每次开机都写 AT24CXX

    if(temp==0X55)

        return 0;

    else//排除第一次初始化的情况

    {

        AT24CXX_WriteOneByte(255,0X55);

        temp=AT24CXX_ReadOneByte(255);

        if(temp==0X55)

            return 0;

    }

    return 1;

}


7.AT24CXX 里面的指定地址开始读出指定个数的数据

/在 AT24CXX 里面的指定地址开始读出指定个数的数据

//ReadAddr :开始读出的地址 对 24c02 为 0~255

//pBuffer :数据数组首地址

//NumToRead:要读出数据的个数


void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)

{

    while(NumToRead)

    {

        *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);

        NumToRead--;

    }

}


8.AT24CXX 里面的指定地址开始写入指定个数的数据

//在 AT24CXX 里面的指定地址开始写入指定个数的数据

//WriteAddr :开始写入的地址 对 24c02 为 0~255

//pBuffer :数据数组首地址

//NumToWrite:要写入数据的个数


void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)

{

    while(NumToWrite--)

    {

        AT24CXX_WriteOneByte(WriteAddr,*pBuffer);

        WriteAddr++;

        pBuffer++;

    }

}


参考:

1.原子 STM32 开发库函数版本


关键字:IIC  STM32  驱动AT24C02

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2019/ic-news010942856.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:SPI专题(二)——STM32驱动FLASH(W25Q64)
下一篇:STM32学习笔记一一ADC

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

51单片机之IIC&EEPROM的驱动程序

#include <reg52.h>#include "./delay/delay.h"sbit SCL = P2^0;sbit SDA = P2^1;bit ack = 0; unsigned char flag = 1;#define LCDPORT P0#define LCD_WRITE_DATA 1#define LCD_WRITE_COM 0sbit RS = P2^4;sbit RW = P2^5;sbit E = P2^6; #define SUCC 0#define ERR 1 void iic_start(){ SDA = 1;  //先
发表于 2019-04-08

GPIO模拟IIC过程中对IIC的理解

前两天在配置一款数字陀螺仪的IIC时序,分别实现了使用芯片自带IIC模块配置和使用GPIO模拟,下面谈谈个人对IIC的一些理解。概述IIC是一个总线协议,和spi类似的一个串行总线协议,它的特点是只用的信号线特别少,只需要两根,分别是SCL和SDA,但是与此同时也降低了通信速度。IIC总线信号线少就造成它的通信协议稍微复杂,理解IIC的时序是理解IIC总线的关键。.IIC总线通过上拉电阻接到VDD,当总线空闲时,两根信号线均为高电平。连接总线的任意一个器件输出低电平,将使总线信号变低,即各器件的信号线是“线与”关系。每个IIC上连接的器件都有唯一的地址(7bit),当某个器件发出广播(地址信号)时,该器件即为主机,其它器件为从机
发表于 2019-04-08

关于IIC通信协议的理解

   前段时间,一直在调SDRAM与VGA的驱动,搞了很长一段时间,参考了很多资料,最终终于思路理清了,不过鉴于手上没有相关的硬件电路,所以暂时搁置了,回归正题,先来看IIC之间的通信吧。   首先,IIC通信与UART,还有SPI统称为串行接口通信,不过它们之间还是有区别的,如UART的负电平逻辑,还有UART通信不需要时钟,只需要特定的波特率即可,SPI与IIC都可以有一个主机,多个从机的情况,不过IIC适用于短距离传输,如片间通信,摄像头的配置等场景。   要搞定IIC首先来看IIC的硬件接口:    如图所示,我们知道IIC一个主机可以悬挂多个
发表于 2019-04-08
关于IIC通信协议的理解

标准IIC和IO口模拟IIC之间的主从机通信区别

主机用的是标准IIC发送及接受数据,从机用的是IO口模拟的IIC两者之间的通信需要注意的地方:1.主机使用标准IIC发送数据时,发送函数几乎不用改动,直接按照芯片给的标准IIC发送函数。但是接收函数有几点需要注意的地方,因为标准IIC发送地址是用的是这个函数I2C_Send7bitAddress(address,IEC_DIRECTION_RX);这个函数的特点是发送和接收的发送地址都是用这个函数,但是如何区别它到底是发送时地址还是接收时地址呢?后面的那个参数就是一个标志,RX是接收,TX是发送,其中TX=0X00,RX=0X01;这在IO口模拟时是没有检验的(可见标准IIC还是很大稳定性的,呵呵),通过这个函数校验的时候就可以
发表于 2019-04-08
标准IIC和IO口模拟IIC之间的主从机通信区别

单片机硬件IIC和软件IIC区别

1. 硬件IIC用法比较复杂,模拟IIC的流程更清楚一些。2. 硬件IIC速度比模拟快,并且可以用DMA3. 模拟IIC可以在任何管脚上,而硬件只能在固定管脚上。4. 软件i2c是程序员使用程序控制SCL,SDA线输出高低电平,模拟i2c协议的时序。一般较硬件i2c稳定,但是程序较为繁琐,但不难。5. 硬件i2c程序员只要调用i2c的控制函数即可,不用直接的去控制SCL,SDA高低电平的输出。但是有些单片机的硬件i2c不太稳定,调试问题较多。
发表于 2019-04-08

STM32 IIC 详解 之 stm32 IIC 从机模式(中断方式收发数据)

1、IIC简介第二节代码会用到该部分内容,对于IIC来说,从机是不能主动发送数据的,开始条件都是由主机生成。 1.1、主机发送数据流程  1) 主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始  2) 主机接着发送一个命令字节。该字节由 7 位的外围器件地址和 1 位读写控制位 R/W组成(此时 R/W=0)  3) 相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0)  4) 主机收到从机的应答信号后开始发送第一个字节的数据  5) 从机收到数据后返回一个应答信号 ACK 
发表于 2019-04-08

小广播

何立民专栏

单片机及嵌入式宝典

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

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