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

文章目录

    • 一.概要
    • 二.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总线的设备进行数据读写。

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

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

相关文章

如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理?

文章目录 如何监控 PostgreSQL 中表空间的使用情况并进行合理的管理 一、引言 在 PostgreSQL 数据库中&#xff0c;表空间&#xff08;Tablespace&#xff09;是用于管理数据库对象存储位置的逻辑存储区域。有效地监控和管理表空间的使用情况对于确保数据库的性能、优化存储资…

第11章 规划过程组(三)(11.11规划成本管理)

第11章 规划过程组&#xff08;三&#xff09;11.11规划成本管理&#xff0c;在第三版教材第403~404页&#xff1b; 文字图片音频方式 第一个知识点&#xff1a;成本管理概述 1、成本的类型&#xff08;重要知识点&#xff09; 直接成本 如项目团队差旅费、工资、项目使用的…

scrapy写爬虫

Scrapy是一个用于爬取网站数据并提取结构化信息的Python框架 一、Scrapy介绍 1.引擎&#xff08;Engine&#xff09; – Scrapy的引擎是控制数据流和触发事件的核心。它管理着Spider发送的请求和接收的响应&#xff0c;以及处理Spider生成的Item。引擎是Scrapy运行的驱动力。…

Qt学生管理系统(付源码)

Qt学生管理系统 一、前言1.1 项目介绍1.2 项目目标 2、需求说明2.1 功能性说明2.2 非功能性说明 三、UX设计3.1 登录界面3.2 学生数据展示3.3 信息插入和更新 三、架构说明3.1 客户端结构如下3.2 数据流程图3.2.1 数据管理3.2.2 管理员登录 四、 设计说明3.1 数据库设计3.2 结构…

unsupported_country_region_territory

最近调用chatgpt接口出现&#xff1a;unsupported_country_region_territory&#xff0c;Country, region, or territory not supported 翻译过来的大致意思就是

合宙 Air780E模块 AT 指令 MQTT连接

固件说明 重启模块 //tx ATRESET//rx ATRESETOK ^boot.romv!\n RDY^MODE: 17,17E_UTRAN ServiceCGEV: ME PDN ACT 1NITZ: 2024/07/10,08:33:440,0查询模块版本信息 //tx ATCGMR//rx ATCGMRCGMR: "AirM2M_780E_V1161_LTE_AT"OK基本流程 4G模块支持MQTT和MQTT SSl协…

某企业数据治理总体解决方案(45页PPT)

引言&#xff1a;集团企业数据治理总体解决方案旨在构建一个高效、安全、合规且灵活的数据管理体系&#xff0c;以支持企业决策优化、业务创新、风险管理和运营效率提升。该方案通过整合数据资源、规范数据流程、强化数据质量和促进数据共享&#xff0c;实现数据资产的最大化价…

Python task

def wordcount(text):# 将文本分割成单词列表&#xff0c;并转换为小写words text.lower().split()# 初始化一个空字典用于存储单词计数word_counts {}# 遍历单词列表中的每个单词for word in words:# 如果单词在字典中&#xff0c;则计数加1&#xff0c;否则将单词加入字典并…

Flutter跨平台开发技术

仅分享文字&#xff0c;见谅 Flutter Flutter 介绍 功能跨平台性架构流行度Flutter vs React Native 配置 Windows Flutter App 环境配置 Tizen Flutter App 环境用 Dart 语言开发 Flutter AppFlutter-Tizen 的限制 Flutter 介绍 Flutter 是由 Google 推出的开源移动应用开发…

“闭门造车”之多模态思路浅谈:自回归学习与生成

©PaperWeekly 原创 作者 | 苏剑林 单位 | 科学空间 研究方向 | NLP、神经网络 这篇文章我们继续来闭门造车&#xff0c;分享一下笔者最近对多模态学习的一些新理解。 在前文《“闭门造车”之多模态思路浅谈&#xff1a;无损》中&#xff0c;我们强调了无损输入对于理想的…

Qt中实现让静态图片动起来,创建动画效果

在现代应用程序开发中&#xff0c;动画效果是提升用户体验的重要元素之一。Qt作为一个强大的跨平台应用程序框架&#xff0c;提供了丰富的工具和库来创建各种动画效果。本文将介绍如何在Qt中使用静态图片创建动画效果。 实现方法一 使用QTimer和QPixmap 1.准备图片资源&#…

Diffusion model笔记

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/f5ec0915d48e4e17bf158b70296cc8d8.png stable diffusion

谷粒商城实战笔记-27-分布式组件-SpringCloud-Gateway-创建测试API网关

本节的主要内容是创建网关模块&#xff0c;将网关注册到Nacos&#xff0c;并配置路由进行测试。 一&#xff0c;创建网关模块 右键工程New->Module&#xff0c;创建新模块&#xff0c;模块名称 gulimall-gateway。 填充各种信息。 选中Gateway依赖。 点击Create创建模块。…

普中51单片机:定时器与计数器详解及应用(七)

文章目录 引言定时器工作原理TMOD定时器/计数器工作模式寄存器定时器工作模式模式0(13位定时器/计数器)模式1(16位定时器/计数器)模式2(8位自动重装模式)模式3(两个8位计数器) 定时器配置流程代码演示——LED1间隔1秒闪烁代码演示——按键1控制LED流水灯状态代码演示——LCD160…

企业数据治理做完了,如何让业务部门用起来

引言&#xff1a;企业数据治理完成后&#xff0c;确保业务部门能够充分利用这些数据并融入日常运营中&#xff0c;是实现数据价值最大化的关键步骤。以下是一些策略和建议&#xff0c;帮助推动业务部门使用数据治理成果&#xff1a; 一、管理层面推广 高层应用示范&#xff1…

【漏洞复现】方正全媒体采编系统——binary.do——SQL注入

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 方正全媒体采编系统&#xff08;FZMediaEditor&#xff09;是一…

网络安全第一次作业

需求 前置工作 给设备配好ip地址&#xff0c;并且在总公司处配置vlan 1&#xff0c; 先建立多个安全区域 接着新建两个策略 :办公区访问dmz区域策略&#xff0c;生产区访问dmz区域策略 2 &#xff0c; 不做配置即可&#xff0c;生产区本不允许访问互联网 3&#xff0c; 新…

学习大数据DAY14 PLSQL基础语法3

目录 二重循环 三种循环随便嵌套 exit continue return 作业 数据提取 游标 隐式游标 显示游标 动态游标 游标使用流程 游标属性 游标配合循环使用示例 作业2 参数游标 current of 语句 作业3 PLSQL基础语法&#xff08;三&#xff09; 二重循环 三种循环随便嵌…

LangChain框架详解

LangChain框架详解 LangChain是一个基于语言模型开发应用程序的强大框架&#xff0c;旨在帮助开发人员简化与大模型交互、数据检索以及将不同功能模块串联起来以完成复杂任务的过程。它提供了一套丰富的工具、组件和接口&#xff0c;使开发人员能够轻松构建上下文感知和具备逻…

Qt:19.浮动窗口/子窗口(子窗口介绍、代码方式创建子窗口、设置子窗口标题、为子窗口添加控件、设置子窗口停靠位置)

目录 1.子窗口介绍&#xff1a; 2.代码方式创建子窗口&#xff1a; 3.设置子窗口标题&#xff1a; 4.为子窗口添加控件&#xff1a; 5.设置子窗口停靠位置。 1.子窗口介绍&#xff1a; 在 Qt 中&#xff0c;可以创建和管理子窗口&#xff08;子窗口体&#xff09;以实现多窗…