STM32 寄存器配置笔记——I2C 读写AT24C02 EEPROM

一、简介

        本文主要介绍STM32F10xx系列如何使用软件模拟I2C总线读写AT24C02的EEPROM数据。

二、概述

        I2C协议是一种用于同步、半双工、串行总线(由单片机时钟线、单数据交换器数据线组成)上的协议。规定了总线空闲状态、起始条件、停止条件、数据有效性、字节格式、响应确认信号、从设备地址选择、数据方向。有主从机之分,主机主控就是掌控单片机时钟信号的一方,并且起始信号和停止信号也由主机发送。现在很多的硬件、传感器等都是用到i2c协议与MCU(stm32)进行通信的。因此i2c还是必不可少的一个重要知识点。

三、I2C协议

        I2C基本读写过程如下:

        

包括:起始信号、停止信号、应答、发送数据等。

        1)起始信号

        在SCL为高定平的基础上,SDA由高电平跳变为低电平为起始信号。为一次传输的开始。

      2)停止信号

      在SCL为高定平的基础上,SDA由低电平跳变为高电平为停止信号。为一次传输的结束。

        3)数据有效性

       在起始信号接收到之后,需将SCL信号拉低准备数据传输。SCL 为高电平的时候 SDA 表示的数据有效,即此时的 SDA 为高电平时表示数据“1”,为低电平时表示数据“0”。当 SCL 为低电平时,SDA的数据无效,一般在这个时候 SDA 进行电平切换,为下一次表示数据做好准备。注意每次数据传输都以字节为单位。

        4)应答

       I2C 的数据和地址传输都带响应。响应包括“应答 (ACK)”和“非应答 (NACK)”两种信号。作为数据接收端时,当设备 (无论主从机) 接收到 I2C 传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答 (ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答 (NACK)”信号,发送方接收到该信号后会产生一个
停止信号,结束信号传输。传输时主机产生时钟,在第9个时钟时,数据发送端会释放 SDA 的控制权,由数据接收端控制SDA,若 SDA 为高电平,表示非应答信号 (NACK),低电平表示应答信号 (ACK)。
 

四、驱动代码

        1)IIC驱动

#include "iic_drv.h"
#include "delay.h"

#define IIC_SCL  PCout(12)
#define IIC_SDA  PCout(11)

#define SDA_OUT() {GPIOC->CRH &= 0xFFFF0FFF;\
                 GPIOC->CRH |= 0x00003000;\
                };

#define SDA_IN() {GPIOC->CRH &= 0xFFFF0FFF;\
                 GPIOC->CRH |= 0x00008000;\
                };

void IIC_Init(void)
{
    RCC->APB2ENR |= 1 << 4;           //enable I/O port C clock
    GPIOC->CRH &= 0xFFF00FFF;          //cfg sda scl as output PP speed 50MHZ
	  GPIOC->CRH |= 0x00033000;
	  GPIOC->ODR |= 0x3 << 11;           //cfg sda scl output '1'
}

//start signal SCL=1 SDA change from high to low
void IIC_Start(void)
{
    SDA_OUT();
	  IIC_SDA = 1;
    IIC_SCL = 1;
	  delay_us(4);
	  IIC_SDA = 0;
	  delay_us(4);
	  //IIC_SCL = 0;     //SCL change to low for ready to send data after start signal(SCL = 1,data line stable,data valid)
}

//stop signal SCL=1 SDA change from low to high
void IIC_Stop(void)
{
    SDA_OUT();
	  IIC_SDA = 0;
    IIC_SCL = 1;
	  delay_us(4);
	  IIC_SDA = 1;
	  delay_us(4);
}

//wait ack
//return       0:ACK
//             1:NACK
void IIC_WaitAck(void)
{
	  u8 ack = 0;
	  u16 timeout = 0;
    SDA_IN();
	  IIC_SCL = 1;
	  delay_us(4);
	  do
		{
	      ack = IIC_SDA;
			  timeout++;
			  if (timeout > 250)
				{
				    IIC_Stop();
					  return;
				}
		} while (ack);
}

//send Ack
void IIC_Ack(void)
{
    SDA_OUT();
	  IIC_SDA = 0;
    IIC_SCL = 1;
	  delay_us(4);
	  IIC_SCL = 0;    //release scl
	  delay_us(4);
}

//send NAck
void IIC_NAck(void)
{
    SDA_OUT();
	  IIC_SDA = 1;
    IIC_SCL = 1;
	  delay_us(4);
	  IIC_SCL = 0;    //release scl
	  delay_us(4);
}

void IIC_Send_Byte(u8 dat)
{
	  u8 i;
    SDA_OUT();

	  for (i = 0; i < 8; i++)
	  {
        IIC_SCL = 1;
			  IIC_SDA = (dat >> 7) & 0x01;
			  delay_us(2);
        IIC_SCL = 0;
			  delay_us(2);
	  }
}

u8 IIC_Read_Byte(u8 ack)
{
	  u8 i, receive = 0;
    SDA_IN();

	  for (i = 0; i < 8; i++)
	  {
        IIC_SCL = 1;
			  receive |= IIC_SDA << (7 - i);
			  delay_us(4);
        IIC_SCL = 0;
			  delay_us(4);
	  }
		
		(ack == 0) ? IIC_Ack() : IIC_NAck();
		return receive;
}

        2)AT24C02驱动

#include "AT24C02.h"
#include "iic_drv.h"
#include "delay.h"

void AT24C02_Init(void)
{
    IIC_Init();
}

u8 AT24C02_ReadOneByte(u16 ReadAddr)
{
    u8 temp = 0;
	  IIC_Start();
	  IIC_Send_Byte(0xA0);
	  IIC_WaitAck();
	  IIC_Send_Byte(ReadAddr%256);
	  IIC_WaitAck();
	  IIC_Start();
	  IIC_Send_Byte(0xA1);
	  IIC_WaitAck();
	  temp = IIC_Read_Byte(1);
	  IIC_Stop();
}

void AT24C02_WriteOneByte(u16 WriteAddr, u8 dat)
{
    IIC_Start();
	  IIC_Send_Byte(0xA0);
	  IIC_WaitAck();
	  IIC_Send_Byte(WriteAddr%256);
	  IIC_WaitAck();
    IIC_Send_Byte(dat);
	  IIC_WaitAck();
	  IIC_Stop();
	  delay_ms(10);
}

u8 AT24C02_Check(void)
{
    u8 temp;
	  temp = AT24C02_ReadOneByte(0xFF);
	  if (temp == 0x55)
			return 0;

		AT24C02_WriteOneByte(0xFF, 0x55);
		temp = AT24C02_ReadOneByte(0xFF);
		if (temp == 0x55)
			return 0;
		
		return 1;
}

void AT24C02_Read(u16 ReadAddr, u8 *pBuf, u16 NumToRead)
{
    while (NumToRead--)
		{
		    *pBuf++ = AT24C02_ReadOneByte(ReadAddr);
			  ReadAddr++;
		}
}

void AT24C02_Write(u16 WriteAddr, u8 *pBuf, u16 NumToWrite)
{
    while (NumToWrite--)
		{
		    AT24C02_WriteOneByte(WriteAddr, *pBuf);
			  WriteAddr++;
			  pBuf++;
		}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c# 为什么修改Font导致Location 变化

搜索引擎、各种人工智能&#xff0c;只有这个帮我解决了问题 然后我发现了这个 我就奇怪&#xff0c;一行行调试代码&#xff0c;最终发现设置Font&#xff0c;Location就变了&#xff0c;完全想不通

Linux 创建分区

要求 分一个区就行&#xff0c;用 ext4 文件系统&#xff0c;挂到 /data 目录。 查看 lsblk sdb 没有分区 创建分区 [rootlocalhost ~]# ll /dev/sd* brw-rw----. 1 root disk 8, 0 2月 27 15:10 /dev/sda brw-rw----. 1 root disk 8, 1 2月 27 15:10 /dev/sda1 brw-rw-…

【vue】jenkins打前端包时报错:第 8 行:cd: dist: 没有那个文件或目录

问题描述 jenkins打前端包时报错&#xff1a;第 8 行&#x1f4bf; dist: 没有那个文件或目录 Jenkins中 “Execute shell” 配置的脚本&#xff1a; echo $PATH node -v npm -v npm config set registry http://ued.edtsoft.com/ npm install npm run build:prod cd dist rm…

PostgreSQL向量数据插件--pgvector安装(附PostgreSQL安装)

PostgreSQL向量数据插件--pgvector安装 一、版本二、数据库安装1. 在官网下载PostgreSQL14.0的安装包2.增加用户postgres3.解压安装 三、pgvector安装1. 从github上克隆下来2. 安装pgvector插件3. 开始使用pgvector启用pgsql命令行创建扩展 本文为本人在安装pgvector中踩过的坑…

Github2023-12-15 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-15统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目3非开发语言项目3JavaScript项目1Python项目1Rust项目1PHP项目1 基于项目的学习 创建周期&am…

【通用】Linux,VSCode,IDEA,Eclipse等资源相对位置

正文 不论是 IDEA、Linux、VSCode、cmd等等吧&#xff0c;都遵循这个规则&#xff1a; 如果以斜杠开头&#xff0c;表示从根开始找&#xff1a; IDEA的根是classpath&#xff08;classpath就是项目被编译后&#xff0c;位于 target下的 classes文件夹&#xff0c;或者位于ta…

QT笔记(节选)具体图片等下载资源

QT笔记&#xff08;节选&#xff09;具体图片等下载资源 根据b站视频做的笔记&#xff1a; https://www.bilibili.com/video/BV1g4411H78N?p44&spm_id_frompageDriver&vd_sourcea3e6a48ccd3d7d1f969f662653ed68c9 qt是一个跨平台的c图形用户界面应用程序框架&#x…

编程导航算法通关村——算法基础

目录 1. 时间复杂度 1.1. 时间复杂度概念 1.2. 几种常见的阶 1.2.1. 常数阶 O(1) 1.2.2. 线性阶 O(n) 1.2.3. 平方阶 (n) 1.2.4. 对数阶 O(logn) 2. 最坏情况和平均情况 3. 空间复杂度 1. 时间复杂度 1.1. 时间复杂度概念 当我们说算法的时间复杂度时&#xff0c;我们…

【动手学深度学习】(十四)数据增广+微调

文章目录 一、数据增强1.理论知识2.代码 二、微调1.理论知识 一、数据增强 1.理论知识 增加一个已有数据集&#xff0c;使得有更多的多样性 在语言里面加入各种不同的背景噪音改变图片的颜色和形状 使用增强数据训练 翻转 左右翻转上下翻转 不总是可行 切割 从图片中切…

【数据结构和算法】判断子序列

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一&#xff1a;双指针 三、代码 3.1 方法一&#xff1a;双指针 3.1.1 Java易懂版&#xff1a;…

解决Chrome同一账号在不同设备无法自动同步书签的问题

文章目录 一、问题与原因&#xff1f;2. 解决办法 一、问题与原因&#xff1f; 1.问题 使用谷歌Chrome浏览器比较头疼的问题就是&#xff1a;使用同一个Google账号&#xff0c;办公电脑与家用电脑的数据无法同步。比如&#xff1a;办公电脑中的书签、浏览记录等数据&#xff0…

drf入门规范

一 Web应用模式 在开发Web应用中&#xff0c;有两种应用模式&#xff1a; 1.1 前后端不分离 1.2 前后端分离 二 API接口 为了在团队内部形成共识、防止个人习惯差异引起的混乱&#xff0c;我们需要找到一种大家都觉得很好的接口实现规范&#xff0c;而且这种规范能够让后端写…

Tomcat部署与调优

目录 前瞻 什么是tomcat&#xff1f; 什么是servlet&#xff1f; 什么是JSP? Tomcat功能组件结构 Container结构分析 Tomcat请求过程 Tomcat服务部署 1.关闭防火墙&#xff0c;将安装 Tomcat 所需软件包传到/opt目录下 2.安装JDK 3.设置JDK环境变量 4.安装启动Tomc…

1130 - Host “WIN-CA4FHERGO9J‘ is not allowed to connect to this MySQL server

1、知识小课堂 1.1 Mysql MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB公司开发&#xff0c;属于Oracle旗下产品。它是最流行的关系型数据库管理系统之一&#xff0c;在WEB应用方面&#xff0c;MySQL是最好的RDBMS (Relational Database Management System&am…

[每周一更]-(第27期):HTTP压测工具之wrk

[补充完善往期内容] wrk是一款简单的HTTP压测工具,托管在Github上,https://github.com/wg/wrkwrk 的一个很好的特性就是能用很少的线程压出很大的并发量. 原因是它使用了一些操作系统特定的高性能 io 机制, 比如 select, epoll, kqueue 等. 其实它是复用了 redis 的 ae 异步事…

逻辑回归代价函数

逻辑回归的代价函数通常使用交叉熵损失来定义。这种损失函数非常适合于二元分类问题。 本篇来推导一下逻辑回归的代价函数。 首先&#xff0c;我们在之前了解了逻辑回归的定义&#xff1a;逻辑回归模型是一种用于二元分类的模型&#xff0c;其预测值是一个介于0和1之间的概率…

都有哪些大厂开始适配鸿蒙原生应用呢

12月8日&#xff0c;随着支付宝宣布启动鸿蒙原生应用开发以来&#xff0c;国内宣布接入鸿蒙原生应用开发的公司越来越多。事实上&#xff0c;自9月华为宣布鸿蒙原生应用全面启动以来&#xff0c;已有金融、旅行、社交等多个领域的企业和开发者陆续宣布加入鸿蒙生态&#xff0c;…

twitter开发如何避坑

此篇介绍在twitter开发过程中遇到的坑&#xff08;尤其是费用的坑&#xff09;。 一坑&#xff1a;免费接口少&#xff01; 刚开始申请免费API使用的时候&#xff0c;twitter官方只会给你三个免费接口使用。 发twitter、删推文、查看用户信息。 这三个接口远远不够开发中使用…

例如,用一个DatabaseRow类型表示一个数据库行(容器),用泛型Column<T>作为它的键

以下是一个简单的示例&#xff0c;演示如何使用泛型的Column<T>作为DatabaseRow的键&#xff0c;表示一个数据库行&#xff08;容器&#xff09;&#xff1a; // 列定义 class Column<T> {private String columnName;private T value;public Column(String column…

将 Github token 添加至远程仓库

将 Github token 添加至远程仓库后便于每次 push 重复输入的麻烦 首先,将已生成的 token 记录(注:生成后的 token 确认后便无法查看只能重新生成)并找到对应的项目 git 本地文件路径下 其次,将其与项目所关联,按如下格式配置即可 token 格式类似于 ghp_CAxxxxxxxxxxxxxxxxxGx5j…