STM32 IIC开发学习

1IIC总线时序图

在这里插入图片描述
① 起始信号
当 SCL 为高电平期间,SDA 由高到低的跳变。起始信号是一种电平跳变时序信号,而不是
一个电平信号。该信号由主机发出,在起始信号产生后,总线就会处于被占用状态,准备数据
传输。
② 停止信号
当 SCL 为高电平期间,SDA 由低到高的跳变。停止信号也是一种电平跳变时序信号,而不
是一个电平信号。该信号由主机发出,在停止信号发出后,总线就会处于空闲状态。
③ 应答信号
发送器每发送一个字节,就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK 简称应答位),表示接收器已经成功地接收了
该字节。应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成
功。
观察上图标号③就可以发现,有效应答的要求是从机在第 9 个时钟脉冲之前的低电平期间
将 SDA 线拉低,并且确保在该时钟的高电平期间为稳定的低电平。如果接收器是主机,则在它
收到最后一个字节后,发送一个 NACK 信号,以通知被控发送器结束数据发送,并释放 SDA
线,以便主机接收器发送一个停止信号。
④ 数据有效性
IIC 总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在
时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。数据在 SCL 的上
升沿到来之前就需准备好。并在下降沿到来之前必须稳定。
⑤ 数据传输
在 IIC 总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在 SCL 串行
时钟的配合下,在 SDA 上逐位地串行传送每一位数据。数据位的传输是边沿触发。
⑥ 空闲状态
IIC 总线的 SDA 和 SCL 两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个
器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉
高。

IIC写操作

下面介绍一下 IIC 的基本的读写通讯过程,包括主机写数据到从机即写
操作,主机到从机读取数据即读操作。
在这里插入图片描述
主机首先在 IIC 总线上发送起始信号,那么这时总线上的从机都会等待接收由主机发出的
数据。主机接着发送从机地址+0(写操作)组成的 8bit 数据,所有从机接收到该 8bit 数据后,自
行检验是否是自己的设备的地址,假如是自己的设备地址,那么从机就会发出应答信号。主机
在总线上接收到有应答信号后,才能继续向从机发送数据。注意:IIC 总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。

IIC读操作

在这里插入图片描述

主机向从机读取数据的操作,一开始的操作与写操作有点相似,观察两个图也可以发现,
都是由主机发出起始信号,接着发送从机地址+1(读操作)组成的 8bit 数据,从机接收到数据验
证是否是自身的地址。 那么在验证是自己的设备地址后,从机就会发出应答信号,并向主机返
回 8bit 数据,发送完之后从机就会等待主机的应答信号。假如主机一直返回应答信号,那么从
机可以一直发送数据,也就是图中的(n byte + 应答信号)情况,直到主机发出非应答信号,从
机才会停止发送数据。

STM32 完成IIC的各个阶段的c代码

myiic.h

#ifndef _MYIIC_H
#define _MYIIC_H#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"/****************************************************************************************************/
/* 引脚 定义 */#define IIC_SCL_GPIO_PORT               GPIOB
#define IIC_SCL_GPIO_PIN                GPIO_PIN_10
#define IIC_SCL_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 */#define IIC_SDA_GPIO_PORT               GPIOB
#define IIC_SDA_GPIO_PIN                GPIO_PIN_3
#define IIC_SDA_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 *//****************************************************************************************************//*IO 高低电平*/#define IIC_SCL(x) do{x ? \HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_RESET); \}while(0)  /* SCL */#define IIC_SDA(x) do{x ? \HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_RESET); \}while(0)  /* SDA */                     #define IIC_READ_SDA  HAL_GPIO_ReadPin(IIC_SDA_GPIO_PORT,IIC_SDA_GPIO_PIN) /* 读取SDA */void iic_start(void);
void iic_stop(void);
static void iic_delay(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

myiic.c

#include "myiic.h"/*** @brief       初始化IIC 初始化GPIO* @param       无* @retval      无*/void iic_init(void){GPIO_InitTypeDef gpio_init_struct;IIC_SCL_GPIO_CLK_ENABLE();                          /* SCL引脚时钟使能 */IIC_SDA_GPIO_CLK_ENABLE();                          /* SDA引脚时钟使能 */gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 快速 */HAL_GPIO_Init(IIC_SCL_GPIO_PORT, &gpio_init_struct);/* SCL */gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;        /* 推挽输出 */HAL_GPIO_Init(IIC_SDA_GPIO_PORT, &gpio_init_struct);/* SDA *//* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */iic_stop(); }/*** @brief       IIC延时函数,用于控制IIC读写速度* @param       无* @retval      无*/static void iic_delay(void)
{delay_us(2);
}    /*** @brief       产生IIC起始信号* @param       无* @retval      无*/void iic_start(void)
{IIC_SCL(1);IIC_SDA(1);iic_delay();IIC_SDA(0);     /* START信号: 当SCL为高时, SDA从高变成低, 表示起始信号 */iic_delay();IIC_SCL(0);     /* 钳住I2C总线,准备发送或接收数据 */iic_delay();
}/*** @brief       产生IIC停止信号* @param       无* @retval      无*/
void iic_stop(void)
{IIC_SDA(0);iic_delay();IIC_SCL(1); /* STOP信号: 当SCL为高时, SDA从低变成高, 表示停止信号 */iic_delay();IIC_SDA(1);iic_delay();
}/*** @brief       等待应答信号到来* @param       无* @retval      1,接收应答失败*              0,接收应答成功*/uint8_t iic_wait_ack(void)
{uint8_t waittime =0;uint8_t rack =0;IIC_SDA(1);     /* 主机释放SDA线(此时外部器件可以拉低SDA线) */iic_delay();IIC_SCL(1);     /* SCL=1, 此时从机可以返回ACK */iic_delay();while(IIC_READ_SDA) /* 等待应答 */{waittime++;if(waittime>250){iic_stop();rack=1;break;}}IIC_SCL(0);     /* SCL=0, 结束ACK检查 */iic_delay();return rack;
}/*** @brief       产生ACK应答* @param       无* @retval      无*/void iic_ack(void)
{/* SCL 0 -> 1  时 SDA = 0,表示应答 */IIC_SDA(0);iic_delay();IIC_SCL(1);iic_delay();IIC_SCL(0);iic_delay();IIC_SDA(1);     /* 主机释放SDA线 */iic_delay();
}/*** @brief       不产生ACK应答* @param       无* @retval      无*/void iic_nack(void)
{/* SCL 0 -> 1  时 SDA = 1,表示非应答 */IIC_SDA(1);iic_delay();IIC_SCL(1);iic_delay();IIC_SCL(0);iic_delay();}/*** @brief       IIC发送一个字节* @param       data: 要发送的数据* @retval      无*/void iic_send_byte(uint8_t data)
{uint8_t i;for(i=0;i<8;i++){IIC_SDA((data&0x80)>>7);  /* 高位先发送 */iic_delay();IIC_SCL(1);iic_delay();IIC_SCL(0);data<<=1; /* 左移1位,用于下一次发送 */}IIC_SDA(1);/* 发送完成, 主机释放SDA线 */}/*** @brief       IIC读取一个字节* @param       ack:  ack=1时,发送ack; ack=0时,发送nack* @retval      接收到的数据*/uint8_t iic_read_byte(uint8_t ack)
{uint8_t i;uint8_t rec=0;for(i=0;i<8;i++) /* 接收1个字节数据 */{rec<<=1; /* 高位先输出,所以先收到的数据位要左移 */IIC_SCL(1);iic_delay();if(IIC_READ_SDA){rec++;}IIC_SCL(0);iic_delay();}if(!ack){iic_nack();}else{iic_ack();}return rec;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构学习 Leetcode494 目标和

关键词&#xff1a;动态规划 01背包 dfs回溯 一个套路&#xff1a; 01背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要逆序遍历完全背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要正序遍历 题目&#xff1a; 解法一&#xff1a; …

Python 爬取 哔站视频弹幕 并实现词云图可视化

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 环境介绍: python 3.8 解释器 pycharm 编辑器 第三方模块: requests >>> pip install requests protobuf >>> pip install protobuf 如何安装python第三方模块: win R 输入 cmd 点击确定, 输入安装命…

Cross-Drone Transformer Network for Robust Single Object Tracking论文阅读笔记

Cross-Drone Transformer Network for Robust Single Object Tracking论文阅读笔记 Abstract 无人机在各种应用中得到了广泛使用&#xff0c;例如航拍和军事安全&#xff0c;这得益于它们与固定摄像机相比的高机动性和广阔视野。多无人机追踪系统可以通过从不同视角收集互补的…

uni-app uni.scss内置全局样式变量

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

记录使用minikube部署web程序,并灰度发布不同版本

1. 安装软件 1.1安装docker desktop 下载地址 重点&#xff1a;配置镜像加速 1.2 安装k8s&minikube 这里参考阿里社区的配置 minikube1.24.0版本下载地址 重点&#xff1a;安装版本问题【因为后面要用阿里云的服务来获取所需Docker镜像&#xff0c;一直不成功使用的高版…

vue项目中实现预览pdf

vue项目中实现预览pdf 1. iframe <iframe :src"pdfSrc"></iframe> ​data() {return {pdfSrc: http://192.168.0.254:19000/trend/2023/12/27/5635529375174c7798b5fabc22cbec45.pdf,}},​iframe {width: 100%;height: calc(100vh - 132px - 2 * 20px -…

使用pytorch搭建ResNeXt并基于迁移学习训练

冻结除最后全连接层以外的所有权重&#xff0c;只去单独训练它最后一层的的权重&#xff0c;这个方法&#xff0c;冻结了所有网络的权重。 for param in net.parameters():param.requires_grad False

【已解决】vs2015下c++对sqlite的操作

本博文源于笔者操作sqlite3&#xff0c;借鉴了很多文章的思路&#xff0c;这里并整理了c常用的对数据库的操作供大家点赞收藏以后备用。包含了&#xff1a;c对sqlite3的创建数据库、创建数据表、写入数据表、读取数据表、删除数据表。也包括了最基础的让c运行sqlite3.内容供读者…

大数据Doris(四十二):使用物化视图

文章目录 使用物化视图 一、​​​​​​​创建物化视图

Android 8.1 设置USB传输文件模式(MTP)

项目需求&#xff0c;需要在电脑端adb发送通知手机端接收指令&#xff0c;将USB的仅充电模式更改成传输文件&#xff08;MTP&#xff09;模式&#xff0c;便捷用户在我的电脑里操作内存文件&#xff0c;下面是我们的常见的修改方式 1、android12以下、android21以上是这种方式…

树莓派,opencv,Picamera2利用舵机云台追踪人脸(PID控制)

一、需要准备的硬件 Raspiberry Pi 4b两个SG90 180度舵机&#xff08;注意舵机的角度&#xff0c;最好是180度且带限位的&#xff0c;切勿选360度舵机&#xff09;二自由度舵机云台&#xff08;如下图&#xff09;Raspiberry CSI 摄像头 组装后的效果&#xff1a; 二、项目目…

Elasticsearch中复制一个索引数据到新的索引中

问题 我有时候&#xff0c;需要调试一个已经存在的ES索引&#xff0c;需要从已有的索引复制数据到新的索引中去。 解决 这里我借助一个GUI工具&#xff0c;来解决这个问题&#xff0c;底层它是使用Reindex的API实现索引数据复制的。利用Reindex API搞不定这个事情&#xff0…

留言板(Mybatis连接数据库版)

目录 1.添加Mybatis和SQL的依赖 2.建立数据库和需要的表 3.对应表中的字段&#xff0c;补充Java对象 4.对代码进行逻辑分层 5.后端逻辑代码 之前的项目实例【基于Spring MVC的前后端交互案例及应用分层的实现】https://blog.csdn.net/weixin_67793092/article/details/134…

是德科技E9304A功率传感器

是德科技E9304A二极管功率传感器测量频率范围为9 kHz至6 GHz的平均功率&#xff0c;功率范围为-60至20 dBm。该传感器非常适合甚低频(VLF)功率测量。E系列E9304A功率传感器有两个独立的测量路径&#xff0c;设计用于EPM系列功率计。功率计自动选择合适的功率电平路径。为了避免…

Centos如何修改ssh端口

想必很大一部分的同学用的是centos服务器&#xff0c;对于默认的22端口存在一定的安全风险&#xff0c;所以今天我们一起看下如何修改ssh端口 一、什么是SSH SSH&#xff08;Secure Shell&#xff09;是一种安全的远程登录协议&#xff0c;它允许您通过网络远程连接到Linux系统…

企业员工2024年工作计划和目标怎么写?怎么提醒自己按时执行?

2024年的钟声即将敲响&#xff0c;对于众多企业员工而言&#xff0c;新的一年意味着新的挑战和机遇。而在这之前&#xff0c;制定一份明确的2024年工作计划与目标就显得尤为重要。但不少员工在面对这个任务时&#xff0c;往往感到无从下手&#xff0c;那么如何撰写一份实用且有…

卖给我这支笔:如何回答最棘手的面试问题之一

在求职面试中&#xff0c;招聘经理有时会递给应聘者一支书写工具并说&#xff1a;“把这支笔卖给我”&#xff0c;从而给他们带来了麻烦。 如果您正在寻找销售工作&#xff0c;最好对这个问题做好准备。对于这个问题有好的方法也有坏的方法&#xff0c;如果你的面试官问到这个…

【线性代数】通过矩阵乘法得到的线性方程组和原来的线性方程组同解吗?

一、通过矩阵乘法得到的线性方程组和原来的线性方程组同解吗&#xff1f; 如果你进行的矩阵乘法涉及一个线性方程组 Ax b&#xff0c;并且你乘以一个可逆矩阵 M&#xff0c;且产生新的方程组 M(Ax) Mb&#xff0c;那么这两个系统是等价的&#xff1b;它们具有相同的解集。这…

软件测试/测试开发丨Python学习笔记之基本数据类型与操作

一、变量 1、变量的定义&#xff1a; a. 在python中&#xff0c;变量是一种存储数据的载体。计算机中的变量是实际存在的数据或者说是存储器中存储数据的一块内存空间&#xff1b; b.变量的值可以被读取和修改。 2、命名规则&#xff1a; a.变量名由字母&#xff08;广义的Unic…

一文详解SpringBoot 定时任务(cron表达式)

IDE&#xff1a;IntelliJ IDEA 2022.2.3 x64 操作系统&#xff1a;win10 x64 位 家庭版 JDK: 1.8 文章目录 一、如何开启一个SpringBoot定时任务&#xff1f;二、cron表达式详解2.1 语法格式2.2 符号解析2,2.1 通用符号: , - * /2.2.2 专有符号&#xff1a;&#xff1f;L w # c…