STM32-I2C通信在AT24C02的应用

news2024/11/25 21:12:12

AT24C02是一种失去电源供给后依旧能保持数据的储存器,常用来储存一些配置信息,在系统重新上电之后也可以加载。它的容量是2k bit的EEPROM存储器,采用I2C通信方式。

AT24C02支持两种写操作:字节写操作和页写操作。本实验中我们采用的是字节写操作,就是一个地址一个数据这样进行数据写入。页写模式就是连续写入数据,只需写入一个地址,连续写入数据的时候,地址会自动后移,但有页限制,超出一页的时候,超出数据会覆盖原先写入的数据。

AT24C02支持三种读操作:当前地址读操作,随机地址读操作和顺序读操作模式。

当前地址读模式是基于上一次读/写操作的最后位置继续读出数据。随机地址读模式是指定地址读出数据。顺序读操作模式就是连续读出数据,会自动翻页。

注意到我们采用的STM32F1系列里,SCL时钟线为PB6,SDA数据线为PB7。本次实验中,时钟线我们就正常的设置为推挽输入,数据线则设置为开漏模式(因为我们引入了外部上拉电阻,提供稳定的空闲高电平,而且我们的数据线既要作为输出,又要作为输入,用开漏输出模式,能很好地实现输入输出共用,避免频繁IO模式切换带来的麻烦)。编写代码时,注意完成发送的时候,主机要释放SDA。

在开漏模式下,MCU读取IDR状态寄存器,来获取引脚高低电平。

接下来编写我们的实验代码:

首先编写我们的函数头文件iic.c:

#include "./BSP/IIC/iic.h"
#include "./SYSTEM/delay/delay.h"

void iic_init(void){

    GPIO_InitTypeDef gpio_init_struct = {0};

    IIC_SCL_GPIO_CLK_ENABLE();
    IIC_SDA_GPIO_CLK_ENABLE();

    //SCL设置
    gpio_init_strcut.Pin = IIC_SCL_GPIO_PIN;
    gpio_init_strcut.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_strcut.Pull = GPIO_PULLUP;
    gpio_init_strcut.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(IIC_GPIO_PORT, &gpio_init_strcut); //IIC_GPIO_PORT就是GPIOB

    //SCL设置
    gpio_init_strcut.Pin = IIC_SDA_GPIO_PIN;
    gpio_init_strcut.Mode = GPIO_MODE_OUTPUT_OD;
    HAL_GPIO_Init(IIC_GPIO_PORT, &gpio_init_strcut);
}

static void iic_delay(void){
    delay_ms(2);
}

void iic_start(void){
    //SCL为高电平时,SDA从高电平向低电平跳变,制造起始信号
    IIC_SDA(1);
    IIC_SCL(1);
    delay_ms();
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(0);
    delay_ms();//钳住总线,准备发送或者接受数据
}
 
void iic_stop(void){
    //SCL为高电平的适合,SDA从低电平向高电平跳变,制造停止信号
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
    IIC_SDA(1);
    delay_ms();
}

uint8_t iic_wait_ack(void){ //主机检测应答信号
 
    IIC_SDA(1); //主机释放SDA线
    delay_ms();
    IIC_SCL(1); //从机返回ACK
    delay_ms();
 
    if(IIC_READ_SDA){ //SDA高电平表示读取到高电平,从机未作出应答,由于上拉电阻有高电平阻塞效果,表示读取到非应答信号
        iic_stop();
        return 1;
    }
 
    IIC_SCL(0);
    delay_ms();
    return 0;
}
 
void iic_ack(void){ //从机发送低电平应答信号,将主机发送的高电平信号导入至此,使主机的数据线检测函数得到的是低电平,继续要求数据
 
    IIC_SCL(0);
    delay_ms();
    IIC_SDA(0);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
}
 
void iic_nack(void){ //从机发送非应答信号,不再要求数据
 
    IIC_SCL(0);
    delay_ms();
    IIC_SDA(1);
    delay_ms();
    IIC_SCL(1);
    delay_ms();
}

void iic_send_byte(uint8_t data){
    for(uint8_t t = 0; t < 8; t++){
        //高位先发
        IIC_SDA((data & 0x80) >> 7);
        IIC_SCL(1);
        delay_ms();
        IIC_SCL(0);
        data <<= 1; //左移一位,进行下一次发送
    }
    IIC_SDA(1); //完成后,释放数据线,进行应答检测
}
 
uint8_t iic_read_byte(uint8_t ack){
    uint8_t receive = 0;
 
    for(uint8_t i = 0; t < 8; t++){
        //高位先被输入,左移以腾空右边的位置给下一低位数据
        receive <<= 1;
        IIC_SCL(1);
        delay_ms();
        if(IIC_READ_SDA) receive++;
        IIC_SCL(0);
        delay_ms();
    }

    if(!ack) iic_nack();
    else iic_ack();
    return receive;
}

接下来编写函数头文件iic.h:

#ifndef __IIC_H
#define __IIC_H

void iic_init(void);
static void iic_delay(void);
void iic_start(void);
void iic_stop(void);
uint8_t iic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);
void iic_send_byte(uint8_t data);
uint8_t iic_read_byte(uint8_t ack);

#endif

接下来再编写存储器的函数文件24cxx.c:

#include "./BSP/IIC/iic.h"
#include "./BSP/24CXX/24cxx.h"
#include "./SYSTEM/delay/delay.h"

void at24c02_init(void){
    iic_init();
}

void at24c02_write_byte(uint8_t addr, uint8_t data){
    iic_start();
    iic_send_byte(0xA0); //发送通讯地址(写地址操作)
    iic_wait_ack();
    iic_send_byte(addr);
    iic_wait_ack();
    iic_send_byte(data);
    iic_wait_ack();
    iic_stop();

    delay_ms(10);
}

uint8_t at24c02_read_byte(uint8_t addr){
    uint8_t rec = 0;

    iic_start();
    iic_send_byte(0xA0); //发送通讯地址(写地址操作)
    iic_wait_ack();
    iic_send_byte(addr);
    iic_wait_ack();
    iic_start();
    iic_send_byte(0xA1); //发送通讯地址(写地址操作)
    iic_wait_ack();
    iic_send_byte(addr);
    iic_wait_ack();
    rec = iic_read_byte(0);
    iic_stop();

    return rec;
}

接下来编写存储器函数文件的头文件:24cxx.h:

#ifndef __24CXX_H
#define __24CXX_H

void at24c02_init(void);
void at24c02_write_byte(uint8_t addr, uint8_t data);
uint8_t at24c02_read_byte(uint8_t addr);

#endif

到这里我们的示例代码便编写完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/647276.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三十八、动态规划——背包问题( 01 背包 + 完全背包 + 多重背包 + 分组背包 + 优化)

动态规划-背包问题算法主要内容 一、基本思路1、背包问题概述2、动态规划&#xff08;DP&#xff09;问题分析 二、背包问题1、0 1 背包问题2、完全背包问题3、多重背包问题4、分组背包问题 三、例题题解 一、基本思路 1、背包问题概述 0 1 背包问题&#xff1a; 条件&#x…

前端解决按钮重复提交数据问题(节流和防抖)

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到前端初见的博文&#xff0c;本文主要讲解在工作解决按钮重复提交数据问题&#xff08;节流和防抖&#xff09; &#x1f468;‍&#x1f527; 个人主页 : 前端初见 &#x1f9…

【redis】数据类型,持久化、事务和锁机制、Java和redis交互、使用redis缓存、三大缓存问题

文章目录 Redis数据库NoSQL概论Redis安装和部署基本操作数据操作 数据类型介绍HashListSet和SortedSet 持久化RDBAOF 事务和锁机制锁 使用Java与Redis交互基本操作SpringBoot整合Redis 使用Redis做缓存Mybatis二级缓存Token持久化存储 三大缓存问题缓存穿透缓存击穿缓存雪崩 Re…

kotlin协程Job、CoroutineScope作用域,Android

kotlin协程Job、CoroutineScope作用域&#xff0c;Android import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines…

(横向刷题)【算法1-6】二分查找与二分答案【算法2-1】前缀和、差分与离散化(上),总结

【算法1-6】二分查找与二分答案 P1024[NOIP2001 提高组] 一元三次方程求解 思路&#xff1a;题目说明根与根之差的绝对值>1,且x1<x2&&f(x1)*f(x2)<0则其中存在解&#xff0c;于是联想到枚举&#xff0c;再用二分答案法控制精度 总结&#xff1a;二分对于精度…

【RabbitMQ教程】第四章 —— RabbitMQ - 交换机

&#x1f4a7; 【 R a b b i t M Q 教程】第四章—— R a b b i t M Q − 交换机 \color{#FF1493}{【RabbitMQ教程】第四章 —— RabbitMQ - 交换机} 【RabbitMQ教程】第四章——RabbitMQ−交换机&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &…

《阿里大数据之路》读书笔记:第一章 总述

阿里巴巴大数据系统体系架构图 阿里数据体系主要分为数据采集、数据计算、数据服务和数据应用四大层次。 一、数据采集层 阿里巴巴建立了一套标准的数据采集体系方案&#xff0c;致力全面、高性能、规范地完成海量数据的采集&#xff0c;并将其传输到大数据平台。 数据来源主…

【C++】 STL(下)算法、迭代器、容器适配器 和 仿函数

文章目录 算法迭代器容器适配器栈&#xff08;stack&#xff09;队列&#xff08;queue&#xff09; 仿函数 算法 STL中的算法头文件位于和文件中&#xff08;以为主&#xff09; for_each(InputIterator First,InputIterator Last,Function _Func); 遍历&#xff0c;具体做什…

电影《天空之城》观后感

上周看了电影《天空之城》这部电影&#xff0c;这部电影是六一儿童节时上映的&#xff0c;本周也算是补票吧&#xff0c;童年时&#xff0c;看的都是免费的&#xff0c;早已经忘记是在哪里看到的&#xff0c;但当时对自己触动很大&#xff0c;算是启蒙电影&#xff0c;所以今天…

【RabbitMQ教程】第二章 —— RabbitMQ - 简单案例

&#x1f4a7; 【 R a b b i t M Q 教程】第二章—— R a b b i t M Q − 简单案例 \color{#FF1493}{【RabbitMQ教程】第二章 —— RabbitMQ - 简单案例} 【RabbitMQ教程】第二章——RabbitMQ−简单案例&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人…

汽车电子Autosar之以太网SOMEIP

前言 首先&#xff0c;请问大家几个小小问题&#xff0c;你清楚&#xff1a; 你知道什么是SOME/IP吗&#xff1f;你知道为什么会产生SOME/IP即相关背景吗&#xff1f;你知道SOME/IP与SOA又有着哪些千丝万缕的联系呢&#xff1f;SOME/IP在实践中到底应该如何使用呢&#xff1f…

QuickList

基本概述 ZipList虽节省内存但是申请内存必须是连续的&#xff0c;如果内存占用很大&#xff0c;申请内存效率就会很低&#xff0c;可以限制ZipList长度和entry大小&#xff1b; 实在要存储大量数据&#xff0c;超出ZipList最佳上限了&#xff0c;此时可以创建多个ZipList来分片…

Autosar诊断实战系列04-基于CAPL语言的通信类诊断测试脚本开发

本文框架 前言1.CAPL编程简单介绍2. CAPL脚本开发实战2.1 添加CAPL Test Module2.2 CAPL脚本实战编写前言 在本系列笔者将结合工作中对诊断实战部分的应用经验进一步介绍常用UDS服务的进一步探讨及开发中注意事项, Dem/Dcm/CanTp/Fim模块配置开发及注意事项,诊断与BswM/NvM关…

OpenAI官方提示词课(五)如何进行文本翻译校正修改

在本篇文章中&#xff0c;我们将探讨如何使用大语言模型进行文本转换任务&#xff0c;例如语言翻译、拼写和语法检查、语气调整和格式转换。 翻译 ChatGPT接受多种语言的训练&#xff0c;使得模型具备翻译能力。以下是如何使用这种能力的一些示例。 prompt f""&q…

利用lambda优化反射功能实现方法调用

最近在思考lambda相关的问题&#xff0c;简单记录下做的相关反射替代和函数映射的尝试。 原理分析 lambda是jdk8才提供的&#xff0c;原理其实就是动态生成内部类来执行函数映射的方法。也就是说一段lambda表达式会对应特定的类方法&#xff0c;之后调用。底层是通过LambdaMe…

《离散数学》:逻辑

〇、前言 离散数学是数学的一个分支&#xff0c;研究离散对象和离散结构的数学理论和方法。这学期学校开了离散数学的课程&#xff0c;我受益颇丰&#xff0c;感觉到了离散数学真正的魅力&#xff0c;也被开创离散数学各个分支的人的聪明与才智深深折服。与连续数学不同&#…

Stopwatch工具类计时器探究

搬砖的我们 特别是Java开发的童鞋们, 经常需要通过记录开始时间和结束时间&#xff0c;然后通过计算差值&#xff0c;得到时间差&#xff0c;如下面的代码&#xff1a; long start System.currentTimeMillis(); long end System.currentTimeMillis(); System.out.println(…

【数字调制】数字调制技术FSK与PSK分析与研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

栈的数据结构完成表达式(5*10+2-7+5)/10+5的计算

栈&#xff08;Stack&#xff09;是一种线性数据结构&#xff0c;具有后进先出&#xff08;LIFO&#xff09;的特性。它可以理解为一种类似于抽屉的容器&#xff0c;只能在顶部进行插入和删除操作&#xff0c;其他位置不可访问。栈的基本操作包括入栈&#xff08;push&#xff…

[数字图像处理]第五章 图像复原与重建

文章目录 第五章 图像复原与重建5.1图像退化复原过程的模型图像退化图像复原图像复原与图像增强图像退化的数学模型为什么采用线性位移不变系统模型来描述图像退化过程 5.2 噪声模型x5.2.1 噪声的空间和频率特性5.2.2 一些重要的噪声概率密度函数高斯噪声实验&#xff1a;采用高…