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 引用地址:IIC专题(二)——STM32驱动AT24C02

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

推荐阅读最新更新时间:2024-03-16 16:22

由浅入深尽享STM32标准库开发的乐趣
摘要:从STM32新建工程、编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣。 自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题。对于追求开发速度的业务场景下,使用快速配置软件是合理的,高效的,但对于学生的学习场景下,更为重要的是知其然并知其所以然。 以下是学习(包括但不限于)嵌入式的三个重要内容, 1、学会如何参考官方的手册和官方的代码来独立写自己的程序。 2、积累常用代码段,知道哪里的问题需要哪些代码处理。 3、跟随大佬步伐,一步一个脚印。 首先:我们都知道编程时一般查的是《参考手册》,而进行芯片选型或需要芯片数据时,查阅的是《数据手册》。此外市面上所有关于STM32的
[单片机]
由浅入深尽享<font color='red'>STM32</font>标准库开发的乐趣
基于STM32和CAN总线的电动车电池管理系统设计
随着电池能源的广泛应用,石油资源的枯竭和环境污染,电动汽车以其节能环保的优势引起越来越多的重视,在电动汽车的研究和发展上,车载电池及其管理系统的研究与制造占据着重要位置。电动汽车动力电池在应用中的主要问题表现在:生产过程中,电池的工艺,技术以及成组技术还不能保证其初始性能具有良好的一致性;使用过程中,对过充电、过放电、过温度、过电流等非常敏感,这类情况的发生会明显缩短电池寿命,甚至会导致电池报废。电池组是几十个甚至上百个单体电池串联,单体电池之间存在不一致性,随着连续的充放电循环,电池间的不一致性加剧,电池组的可用容量受容量最小的单体电池制约。对于这些情况,电池的初始性能必须要依靠企业生产工艺的优化,生产过程关键参数的控制来改善,
[电源管理]
基于<font color='red'>STM32</font>和CAN总线的电动车电池管理系统设计
STM32 PWM简介及呼吸灯实验
1.PWM简介 脉冲宽度调制(PWM)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单来说,就是对脉冲宽度的控制,原理图如下: 当CNT CCRx时,输出0,反之,则输出1。因此可以输出如上的PWM示意图。当CNT达到CCRx时,重新归零,然后再向上计数,依次循环。通过改变CCRx的值,就可以改变PWM的输出占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。 这里我们使用STM32F4的TIM14的CH1产生一路PWM输出。 值得一提的是控制PWM的三个寄存器:捕获/比较模式寄存器(TIMx_CCMR1/2),捕获/比较使能寄存器(TIMx_CCER),捕获/比较寄存器(TIMx
[单片机]
STM32 关于ADC采交直流问题探讨(二)
5. 硬件电路设计 5.1 电压比较器电路 电压比较器的功能是对两个输入电压的大小进行比较,并根据比较结果输出高低电平。 通常用阈值电压和传输特性来描述比较器的工作特性。 阈值电压(又称门槛电平)是使比较器输出电 压发生跳变时的输入电压值,简称为阈值,用符号UTH表示。估算阈值主要应抓住输入信号使输出电压发生跳变时的临界条件。这个临界条件 是集成运放两个输入端的电位相等(两个输入端的电流也视为零),即U+=U–。 5.1.1 零电平比较器(过零比较器) 电压比较器是将一个模拟输入信号ui与一个固定的参考电压UR进行比较和鉴别的电路。   参考电压为零的比较器称为零 电平比较器。按输入方式的不同可分为反相输入和同
[单片机]
<font color='red'>STM32</font> 关于ADC采交直流问题探讨(二)
STM32 构建库函数
由于自己的粗心大意 导致构建库函数 这一个简单的事 弄了好几个小时 所以我决定把这个配置的过程记录下来 我们按照这个逻辑来 就没有啥问题 前面构建工程过程 就不多赘述 新建文件夹 点击鼠标右键 选择add grup 长按 可以修改文件夹的名字 然后就是从已经有的固件库中导入文件 STRATUP 只需要选择 那个stm32f10x_ hd.s 结尾的 配置成这样就可以了 然后我们选择编译会发现出现error 但是千万不要慌 为什么呢 原因就是 就是我们锤子还没完成配置 点击锤子 选择c/c++ 点击这里 添加一下路径 这里的路径不能带中文 选择这三个就可 然后我们点开user 的main.c 文件 点击头文件
[单片机]
<font color='red'>STM32</font> 构建库函数
STM32-外部中断实验
这一节,我们将向大家介绍如何使用STM32的外部输入中断。通过第1、2节的学习,我们掌握了STM32的IO口最基本的操作。这节我们将介绍作为外部中断输入口,STM32的需要做哪些设置。本节分为如下几个部分: 3.4.1 STM32外部中断简介 3.4.2 硬件设计 3.4.3 软件设计 3.4.4 下载与测试 3.4.1 STM32外部中断简介 STM32的IO口在本章第一节有详细介绍,而外部中断在第二章也有详细的阐述。这里我们将介绍如何将这两者结合起来,实现外部中断输入。 STM32的每个IO口都可以作为中断输入,这点很好用。要把IO口作为外部中断输入,有以下几个步骤: 1)初始化IO口为输入。 这一步设置你要作为外部中断输入
[单片机]
STM32入门系列-库帮助文档使用
在前面文件夹介绍时,提到了stm32f10x_stdperiph_lib_um.chm文件,此文件是库函数使用帮助文档,可以直接打开如下图。 因为STM32库函数非常多,我们不可能把所有的外设函数都记住,那么这个帮助文档就是学习STM32库函数时所必备的, 所以要学会如何在这个帮助文档内查找函数。使用的库函数全部都在如下图所示列表里。 要查找哪个外设的库函数,只需要找到对应的外设名称即可。比如要查找对GPIO外设操作的库函数,我们可以在这个列表下往下拉找到GPIO栏,其中Functions列表下就是GPIO所有操作的库函数。 假如要查找GPIO_Init函数的功能说明及使用方法, 可以在下拉列表中点击这个函
[单片机]
基于STM32平台实现SVPWM调制
SVPWM SVPWM是空间矢量脉宽调制(Space Vector Pulse Width Modulation)的简称,通常由三相逆变器的六个功率开关管组成,经过特定的时序和换相所所产生的脉冲宽度调制波,最终输出的波形可能会十分接近理想的正弦波形。具体如下图所示;左侧为复平面,即空间矢量,右侧为时域的正弦波形。 关于SVPWM原理的文章非常多,这里可以推荐一下网上一个非常不错的教程《SVPWM的原理及法则推导和控制算法详解第五修改版》,本文将如何实现SVPWM进行简单的介绍。 IQMATH TI的片子很香,控制方面,TI无疑是做的最好的方案之一,相对来说资料也非常齐全;另外TI针对没有浮点运算器的定点DSP推出了IQMATH
[单片机]
基于<font color='red'>STM32</font>平台实现SVPWM调制
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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