IIC使用方法

news2025/4/5 16:12:56

IIC模块简介

在这里插入图片描述
iic是stm32芯片上的一个外设 有两个外设接口 其中iic1可以重映射 iic2不可以重映射

寄存器组和内部结构

在这里插入图片描述
因为iic外设挂载在APB1总线上 所以时钟也是来自于APB1总线 时钟控制寄存器就是控制开关的 发送数据和接收数据都是经过了双缓冲区(串行转行 接收 并行转串行 发送 )移位寄存器和TDR RDR寄存器 然后SDA控制电路就是负责数据帧的解析和打包的 都是由状态寄存器和CR寄存器控制 然后通过编程接口来控制这些电路

IIC初始化

在这里插入图片描述
电路连接
在这里插入图片描述
配置IO引脚
在这里插入图片描述
开启时钟
在这里插入图片描述
首先IIC1是挂载在APB1上的 然后复位 相当于按下复位按钮 第二行 然后松开按钮 第三行 把外设恢复到初始状态
使能IIC在这里插入图片描述

配置IIC参数
在这里插入图片描述
因为SCL是时钟引脚就是输出一个个方波表示时钟(主机)所以要设置波特率 首先IIC有两个模式 1。标准模式 最大的波特率为100k超过了100k就默认为高速模式 2.高速模式 所以最大的波特率不能超过400k
第二个参数就是设置模式 这里就设置为I2C——Mode——I2C 第三个参数是在高速模式下设置才有意义的 2表示低电平占2位高电平占1位 16_9表示低电平占16位 高电平占9位 灰色的参数表示为从机模式 但是我们只学习主句模式所以不需要设置
使能IIC
在这里插入图片描述

主机发送数据

数据发送流程概述
在这里插入图片描述
一开始SCL和SDA都处于空闲状态 都被上拉电阻拉为高电平 然后在SCL为高电平的情况下 SDA下降 表示数据的开始传输 发送地址(主机向从机发送)然后应答信号ACK如果应答信号不是ACK那么就跳转到STOP直接结束然后发送数据 最后发送停止位 我们只需要把这个过程封装到一个函数里面就是下面的这个函数 第一个参数就是从机的地址 第二个参数就是数据数组
第三个参数就是数组的长度
等待总线空闲
在这里插入图片描述
在这里插入图片描述
发送起始位
在这里插入图片描述
在这里插入图片描述
调用函数接口I2C_GenerateSTART IIC1 ENABLE就是向START写1发送起始位 然后查询标志位是否为1 为1就是发送完成
发送地址
在这里插入图片描述
1.清除AF 2.往TDR寄存器中写入地址 3.判断标志位ADR AF是否为1或为0
若寻址成功就可以发送数据 在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "stm32f10x.h"
#include "stm32f10x_pal.h"

static void App_I2C_Init(void);
static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size);
static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size);

int main(void)
{
	PAL_Init();
	
	App_I2C_Init();
	
  const uint8_t oled_init_command[] = {
		0x00, // Data Stream
		0xa8, 0x3f, // Set MUX Ratio
		0xd3, 0x00, // Set Display Offset
		0x40, // Set Display Start Line
		0xa0, // Set Segment re-map
		0xc0, // Set COM Output Scan Direction
		0xda, 0x02, // Set COM Pins hardware configuration
		0x81, 0x7f, // Set Contrast Control
		0xa5, // Enable Entire Display On
		0xa6, // Set Normal Display
		0xd5, 0x80, // Set OSC Frequency
		0x8d, 0x14, // Enable charge pump regulator
		0xaf, // Display on
	}; 
	
	App_I2C_MasterTransmit(0x78, oled_init_command, sizeof(oled_init_command)/sizeof(uint8_t));
	
	const uint8_t oled_display_off_command[] = {0x00, 0xae};
	const uint8_t oled_display_on_command[] = {0x00, 0xaf};
	
	uint8_t buffer[8];
	
	// 熄灭屏幕
	App_I2C_MasterTransmit(0x78, oled_display_off_command, sizeof(oled_display_off_command)/sizeof(uint8_t));
	
	App_I2C_MasterReceive(0x78, buffer, 1);
	App_I2C_MasterReceive(0x78, buffer, 2);
	App_I2C_MasterReceive(0x78, buffer, 8);
	
	App_I2C_MasterTransmit(0x78, oled_display_on_command, sizeof(oled_display_on_command)/sizeof(uint8_t));
	
	App_I2C_MasterReceive(0x78, buffer, 1);
	App_I2C_MasterReceive(0x78, buffer, 2);
	App_I2C_MasterReceive(0x78, buffer, 8);
	
	while(1)
	{
	}
}

static void App_I2C_Init(void)
{
	// #1. 初始化SCL和SDA引脚
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	// #2. 为I2C1开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
	
	// #3. 配置I2C的参数
	I2C_InitTypeDef I2C_InitStruct;
	I2C_InitStruct.I2C_ClockSpeed = 400000;
	I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
	// I2C_InitStruct.I2C_OwnAddress1 = 0x12;
	// I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;
	// I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_Init(I2C1, &I2C_InitStruct);
	
	// #4. 使能I2C
	I2C_Cmd(I2C1, ENABLE);
}

static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size)
{	
	// #1. 等待总线空闲
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);
	
	// #2. 发送起始位
	I2C_GenerateSTART(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET);
	
	// #3. 发送从机地址
	I2C_ClearFlag(I2C1, I2C_FLAG_AF);
	I2C_SendData(I2C1, SlaveAddr & 0xfe);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET)
	{
		if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
		{
			goto TAG_ERROR;
		}
	}
	I2C_ReadRegister(I2C1, I2C_Register_SR1);
	I2C_ReadRegister(I2C1, I2C_Register_SR2);
	
	// #4. 发送数据
	uint32_t i;
	for(i=0;i<Size;i++)
	{
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET)
		{
			if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
			{
				goto TAG_ERROR;
			}
		}
		I2C_SendData(I2C1, pData[i]);
	}
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET)
	{
		if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
		{
			goto TAG_ERROR;
		}
	}
	
	// #5. 发送停止位
	I2C_GenerateSTOP(I2C1, ENABLE);
	return SUCCESS;
	
TAG_ERROR:
	I2C_GenerateSTOP(I2C1, ENABLE);
	return ERROR;
}

static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size)
{
	if(Size == 0)
	{
		return ERROR;
	}
	
	// #1. 等待总线空闲
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);
	
	// #2. 发送起始位
	I2C_GenerateSTART(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET);	
	
	// #3. 发送从机地址
	I2C_ClearFlag(I2C1, I2C_FLAG_AF);
	I2C_SendData(I2C1, SlaveAddr | 0x01);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET)
	{
		if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
		{
			goto TAG_ERROR;
		}
	}
	
	// #4. 接收数据
	
	I2C_AcknowledgeConfig(I2C1, ENABLE);
	I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
	
	if(Size == 1)
	{
		I2C_ReadRegister(I2C1, I2C_Register_SR1);
		I2C_ReadRegister(I2C1, I2C_Register_SR2);
		I2C_AcknowledgeConfig(I2C1, DISABLE);
		I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
		I2C_GenerateSTOP(I2C1, ENABLE);
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);
		pDataOut[0] = I2C_ReceiveData(I2C1);
	}
	else if(Size == 2)
	{
		I2C_AcknowledgeConfig(I2C1, ENABLE);
		I2C_ReadRegister(I2C1, I2C_Register_SR1);
		I2C_ReadRegister(I2C1, I2C_Register_SR2);
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);
		I2C_AcknowledgeConfig(I2C1, DISABLE);
		I2C_GenerateSTOP(I2C1, ENABLE);
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);
		pDataOut[0] = I2C_ReceiveData(I2C1);
		pDataOut[1] = I2C_ReceiveData(I2C1);
	}
	else
	{
		uint32_t i;
		
		I2C_ReadRegister(I2C1, I2C_Register_SR1);
		I2C_ReadRegister(I2C1, I2C_Register_SR2);
		
		for(i=0;i<Size-3;i++)
		{
			while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);
			pDataOut[i] = I2C_ReceiveData(I2C1);
		}
		
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);
		
		I2C_AcknowledgeConfig(I2C1, DISABLE);
		
		pDataOut[Size-3] = I2C_ReceiveData(I2C1);
		
		I2C_GenerateSTOP(I2C1, ENABLE);
		
		pDataOut[Size-2] = I2C_ReceiveData(I2C1);
		
		while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);
		pDataOut[Size-1] = I2C_ReceiveData(I2C1);
	}
	
	return SUCCESS;
TAG_ERROR:
	I2C_GenerateSTOP(I2C1, ENABLE);
	return ERROR;
}

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

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

相关文章

蓝桥杯专题-真题版含答案-【扑克牌排列】【取球博弈】【古堡算式】【泊松分酒】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

南京航空航天大学-高等计算机网络复习

计算机网络复习 计算机网络 通信网络 网络提供信息传递服务&#xff08;端用户角度&#xff09; 通信介质&#xff1a;电子和光子&#xff0c;传输介质&#xff1a;fiber……&#xff0c;交换方式&#xff0c;协议&#xff0c;算法&#xff0c;功能&#xff0c;应用 通信网…

【DOM笔记四】事件高级!(注册/删除事件、DOM事件流、事件对象、事件委托、鼠标 / 键盘事件、相关案例)

文章目录 7 事件高级7.1 注册事件概述7.2 删除事件7.3 DOM事件流7.4 事件对象7.5 事件委托7.6 鼠标事件7.6.1 常用的鼠标事件7.6.2 鼠标事件对象 7.7 键盘事件7.7.1 常用的键盘事件7.7.2 键盘事件对象 7 事件高级 7.1 注册事件概述 给元素添加事件&#xff0c;称为注册事件或…

码住不亏!10家程序员接单平台横向对比

很多程序员都在空闲时间想要尝试接单&#xff0c;其实程序员接单在程序员圈子里非常常见&#xff0c;但想要找到一个合适的程序员接单平台却很难&#xff0c;今天给兄弟们整理了18个程序员接单平台的横向对比&#xff0c;希望可以给还在观望的小伙伴一点参考。 程序员客栈 规…

真一键关闭BitLocker!

网管小贾 / sysadm.cc 同事老莫近日喜提新电脑一台&#xff0c;遂请我周末去他家帮忙给电脑开开光。 我口送佛号欣然应允&#xff0c;心中暗道又能喝到嫂夫人的私人定制绝美养生鸡汤&#xff0c;嘿嘿&#xff0c;阿弥陀佛&#xff0c;善哉善哉&#xff01; 老莫家就租住在市中…

Python---TCP服务端程序开发

1. 开发 TCP 服务端程序开发步骤回顾 创建服务端端套接字对象绑定端口号设置监听等待接受客户端的连接请求接收数据发送数据关闭套接字 2. socket 类的介绍 导入 socket 模块import socket 创建服务端 socket 对象socket.socket(AddressFamily, Type) 参数说明: AddressF…

从0到1打造一款WebStyle串口调试工具

Tip:No Ego Some programmers have a huge problem: their own ego. But there is no time for developing an ego. There is no time for being a rockstar. Who is it who decides about your quality as programmer? You? No. The others? Probably. But can you really…

拥抱鸿蒙 - 在展讯T606平台上的探索与实践

前 言 自OpenHarmony 问世后受到了社会各界的广泛关注&#xff0c;OpenHarmony 的生态系统在如火如荼的发展。 酷派作为一家积极拥抱变化的公司&#xff0c;经过一段时间的探索与实践&#xff0c;成功实现将OpenHarmony 系统接入到展讯平台上&#xff0c;我们相信这是一个重要…

Infant-freesurfer安装和使用,适用于0-2岁婴幼儿大脑自动分割

Infant-freesurfer安装和使用 #Note https://surfer.nmr.mgh.harvard.edu/fswiki/infantFS --官网申请下载infant_recon_all --s SUBJ --age age_in_months--newborn flag (it aut

AVP摄像头与ECU交互需求规范

目录 1 文档范围及控制方法... 5 1.1 目的.... 5 1.2 文档授权... 5 1.3 文档变更管理... 5 1.4 缩写.... 5 1.5 术语.... 5 2 系统组成... 6 2.1 系统框图... 6 2.2 电源供应和时序要求... 7 2.2.1 摄像头供电控制... 7 2.2.2 摄像头上电时序要求…

Linux Centos7 安装NVIDIA 驱动

cat /etc/redhat-release 查看系统版本 服务器IP 系统版本 内核 GPU 内存和硬盘 后期扩容 10.0.2.125 CentOS Linux release 7.9.2009 5.3.10-1.el7.elrepo.x86_64 4 张 Tesla T4&#xff08;16G&#xff09; 376G 1.5T 物理机 10.0.2.130 CentOS Linux release …

消息中间件的介绍

消息中间件&#xff08;message oriented middleware&#xff09;是指支持与保障分布式应用程序之间同步/异步收发消息的中间件。消息是分布式应用之间进行数据交换的基本信息单位&#xff0c;分布式应用程序 之间的通信接口由消息中间件提供。其中&#xff0c;异步方式指消息发…

T2I-Adapter: 让马良之神笔(扩散模型)从文本生成图像更加可控

文章信息 单位&#xff1a;北大深张健团队&#xff0c;腾讯ARC lab 源码: https://github.com/TencentARC/T2I-Adapter 图1. 插个DXL的渲染图&#xff0c;这么真实的光感&#xff0c;感觉PS都可以被取代了 目录 文章信息前言一、介绍二、相关工作1.图像合成与转换2 扩散模型3 适…

多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测

多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测 目录 多维时序 | MATLAB实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现…

【计算机图形学】Ditto: Building Digital Twins of Articulated Objects from Interaction

项目主页&#xff1a;Ditto: Building Digital Twins of Articulated Objects from Interaction 文章目录 1. 为什么要做这件事2. 做了件什么事3. 之前的工作&#xff08;Related work&#xff09;铰接模型估计铰接物体的3D重建隐式神经表达物理仿真中的铰接物体 4. 问题定义5…

腾讯云服务器上传文件 :Permission denied (os error 13) ,由于权限无法上传

根据网上的修改云服务器上传文件目录的权限&#xff0c;或是用root权限上传本地文件&#xff0c;均失败。 正解办法&#xff1a; ubuntu:/home/wwwroot# sudo passwd root Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully首先修…

Windows常用的功能命令

Win操作方法 快捷键winR&#xff0c;输入cmd回车&#xff0c;然后就可以输入cmd命令了&#xff0c;赶紧收藏起来&#xff0c;用的时候更方便 打开程序和功能 快捷键winR&#xff0c;输入appwiz.cpl回车 启动计算器 快捷键winR&#xff0c;输入calc回车 计算机管理 …

saas供应链批发订货系统源码整套输出的3大好处

随着电子商务的快速发展&#xff0c;越来越多的企业开始关注和采用供应链批发订货系统&#xff0c;以提高其供应链管理的管理效率和数据沉淀。现在大多企业还是使用SaaS供应链系统&#xff0c;而源码整套输出的3大好处、尤其是第三个可让企业受益匪浅。 1. 定制化能力&#xff…

Leetcode 55 跳跃游戏

题意理解&#xff1a; 非负整数数组 nums, 最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 需要跳到nums最后一个元素即为成功。 目标&#xff1a;是否能够跳到最后一个元素。 解题思路&#xff1a; 使用贪心算法来解题&#xff0c;需要理解…

Unity中Shader平移矩阵

文章目录 前言方式一&#xff1a;对顶点本地空间下的坐标进行相加平移1、在属性面板定义一个四维变量记录在 xyz 上平移多少。2、在常量缓冲区进行申明3、在顶点着色器中&#xff0c;在进行其他坐标转化之前&#xff0c;对模型顶点本地空间下的坐标进行转化4、我们来看看效果 方…