零基础STM32单片机编程入门(九)IIC总线详解及EEPROM实战含源码视频

news2024/11/24 16:45:06

文章目录

    • 一.概要
    • 二.IIC总线基本概念
      • 1.总体特征
      • 2.通讯流程
    • 三.EEPROM介绍
      • 1.M24C08基本介绍
      • 2.向M24C08写一个字节时序图
      • 3.从M24C08读一个字节时序图
    • 四.GPIO模拟IIC驱动M24C08读写
    • 五.CubeMX工程源代码下载
    • 六.讲解视频链接地址
    • 七.小结

一.概要

IIC(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。

二.IIC总线基本概念

I2C 总线,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。
在这里插入图片描述

1.总体特征

在这里插入图片描述

2.通讯流程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

三.EEPROM介绍

EEPROM( Electrically Erasable Programmable Read Only Memory )全称是电可擦除可编程只读存储器,是非易失存储器,可以访问到每个字节,容量比较小。目前的EEPROM一般是IIC接口或者SPI接口的。

1.M24C08基本介绍

M24C08是ST公司(意法半导体公司)的串行接口的EEPROM存储芯片,它的容量是8K bit。
在这里插入图片描述

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

芯片特性介绍:

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

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

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

4.数据保存可达100年

5.100万次擦写周期

6.高数据传送速率为400KHz、低速100KHZ和IIC总线兼容

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

在这里插入图片描述

M24C08的E2(3脚)一般接地,E1,E0是容量大点的EEPROM才有,这样M24C08这个器件,写操作时候的地址就是0xA0,读操作时候的地址是0xA1。

2.向M24C08写一个字节时序图

写操作过程中只有ACK是M24C08发出的,其他信号都是单片机发出的。

在这里插入图片描述

3.从M24C08读一个字节时序图

读操作过程中ACK跟返回的数据是M24C08发出的,其他信号都是单片机发出的。

在这里插入图片描述

四.GPIO模拟IIC驱动M24C08读写

硬件准备:

STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口,
STM32F103C8T6小系统板跟EEPROM模块连接:
板子G----模块GND
板子3.3–模块VCC
板子PB10—模块SCL
板子PB11—模块SDA

在这里插入图片描述
打开STM32CubeMX软件,新建工程
在这里插入图片描述
Part Number处输入STM32F103C8,再双击就创建新的工程
在这里插入图片描述
配置下载口引脚
在这里插入图片描述
配置外部晶振引脚
在这里插入图片描述
配置系统主频
在这里插入图片描述
配置工程文件名,保存路径,KEIL5工程输出方式
在这里插入图片描述
生成工程
在这里插入图片描述
用Keil5打开工程
在这里插入图片描述
添加代码
在这里插入图片描述
在这里插入图片描述
主要代码

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();//8M外部晶振,系统主频72M

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	EE_IIC_Init();//管脚初始化
	EE_EE_IIC_SendByteToSlave(0xA0,0x00,0x55);//0地址写入0x55
	HAL_Delay(10);//等待10ms
	EE_IIC_ReadByteFromSlave(0xA0,0x00,&EEDATA);//从0地址读取内容存储到变量
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}



#include "main.h"
#define	EE_ADDR 0xa0		
#define EE_SCL_PIN  GPIO_PIN_10   //模拟IIC的SCL信号  1.修改引脚即可修改IIC接口
#define EE_SDA_PIN  GPIO_PIN_11   //模拟IIC的SDA信号

void EE_SDA_IN(void) 	//配置成输入  
	{  
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
} 
void EE_SDA_OUT(void)//配置成输出
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}

void EE_SCK_OUT(void) //配置成输出
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}


#define EE_IIC_SCL(val)         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,val)                   //SCL      2.修改引脚即可修改IIC接口        
#define EE_IIC_SDA(val)         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11,val)                    //SDA	

 




unsigned char EE_READ_SDA(void)
{
return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11);
}	



/******************************************************************************
*函  数:void EE_IIC_Delay(void)
*功 能:IIC延时
*参  数:无
*返回值:无
*备  注: 移植时只需要将EE_IIC_Delay()换成自己的延时即可
*******************************************************************************/	
void EE_IIC_Delay(uint8_t us)
{
        for(int i = 0; i < 20; i++)    
        {
            __asm("NOP");//core bus 160M  情况下大概IIC速率 400K
        }
    
}
/******************************************************************************
*函  数:void IIC_Init(void)
*功 能:IIC初始化
*参  数:无
*返回值:无
*备  注:无
*******************************************************************************/

void EE_IIC_Init(void)
{			
  __HAL_RCC_GPIOB_CLK_ENABLE();
   
    EE_SCK_OUT();
    EE_SDA_OUT();
    EE_IIC_SCL(1);
    EE_IIC_SDA(1);
    
}
	
void EE_IIC_Start(void)
{
	EE_SDA_OUT(); //sda线输出 
	EE_IIC_SDA(1);	
	EE_IIC_SCL(1);
	EE_IIC_Delay(4);
 	EE_IIC_SDA(0); //START:when CLK is high,DATA change form high to low 
	EE_IIC_Delay(4);
	EE_IIC_SCL(0); //钳住I2C总线,准备发送或接收数据 
}

	  
void EE_IIC_Stop(void)
{
	EE_SDA_OUT(); //sda线输出
	EE_IIC_SCL(0);
	EE_IIC_SDA(0); //STOP:when CLK is high DATA change form low to high
  EE_IIC_Delay(4);
	EE_IIC_SCL(1); 
	EE_IIC_SDA(1); //发送I2C总线结束信号
  EE_IIC_Delay(4);							   	
}


uint8_t EE_IIC_WaitAck(void)
{
	uint8_t ucErrTime=0;
	EE_SDA_IN(); //SDA设置为输入  (从机给一个低电平做为应答) 
	EE_IIC_SDA(1);EE_IIC_Delay(1);	   
	EE_IIC_SCL(1);EE_IIC_Delay(1);;	 
	while(EE_READ_SDA())
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			EE_IIC_Stop();
			return 1;
		}
	}
	EE_IIC_SCL(0); //时钟输出0 	   
	return 0;  
} 



void EE_IIC_Ack(void)
{
	EE_IIC_SCL(0);
	EE_SDA_OUT();
	EE_IIC_SDA(0);
	EE_IIC_Delay(1);
	EE_IIC_SCL(1);
	EE_IIC_Delay(2);
	EE_IIC_SCL(0);
}


void EE_IIC_NAck(void)
{
	EE_IIC_SCL(0);
	EE_SDA_OUT();
	EE_IIC_SDA(1);
	EE_IIC_Delay(1);
	EE_IIC_SCL(1);
	EE_IIC_Delay(1);
	EE_IIC_SCL(0);
}					 				     

	  
void EE_IIC_SendByte(uint8_t data)
{                        
    uint8_t t;   
    EE_SDA_OUT(); 	    
    EE_IIC_SCL(0); //拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        EE_IIC_SDA((data&0x80)>>7);
        EE_IIC_Delay(1);			
        EE_IIC_SCL(1);
        data<<=1;
        EE_IIC_Delay(1);
        EE_IIC_SCL(0);	   
    }
    EE_IIC_Delay(1);
} 	 

	
uint8_t EE_IIC_ReadByte(uint8_t ack)
{
	uint8_t i,receive=0;
	EE_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据
    for(i=0;i<8;i++ )
	{
        EE_IIC_SCL(0); 
        EE_IIC_Delay(1);
        EE_IIC_SCL(1);
        receive<<=1;
        if(EE_READ_SDA())receive++; //从机发送的电平
        EE_IIC_Delay(1); 
    }					 
    if(ack)
        EE_IIC_Ack(); //发送ACK 
    else
        EE_IIC_NAck(); //发送nACK  
    return receive;
}


uint8_t EE_IIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf)
{
	EE_IIC_Start();	
	EE_IIC_SendByte(I2C_Addr);	 //发送从机地址
	if(EE_IIC_WaitAck()) //如果从机未应答则数据发送失败
	{
		EE_IIC_Stop();
		return 1;
	}
	EE_IIC_SendByte(reg); //发送寄存器地址
	EE_IIC_WaitAck();	  
	
	EE_IIC_Start();
	EE_IIC_SendByte(I2C_Addr+1); //进入接收模式			   
	EE_IIC_WaitAck();
	*buf=EE_IIC_ReadByte(0);	   
        EE_IIC_Stop(); //产生一个停止条件
	return 0;
}


uint8_t EE_EE_IIC_SendByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{
	EE_IIC_Start();
	EE_IIC_SendByte(I2C_Addr); //发送从机地址
	if(EE_IIC_WaitAck())
	{
		EE_IIC_Stop();
		return 1; //从机地址写入失败
	}
	EE_IIC_SendByte(reg); //发送寄存器地址
        EE_IIC_WaitAck();	  
	EE_IIC_SendByte(data); 
	if(EE_IIC_WaitAck())
	{
		EE_IIC_Stop(); 
		return 1; //数据写入失败
	}
	EE_IIC_Stop(); //产生一个停止条件
    
	return 0;
}

五.CubeMX工程源代码下载

链接:https://pan.baidu.com/s/1MMYww6IgUNa3wPaN-pWqdw
提取码:d39f
如果链接失效,可以联系博主给最新链接

程序下载下来之后解压就行

六.讲解视频链接地址

IIC总线讲解

七.小结

学会使用模拟IIC,能适应各种平台,不管是STM32的单片机,还是其他牌子的单片机,都能很快实现对EEPROM等IIC总线的设备进行数据读写。

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

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

相关文章

认识异常详解

1. 异常的定义&#xff1a; 在Java中&#xff0c;异常&#xff08;Exception&#xff09;是在程序执行过程中可能出现的错误或意外情况。异常可以分为两种类型&#xff1a;受检异常&#xff08;Checked Exception&#xff09;和未受检异常&#xff08;Unchecked Exception&…

C9联盟是什么?

九校联盟&#xff08;C9 League&#xff09;&#xff0c;简称C9联盟&#xff0c;是中国首个顶尖大学间的高校联盟&#xff0c;于2009年10月正式启动。 其成员都是国家首批“985工程”重点建设的一流大学&#xff0c;包括北京大学、清华大学、哈尔滨工业大学、复旦大学、上海交通…

水仙花数算法

一、水仙花的传说 希腊神话故事 传说希腊神话里&#xff0c;美少年纳西索斯&#xff08;Narcissus&#xff09;是希腊最俊美的男子&#xff0c;无数的少女对他一见倾心&#xff0c;可他却自负地拒绝了所有的人。这当中包括美丽的山中仙女伊可&#xff08;Echo&#xff09;。伊可…

(南京观海微电子)——MOS管原理及应用区别

MOS管&#xff1a; 全称为金属氧化物半导体场效应管&#xff08;Metal Oxide Semiconductor Field Effect Transistor&#xff09;&#xff0c;也被称为MOSFET&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor&#xff09;。它是一种半导体器件&#xff0c;常用…

Vulkan 学习(1)---- Vulkan 基本概念和发展历史

目录 Vulkan及其演化史Vulkan 基本概念基本术语 Vulkan 的原理Vulkan应用程序Vulkan的编程模型硬件初始化窗口展示表面资源设置流水线设置描述符和描述符缓冲池基于SPIR-V的着色器流水线管理指令的记录队列的提交 Vulkan及其演化史 目前主流的图形渲染API有OpenGL、OpenGL ES、…

Sequelize 操作 MySQL 数据库

安装 npm install --save sequelize安装驱动程序&#xff1a; npm install --save mysql2连接到数据库 要连接到数据库,必须创建一个 Sequelize 实例. 这可以通过将连接参数分别传递到 Sequelize 构造函数或通过传递一个连接 URI 来完成&#xff1a; const {Sequelize} re…

【Linux系统编程】文件系统

介绍&#xff1a; 文件系统是操作系统中负责管理和存储文件信息的软件结构&#xff0c;它组织和管理磁盘上的文件和目录&#xff0c;并定义了文件的存储结构。 Linux文件系统采用树状结构&#xff0c;只有一个根目录&#xff08;用“/”表示&#xff09;&#xff0c;其中含有下…

C++ 函数高级——函数的默认参数

函数默认参数 在C中&#xff0c;函数的形参列表中的形参是可以有默认值的 语法&#xff1a;返回值类型 函数名 &#xff08;参数 默认值&#xff09;{ } 示例&#xff1a; 正确代码&#xff1a; 运行结果&#xff1a;

黑马|最新AI+若依 |初识项目

本章主要内容是&#xff1a; 1.快速搭建了若依前后端项目在本地 2.实现了单表的增删改查快速生成 文章目录 介绍1.若依介绍2.若依的不同版本3.项目运行环境 初始化前后端项目1.下载若依项目2.初始化后端a.把表导入到数据库中b.更改application.yml文件 3.初始化前端a.安装依赖…

java集合(2)

目录 一. Map接口下的实现类 1. HashMap 1.1 HashMap常用方法 2. TreeMap 2.1 TreeMap常用方法 3. Hashtable 3.1 Hashtable常用方法 4.Map集合的遍历 4.1 根据键找值 4.2 利用map中的entrySet()方法 二.Collections类 1.Collections类中的常用方法 三. 泛型 1. 为什…

大连外贸建站公司wordpress主题模板

Robonaut萝卜纳特WP外贸站模板 适合用于工业机器人公司出口做外贸搭建公司官方网站使用的WordPress模板。 https://www.jianzhanpress.com/?p7091 优衣裳WordPress外贸建站模板 简洁的wordpress外贸独立站模板&#xff0c;适合服装、衣服、制衣外贸公司搭建公司官方网站使用…

shark云原生-日志体系-filebeat高级配置(适用于生产)-更新中

文章目录 1. filebeat.inputs 静态日志收集器2. filebeat.autodiscover 自动发现2.1. autodiscover 和 inputs2.2. 如何配置生效2.3. Providers 提供者2.4. Providers kubernetes2.5. 配置 templates2.5.1. kubernetes 自动发现事件中的变量字段2.5.2 配置 templates 2.6. 基于…

人工智能系列-Pandas基础

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Pandas简介 Pandas是Python语言的拓展程序库&#xff0c;用于数据分析。 Pandas是一个开放源码&#xff0c;BSD许可的库&#xff0c;提供高性能&#xff0c;易于使用的数据结…

vuepress创建步骤

背景 记录vuepress配置步骤&#xff0c;以便下次使用快速上手。 读此文章之前默认您已经学会了创建vuepress项目。vuepres快速开始 最终成品 doc.jeecgflow.com 配置步骤 创建.vuepress 目录。 你的文档目录下创建一个 .vuepress 目录。 创建.vuepress/config.js module.e…

【IMU】 确定性误差与IMU_TK标定原理

1、确定性误差 MEMS IMU确定性误差模型 K 为比例因子误差 误差来源:器件的输出往往为脉冲值或模数转换得到的值,需要乘以一个刻度系数才能转换成角速度或加速度值,若该系数不准,便存在刻度系数误差。 T 为交轴耦合误差 误差来源:如下图,b坐标系是正交的imu坐标系,s坐标系的三…

spring-ai 下载不了依赖spring-ai-openai-spring-boot-starter

第1坑&#xff1a;配置第三方仓库不生效&#xff0c; 提示在阿里云仓库没有找到 spring-ai-openai-spring-boot-starter 第2坑&#xff1a;升级jdk17后&#xff0c;springboot项目启动报错 Internal error (java.lang.reflect.InaccessibleObjectException): Unable to make pr…

第10章:网络与信息安全

目录 第10章&#xff1a;网络与信息安全 网络概述 计算机网络概念 计算机网络的分类 网络的拓扑结构 ISO/OSI网络体系结构 网络互联硬件 物理层互联设备 数据链路层互联设备 网络层互联设备 应用层互联设备 网络的协议与标准 网络标准 TCP/IP协议族 网络接口层协…

【若依前后端分离】通过输入用户编号自动带出部门名称(部门树)

一、部门树 使用 <treeselect v-model"form.deptId" :options"deptOptions" :show-count"true" placeholder"请选择归属部门"/> <el-col :span"12"><el-form-item label"归属部门" prop"dept…

C++ 什么是虚函数?什么是纯虚函数,以及区别?(通俗易懂)

&#x1f4da; 当谈到虚函数时&#xff0c;通常是指在面向对象编程中的一种机制&#xff0c;它允许在派生类中重写基类的函数&#xff0c;并且能够通过基类指针或引用调用派生类中的函数。 目录 前言 &#x1f525; 虚函数 &#x1f525; 纯虚函数 &#x1f525; 两者区别…

IntelliJ IDEA教育版在Windows电脑中的下载、安装方法

本文介绍IntelliJ IDEA软件Community&#xff08;社区版&#xff09;在Windows操作系统中的下载、安装、运行与使用方法。 IntelliJ IDEA软件是一款由JetBrains公司开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要用于Java语言的开发&#xff0c;但同时也支持其…