STM32设置为I2C从机模式

2023-11-05

STM32设置为I2C从机模式

前言

STM32的I2C作为主机的情况相信很多同学都用过,网上也有很多教程,但是作为从设备使用的例子应该不多,本文通过硬件和软件的层面,介绍如何把STM32设置为一个I2C从机。

1 硬件连接

测试芯片:STM32F103ZET6
测试方法:用一个USB转I2C的工具接到STM32的I2C引脚上,通过上位机工具进行读写操作。如果没有这个工具,也可以用另外一个stm32或者其他设备测试通讯,同时也可以借助示波器或者逻辑分析仪来辅助调试。
硬件连接:
STM32这边使用硬件I2C1(PB6、PB7),并外接上拉电阻。
在这里插入图片描述
在这里插入图片描述

2 软件编程

根据STM32数据参考手册,I2C作为从设备时发送和接收的流程如下:
在这里插入图片描述
在这里插入图片描述

测试例程:定义一个256字节的buffer用来存放I2C从机的数据,默认赋初值0-255,然后通过中断的方式实现I2C数据读写。
示例代码如下:

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_i2c.h"
#include "misc.h"

#define I2CSLAVE_ADDR           0x40 << 1  // address is 0x40

#define I2C1_CLOCK_FRQ          100000     // I2C-Frq in Hz (100 kHz)
#define I2C1_RAM_SIZE           256        // RAM Size in Byte

#define I2C1_MODE_WAITING       0          // Waiting for commands
#define I2C1_MODE_SLAVE_ADR_WR  1          // Received slave address (writing)
#define I2C1_MODE_ADR_BYTE      2          // Received ADR byte
#define I2C1_MODE_DATA_BYTE_WR  3          // Data byte (writing)
#define I2C1_MODE_SLAVE_ADR_RD  4          // Received slave address (to read)
#define I2C1_MODE_DATA_BYTE_RD  5          // Data byte (to read)

uint8_t i2c1_mode = I2C1_MODE_WAITING;
uint8_t i2c1_ram_adr = 0;
uint8_t i2c1_ram[I2C1_RAM_SIZE];

uint8_t Get_I2C1_Ram(uint8_t adr) 
{
    return i2c1_ram[adr];
}

void Set_I2C1_Ram(uint8_t adr, uint8_t val) 
{
    i2c1_ram[adr] = val;
    return;
}

void I2C1_Ram_Init(void) 
{
    uint16_t i;
    for (i = 0; i < 256; i++)
    {
        Set_I2C1_Ram(i, i);
    }
}

void I2C1_Slave_Init(void) 
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    /* Configure I2C_EE pins: SCL and SDA */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Configure the I2C event priority */
    NVIC_InitStructure.NVIC_IRQChannel                   = I2C1_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Configure I2C error interrupt to have the higher priority */
    NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
    NVIC_Init(&NVIC_InitStructure);

    /* I2C configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = I2CSLAVE_ADDR;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = I2C1_CLOCK_FRQ;

    /* I2C Peripheral Enable */
    I2C_Cmd(I2C1, ENABLE);

    /* Apply I2C configuration after enabling it */
    I2C_Init(I2C1, &I2C_InitStructure);

    I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE); //Part of the STM32 I2C driver
    I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);
    I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE); //Part of the STM32 I2C driver

    I2C1_Ram_Init();
}

void I2C1_ClearFlag(void) 
{
    /* ADDR Flag clear */
    while((I2C1->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR) 
    {
        I2C1->SR1;
        I2C1->SR2;
    }

    /* STOPF Flag clear */
    while((I2C1->SR1&I2C_SR1_STOPF) == I2C_SR1_STOPF) 
    {
        I2C1->SR1;
        I2C1->CR1 |= 0x1;
    }
}

void I2C1_EV_IRQHandler(void) 
{
    uint8_t wert;
    uint32_t event;

    /* Reading last event */
    event = I2C_GetLastEvent(I2C1);

    /* Event handle */
    if(event == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) 
    {
        // Master has sent the slave address to send data to the slave
        i2c1_mode = I2C1_MODE_SLAVE_ADR_WR;
    }
    else if(event == I2C_EVENT_SLAVE_BYTE_RECEIVED) 
    {
        // Master has sent a byte to the slave
        wert = I2C_ReceiveData(I2C1);
        // Check address
        if(i2c1_mode == I2C1_MODE_SLAVE_ADR_WR) 
        {
            i2c1_mode = I2C1_MODE_ADR_BYTE;
            // Set current ram address
            i2c1_ram_adr = wert;
        }
        else 
        {
            i2c1_mode = I2C1_MODE_DATA_BYTE_WR;
            // Store data in RAM
            Set_I2C1_Ram(i2c1_ram_adr, wert);
            // Next ram adress
            i2c1_ram_adr++;
        }
    }
    else if(event == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) 
    {
        // Master has sent the slave address to read data from the slave
        i2c1_mode = I2C1_MODE_SLAVE_ADR_RD;
        // Read data from RAM
        wert = Get_I2C1_Ram(i2c1_ram_adr);
        // Send data to the master
        I2C_SendData(I2C1, wert);
        // Next ram adress
        i2c1_ram_adr++;
    }
    else if(event == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) 
    {
        // Master wants to read another byte of data from the slave
        i2c1_mode = I2C1_MODE_DATA_BYTE_RD;
        // Read data from RAM
        wert = Get_I2C1_Ram(i2c1_ram_adr);
        // Send data to the master
        I2C_SendData(I2C1, wert);
        // Next ram adress
        i2c1_ram_adr++;
    }
    else if(event == I2C_EVENT_SLAVE_STOP_DETECTED) 
    {
        // Master has STOP sent
        I2C1_ClearFlag();
        i2c1_mode = I2C1_MODE_WAITING;
    }
}

void I2C1_ER_IRQHandler(void) 
{
    if (I2C_GetITStatus(I2C1, I2C_IT_AF)) 
    {
        I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
    }
}

3 运行测试

3.1 I2C连续写入

通过上位机工具写入:
请添加图片描述

通过逻辑分析仪抓取波形:
请添加图片描述

3.2 I2C连续读取

通过上位机工具连续读取256字节:
在这里插入图片描述

通过逻辑分析仪抓取波形:
在这里插入图片描述

在这里插入图片描述

3.3 I2C单次读写测试

通过上位机工具读取原值,再写入新值,最后再读取新值:
请添加图片描述

通过逻辑分析仪抓取波形:
请添加图片描述

4 总结

通过上位机工具的测试以及逻辑分析仪的解析,STM32的硬件I2C从机通信正常且稳定,读写速度测试了100k和400k,没有发现问题,至此测试完成。
好了,关于STM32如何设置从机模式就介绍到这里,如果你们有什么问题,欢迎评论区留言。

需要完整源码工程的同学可以自行下载:源码下载地址
另外还有一篇HAL库版本的博客:STM32设置为I2C从机模式(HAL库版本)

如果这篇文章能够帮到你,就…懂的。
请添加图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32设置为I2C从机模式 的相关文章

  • 为什么C语言没有被C++所取代呢?

    今日话题 为什么C语言没有被C 所取代呢 C 的复杂编译器实现和嵌入式平台的限制 使C语言保持了其地位 嵌入式系统多数仅支持C 即使支持C 也会限制某些功能 尤其是异常处理和RTTI 此外 C 引入的功能增加了二进制文件大小和运行时内存占用
  • 学习STM32正点原子好吗?

    今日话题 学习STM32正点原子好吗 正点原子的教程内容简单明了 代码也清晰直接 使初学者能够轻松理解其功能和使用方法 尤其对于需要快速完成大学作业等任务的大学生来说 可以直接借鉴并稍作修改 便可满足需求 正点原子提供的资料通俗易懂 适合用
  • Win11熄屏,自动断开WiFi解决方法

    一 前言 由于 我需要使用自己的电脑 远程连接服务器跑代码 电脑息屏之后 wifi断开 代码也就自动停止了 非常生气 二 解决办法 网上的办法很多都是win10 而且别人的都有电源管理 而我的没有 下面是别人的 这是我的 就是没有电源管理
  • 【性能测试入门】:压力测试概念!

    压力测试可以验证软件应用程序的稳定性和可靠性 压力测试的目标是评估软件在极端负载条件下的鲁棒性和错误处理能力 并确保软件在紧急情况下不会崩溃 它甚至可以进行超出软件正常工作条件的测试 并评估软件在极端条件下的工作方式 在软件工程中 压力测试
  • 处理不舒服的同事关系:实用建议与技巧

    处理不舒服的同事关系 实用建议与技巧 在工作中 我们难免会遇到一些与同事关系不和谐的情况 这些不舒服的关系可能会影响到我们的工作情绪和效率 那么 如何处理这些不舒服的同事关系呢 本文将为你提供一些实用的建议 一 保持冷静和理智 在处理同事关
  • 魏副业而战:小红书AI漫画副业项目

    我是魏哥 与其躺平 不如魏副业而战 今天魏哥给大家分享一个小红书AI漫画副业项目 大家都知道小红书上用户80 以上都是女性 而我们今天的项目主要利用AI生成的漫画宝宝图片来吸引宝妈用户 这个项目操作简单 适合宝妈 或有空闲时间的小伙伴 我们
  • Windows IoT 和 DS3231 RTC 时钟

    对于我的项目 我需要当前时间和日期 不幸的是 当 RP2 关闭时 它就会失去一切 接下来的事情是 我将没有互联网连接来使用 NTP 为此 我需要实现 DS3231 RTC 模块 所有设备的通信都通过 I2C 运行 Raspberry Ard
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • 基于信号完整性的PCB设计原则

    最小化单根信号线质量的一些PCB设计建议 1 使用受控阻抗线 2 理想情况下 所有信号都应该使用完整的电源或地平面作为其返回路径 关键信号则使用地平面作为返回路径 3 信号的返回参考面发生变化时 在尽可能接近信号换层孔的位置增加至少一个返回
  • 图片编辑软件有哪些好用的?这几款快收藏吧

    你有没有过这样的经历 精心拍摄了一组照片 却发现有些角度不对 光线不够好 或者想要给图片加上一些特别的滤镜效果来达到心目中的样子 这时 你就需要一款合适的图片编辑软件了 但是 市面上的图片编辑软件琳琅满目 哪一款才是适合自己的呢 别担心 今
  • 2024最新MathType7.4.10中文版下载安装激活教程

    MathType 是一款专业的数学公式编辑工具 提供交互式编辑器 让你在编辑数学试卷 书籍 报刊 论文 幻灯演示等文档轻松输入各种复杂的数学公式和符号 1 本次讲解mathtype 7版本的安装步骤 MathType2024 Win 安装包
  • 如何正确下载激活NTFS for Mac2024最新版本?

    对于产品来说 更新换代是常有的事 很多软件在用户使用过后 会根据用户的使用需求以及一些客观需求 将软件进行改进 这样一个新的版本的软件就会出现 用户需要将软件进行更新才能享受最新的功能 使用更加完善的软件 所以我们一定要学会如何将软件进行更
  • AI新年头像模板在哪找?告别单调头像的工具分享

    农历新年到啦 今年的春节假期你有没有弄一些氛围装饰呀 除了每年都有的对联 福字等 经典皮肤 现在也流行起给自己的账号营造一些过年的感觉啦 说到这个 很多人第一反应就是给自己换个新年头像 限定皮肤 不过头像要怎么营造新年的感觉呢 其实用AI工
  • 是什么让 SPI 比 I2C 协议更快 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我了解 I2C 和 SPI 通信的基础知识 因为两者都是同步协议 我想知道是什么让 SPI 比 I2C 更快 如果我没记错的话 使用 I2
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • MCP23017 I2C 设备驱动程序探测函数未调用

    我正在使用以下 I2C GPIO设备驱动 https github com torvalds linux blob master drivers gpio gpio mcp23s08 c访问 MCP23017 GPIO 使用 insmod
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • Linux、ARM:为什么仅当启动时存在 I2C GPIO 扩展器时才创建 gpiochip

    在 imx6sx 硬件平台 NXP 嵌入式 ARM 上使用 Linux 3 14 52 问题是设备树中指定的 PCF8575 I2C GPIO 扩展器不会实例化为 sys class gpio 结构中的设备 除非它们在内核启动期间存在 这些

随机推荐

  • 全局监控 click事件的四种方式

    本文主要给大家分享如何在全局上去监听 click 点击事件 并做些通用处理或是拦截 使用场景可能就是具体的全局防快速重复点击 或是通用打点分析上报 用户行为监控等 以下将以四种不同的思路和实现方式去监控全局的点击操作 由简单到复杂逐一讲解
  • Linux学习笔记-----网络编程套接字

    目录 一 概念 一 端口号概念 二 套接字概念 三 套接字 socket 编程接口 四 sockaddr结构 五 网络字节序 二 基于UDP的相关理解 一 UDP协议 二 编写简单的UDP服务端和客户端 三 小结 三 基于TCP的相关理解
  • iOS 自动构建命令——xcodebuild

    想想当初天天来到公司 每天需要做一件事就是打开Xcode打包ipa 上传到fir 日复一日月复一月年复一年的做着同样的事情 作为有志成为优秀工程师的我来说 这是必须要解决的问题 所以决定自动化解决问题 简介 xcodebuild 是苹果发布
  • Qt环境变量配置

    在桌面找到 此电脑 右击 找到属性 点击属性 找到高级系统设置 点击 选中环境变量 选中path 点击编辑 进入环境变量是这个样子的 下一步找到Qt安装的位置复制路径 这个是2015 64的 2015 32和2017 64的路径都要 然后
  • 如何选择期权品种,是做期货期货还是做期权

    有朋友问 国内的疫情目前得到较好的控制 经济也在逐渐恢复运行 国外的疫情在加重 也许会有部分国家经济做阶段停摆 假如上面的成立 我们是不是可以选择一种套利 买入国内经济需求会带动上涨的商品 卖出国外经济下滑会带动下跌的商品 如果这个方案可行
  • 分布式系统下的纠删码技术(一) -- Erasure Code (EC)

    近几个月主要参与一个分布式存储系统的纠删码部分 用于数据容错 纠删码在学术界出现比较早 现在ceph 微软的存储系统 Hadoop 3 0等都用了EC 文章会分为多篇 主要将Erasure Code LRC 以及相关的数学基础 作为学习总结
  • 前端技术搭建贪吃蛇小游戏(内含源码)

    功能介绍 以下是贪吃蛇小游戏的玩法和规则 游戏开始时 玩家控制一条小蛇在游戏区域内移动 通过吃食物来增加分数 小蛇的移动方向由玩家控制 可以使用键盘上的方向键来控制小蛇的移动方向 当小蛇吃到食物时 它会变长 并且玩家的分数会增加 如果小蛇撞
  • 拷贝构造函数(默认的,自定义的,什么时候一定要自定义,什么时候系统会自动调用)

    为什么有指针成员的类 要自定义拷贝构造函数 参考了 https blog csdn net caoshangpa article details 79226270 没有拷贝构造函数的类 系统会创建默认的拷贝构造函数 默认拷贝构造函数是浅拷贝
  • 【JSON 初级】

    概述 前后台数据交换的格式标准 一种优秀的 数据格式 采用键值对的方式 取数据 用键 优势 比XML更小 更快 更容易解析 JSON是存储和交换文本信息的语法 类似XML 工具 网上有校验json数据 并提示错误 将数据转化为json数据
  • 深入理解java虚拟机【并发编程缓存】

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 随着多核CPU的高速发展 为了充分利用硬件的计算资源 操作系统的并发多任务功能正变得越来越重要 但是CPU在进行计算时 还需要从内存读取输出 并 将计算结果存放到内存中 然
  • 【华为OD机试】分苹果(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • 闲聊:自动化到底是干什么的?

    很多人会问 自动化到底是干什么的 也许是因为这个专业所要学习和掌握的知识太庞杂了 以至于自动化被称之为万能胶 干什么都行 却又都不专业 很大一部分同学上到大二大三还不知道自己具体能做什么 迷茫中便选择了转行 希望还在迷茫中的低年级的同学看了
  • C++11变长模板解析(深入理解C++11)

    参考自 深入理解C 11 变长模版 变长函数和变长的模版参数 变长函数 double sum int n 求n个double数据之和 double sum 0 va list args 接受输入数据的数据结构 需声明stdarg h va
  • 3D游戏设计作业9:游戏智能

    坦克对战游戏 AI 设计 游戏截图 1 作业要求 从商店下载游戏 Kawaii Tank 或 其他坦克模型 构建 AI 对战坦克 具体要求 使用 感知 思考 行为 模型 建模 AI 坦克 场景中要放置一些障碍阻挡对手视线 坦克需要放置一个矩
  • python 点名程序(随机点名不重复 可定义名字列表 语音播报 免费下载 多线程打包)

    python点名小程序 含有 调用windows本地语音播报 python多线程打包 等小技巧 软件获取 点击下方地址直接下载压缩包 免费为大家提供 软件获取地址 大家拿了软件别忘了给博主一个免费的赞 谢谢 解压压缩包 里面的MyAPP e
  • 配置和美化Arch Linux

    前面说了如何安装一个最小化的Arch Linux 现在来说说如何配置 配置网络 如果使用有线网络的话 将dhcp服务开机启动 systemctl enable dhcpcd 如果使用无线网络的话 使用wifi menu命令连接网络 如果在使
  • Base64图片上传

    文章目录 1 图片上传样式写法 2 Js写法 1 图片上传样式写法 div class form group div
  • python+OpenCV图像处理(五)图像的阈值分割

    图像的阈值处理 一幅图像包括目标物体 背景还有噪声 要想从多值的数字图像中直接提取出目标物体 常用的方法就是设定一个阈值T 用T将图像的数据分成两部分 大于T的像素群和小于T的像素群 这是研究灰度变换的最特殊的方法 称为图像的二值化 Bin
  • 分号与逗号的区别及举例_顿号与逗号与分号间的区别是什么?

    逗号把句子切分为意群 表示小于分号大于顿号的停顿 而逗号有哪些用法呢 以下是由小编整理关于逗号如何使用的内容 希望大家喜欢 逗号汉语用法句子内部主语与谓语之间如需停顿 用逗号 例如 我们看得见的星星 绝大多数是恒星 句子内部动词与宾语之间如
  • STM32设置为I2C从机模式

    STM32设置为I2C从机模式 目录 STM32设置为I2C从机模式 前言 1 硬件连接 2 软件编程 3 运行测试 3 1 I2C连续写入 3 2 I2C连续读取 3 3 I2C单次读写测试 4 总结 前言 STM32的I2C作为主机的情