STM32 I2C驱动开发全解析:从理论到实战 | 零基础入门STM32第五十步

主题内容教学目的/扩展视频
I2C总线电路原理,跳线设置,I2C协议分析。驱动程序与调用。熟悉I2C总线协议,熟练调用。

师从洋桃电子,杜洋老师


📑文章目录

    • 引言
    • 一、I2C驱动分层架构
    • 二、I2C总线驱动代码精析
      • 2.1 初始化配置(i2c.c)
      • 2.2 数据发送函数(I2C_SAND_BUFFER)
      • 2.3 数据接收函数(I2C_READ_BUFFER)
    • 三、总线速度配置原理
    • 四、用户应用实战(main.c)
    • 五、器件驱动开发(LM75A示例)
      • 5.1 温度读取函数
    • 六、常见问题排查指南
    • 七、进阶优化技巧
    • 八、相关资源
    • 总结


▲ 回顾上期🔍STM32入门之I2C总线应用详解(附LM75A温度传感器实战) | 零基础入门STM32第四十九步


引言

I2C总线是嵌入式系统中广泛使用的通信协议,具有接线简单、多设备共享总线等优点。本文将深入解析STM32的I2C驱动开发,通过分层架构设计代码逐行分析实战案例演示,帮助开发者快速掌握I2C通信的核心技术。


一、I2C驱动分层架构

用户应用层 main.c
器件驱动层 LM75A
总线驱动层 i2c.c
硬件抽象层 stm32f10x_i2c.c
硬件寄存器
  1. 硬件抽象层(HAL)
    ST官方提供的固件库(如stm32f10x_i2c.c),直接操作寄存器实现基础功能。
  2. 总线驱动层
    封装I2C协议的核心操作(发送/接收数据),提供I2C_Configuration()等接口。
  3. 器件驱动层
    针对具体外设(如LM75A温度传感器)的驱动实现。
  4. 用户应用层
    调用驱动函数实现业务逻辑,如温度显示。

二、I2C总线驱动代码精析

2.1 初始化配置(i2c.c)

void I2C_Configuration(void) {// GPIO配置:SCL=PB6, SDA=PB7GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;  // 复用开漏模式GPIO_Init(GPIOB, &GPIO_InitStruct);// I2C参数配置I2C_InitStruct.I2C_ClockSpeed = 100000;       // 100kHz标准模式I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 时钟占空比I2C_Init(I2C1, &I2C_InitStruct);I2C_Cmd(I2C1, ENABLE);                        // 使能I2C
}
  • 关键点
    • GPIO必须配置为复用开漏模式(支持总线仲裁)
    • 时钟速度需匹配从机设备(如LM75A支持400kHz)

2.2 数据发送函数(I2C_SAND_BUFFER)

void I2C_SAND_BUFFER(u8 SlaveAddr, u8 WriteAddr, u8* pBuffer, u16 NumByteToWrite) {I2C_GenerateSTART(I2C1, ENABLE);              // 发送起始信号while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // 等待EV5I2C_Send7bitAddress(I2C1, SlaveAddr, I2C_Direction_Transmitter); // 发送设备地址while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 等待EV6I2C_SendData(I2C1, WriteAddr);                // 发送寄存器地址while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 等待EV8while(NumByteToWrite--) {                     // 循环发送数据I2C_SendData(I2C1, *pBuffer++);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));}I2C_GenerateSTOP(I2C1, ENABLE);               // 发送停止信号
}
  • 协议流程
    1. 起始信号 → 2. 发送地址+写方向 → 3. 发送寄存器地址 → 4. 发送数据 → 5. 停止信号

2.3 数据接收函数(I2C_READ_BUFFER)

MCU Slave START + 设备地址(写) 寄存器地址 REPEATED START + 设备地址(读) 数据字节1 (ACK) 数据字节2 (NACK) STOP MCU Slave

三、总线速度配置原理

i2c.h中定义总线速率:

#define BusSpeed 200000  // 200kHz
  • 计算公式

SCL频率 = APB1时钟频率 2 × ( I2C_ClockSpeed + 1 ) \text{SCL频率} = \frac{\text{APB1时钟频率}}{2 \times (\text{I2C\_ClockSpeed} + 1)} SCL频率=2×(I2C_ClockSpeed+1)APB1时钟频率

  • 注意事项
    • APB1时钟需在初始化时正确配置(默认为36MHz)
    • 实际速率可通过示波器测量SCL引脚验证

四、用户应用实战(main.c)

int main(void) {u8 tempData[3];I2C_Configuration();          // 初始化I2CTM1640_Init();                // 初始化显示模块while(1) {LM75A_GetTemp(tempData);  // 读取温度// 显示温度值(示例代码略)delay_ms(200);            // 控制采样频率}
}
  • 调用链
    main()LM75A_GetTemp()I2C_READ_BUFFER() → 硬件寄存器操作

五、器件驱动开发(LM75A示例)

5.1 温度读取函数

void LM75A_GetTemp(u8 *Tempbuffer) {u8 rawData[2];I2C_READ_BUFFER(LM75A_ADD, 0x00, rawData, 2); // 读取原始数据// 数据解析(示例)int16_t temp = (rawData[0] << 8) | rawData[1];temp = temp >> 5;  // 有效数据为11位*Tempbuffer = temp * 0.125;  // 转换为实际温度值
}
  • 关键参数
    • LM75A_ADD = 0x9E(包含R/W位)
    • 温度数据为16位(高11位有效)

六、常见问题排查指南

现象可能原因解决方案
总线无响应1. 硬件连接错误检查SCL/SDA上拉电阻(4.7kΩ)
数据校验失败2. 时序不匹配降低时钟速度或调整延时
重复地址冲突3. 从机地址配置错误使用I2C扫描工具检测设备地址

七、进阶优化技巧

  1. DMA传输
    使用DMA减少CPU占用:
    I2C_DMACmd(I2C1, I2C_DMAReq_Tx | I2C_DMAReq_Rx, ENABLE);
    
  2. 错误恢复机制
    检测总线忙状态时自动复位:
    if(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) {I2C_SoftwareResetCmd(I2C1, ENABLE);I2C_SoftwareResetCmd(I2C1, DISABLE);
    }
    

八、相关资源

[1] 洋桃电子B站课程-STM32入门100步
[2] STM32F103xx官方数据手册
[3] STM32F103X8-B数据手册(中文)
[4] STM32F103固件函数库用户手册(中文)
[5] I2C总线规范(中文)
[6] LM75(温度传感器)数据手册+编程说明+应用
[7] 温度传感器数码管显示程序
[8] I2C驱动程序分析.pptx


总结

本文从STM32的I2C驱动架构出发,详细解析了总线初始化、数据收发和速度配置的实现原理,并结合LM75A温度传感器展示了实际应用场景。掌握以下核心要点:

  1. 分层架构设计提升代码可维护性
  2. 严格遵循I2C协议时序
  3. 合理配置总线速率匹配外设
  4. 善用调试工具(如逻辑分析仪)验证通信波形

通过理论结合实践的方式,开发者能够快速构建稳定可靠的I2C通信系统。


💬 技术讨论(请在评论区留言~)

📌 下期预告:下一期将探讨LM75A驱动程序分析,欢迎持续关注!

点击查阅🔍往期【STM32专栏】文章

版权声明:本文采用[CC BY-NC-SA 4.0]协议,转载请注明来源
实测开发版:洋桃1号开发版(基于STM32F103C8T6)
更新日志

  • v1.0 初始版本(2025-03-07)

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

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

相关文章

练习-纪律问题(幂运算)

问题描述 一年级一班有 n 个小朋友坐成一排&#xff0c;统计了这些小朋友的爱好后&#xff0c;老师得知了他们一共有 m 种爱好&#xff0c;每个小朋友会拥有这些爱好中的一种。 如果相邻的小朋友爱好相同&#xff0c;那么他们上课时就会忍不住悄悄说话&#xff0c;违反课堂纪…

《基于机器学习的DDoS攻击检测与防御系统设计与实现》开题报告

目录 一、课题的研究目的和意义 1.1课题背景 1.2课题目的 &#xff08;1&#xff09;提高DDoS攻击检测的准确性 &#xff08;2&#xff09;加强DDoS攻击的防御能力 &#xff08;3&#xff09;提升网络安全防护的技术水平 1.3课题意义 &#xff08;1&#xff09;理论意义…

【Java项目】基于JSP的幼儿教育管理系统

【Java项目】基于JSP的幼儿教育管理系统 技术简介&#xff1a;采用JSP技术、B/S结构、MYSQL数据库等实现。 系统简介&#xff1a;幼儿教育管理系统&#xff0c;主要的模块包括查看&#xff1b;管理员&#xff1b;个人中心、用户管理、学生信息管理、班级信息管理、缴费信息管理…

如何将本地已有的仓库上传到gitee (使用UGit)

1、登录Gitee。 2、点击个人头像旁边的加号&#xff0c;选择新建仓库&#xff1a; 3、填写仓库相关信息 4、复制Gitee仓库的地址 5、绑定我们的本地仓库与远程仓库 6、将本地仓库发布&#xff08;推送&#xff09;到远程仓库&#xff1a; 注意到此处报错&#xff…

限制数据库字段长度的公用写法:length和like和rlike对于限制字段长度的原理与区别

关于数据库字段长度的探索: length和like和rlike对于限制字段长度的原理与区别lengthlike、rlikelike的_下划线通配符rlike的正则表达式regexp、regexp_like的正则表达式 length和like和rlike对于限制字段长度的原理与区别 探索之前先简单介绍下&#xff1a; length函数可以返…

LabVIEW cRIO中CSV文件的读取

在LabVIEW cRIO中读取CSV文件&#xff0c;需通过文件传输、路径配置、数据解析等步骤实现。本文详细说明如何通过代码读取本地存储的CSV文件&#xff0c;并探讨直接通过对话框选择文件的可行性及替代方案。 一、CSV文件传输至cRIO本地存储 1. 使用NI MAX文件管理 步骤&#xf…

DeepSeek-R1 论文阅读总结

1. QA问答&#xff08;我的笔记&#xff09; Q1: DeepSeek如何处理可读性问题&#xff1f; 通过构建冷启动数据&#xff08;数千条长CoT数据&#xff09;微调基础模型&#xff0c;结合多阶段训练流程&#xff08;RL训练、拒绝采样生成SFT数据&#xff09;&#xff0c;并优化输…

prometheus的动态发现(基于文件和consul)

prometheus的配置参考&#xff1a;https://prometheus.io/docs/prometheus/2.53/configuration/configuration/ 没有使用动态配置前&#xff0c;需要在 prometheus.yml 这个配置文件中创建数据采集任务&#xff0c;然后重新加载服务。 如果把采集job剥离出去&#xff0c;写在…

安卓逆向魔改版 Base64 算法还原

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 目标 app 简介 可以看到 app 中共有 4 种 Base64 算法。选中一个随机字符串&#xff0c;可以选择其中一种算法进行编码解码。 app地址&#xff1a;https://gi…

CI/CD—GitLab部署

GitLab简介&#xff1a; GitLab 是一个用于代码托管和软件开发协作的平台&#xff0c;在全球开发者社区及企业中应用广泛&#xff0c;以下是对它的详细介绍&#xff1a; 主要功能 代码托管&#xff1a;提供了基于 Git 的代码仓库管理功能&#xff0c;支持创建、克隆、推送、…

采集OPCUA/S7

需求&#xff1a;采集OPCUA服务数据 采用&#xff1a;KEPServerEX6获取OPCUA服务数据 1.新建甬道3 2.驱动程序选择&#xff1a;OPC UA client 3.设置UA服务器-端点URL&#xff1a;opc.tcp://ip:502 安装教程&#xff1a;https://blog.csdn.net/weixin_41425107/article/detai…

3.12代码随想录第十五天打卡

654.最大二叉树 (1)题目描述: (2)解题思路: class Solution { public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {TreeNode* node new TreeNode(0);if (nums.size() 1) {node->val nums[0];return node;}// 找到数组中最大的值和对应的下标…

安全左移动赋能:灵脉IAST交互式应用安全测试平台

左移的安全赋能 Earlier Security Empowerment 悬镜灵脉IAST灰盒安全测试平台作为国内领先的交互式应用安全测试平台&#xff0c;透明集成于现有IT流程&#xff0c;自动化完成业务代码上线前安全测试&#xff0c;重点覆盖90%以上中高危漏洞&#xff0c;防止应用带病上线&…

Linux下学【MySQL】常用函数助你成为数据库大师~(配sql+实操图+案例巩固 通俗易懂版~)

绪论​ 每日激励&#xff1a;“唯有努力&#xff0c;才能进步” 绪论​&#xff1a; 本章是MySQL中常见的函数&#xff0c;利用好函数能很大的帮助我们提高MySQL使用效率&#xff0c;也能很好处理一些情况&#xff0c;如字符串的拼接&#xff0c;字符串的获取&#xff0c;进制…

波特率、比特率、传信率、传码率......

去年搞过一段时间的无线通信&#xff0c;当时我脑子里真的是一团乱麻&#xff0c;本身咱也不是学通信的&#xff0c;咱是学机械出身的&#xff0c;后面又搞电&#xff0c;反正对于通信这一块就不是很懂&#xff0c;后面也慢慢搞出来了一点小东西&#xff0c;但是对于一些细节还…

华为HCIE认证用处大吗?

新盟教育 专注华为认证培训十余年 为你提供认证一线资讯&#xff01; 在ICT行业的认证体系中&#xff0c;华为HCIE认证一直备受关注。那么&#xff0c;华为HCIE认证用处大吗&#xff1f;今天咱们就来深入探讨一下&#xff0c;以数据通信方向为例&#xff0c;看看它到底能带来什…

【WRF-Chem】预处理工具(Preprocessors)总结

WRF-Chem 预处理工具&#xff08;Preprocessors&#xff09; 化学选项&#xff08;Chemistry Options&#xff09;数据下载 预处理工具&#xff08;Preprocessors&#xff09;工具1&#xff1a;mozbc工具2&#xff1a;bio_emiss工具3&#xff1a;anthro_emiss工具4&#xff1a;…

六、OpenGL中EBO的使用及本质

文章目录 一、什么是顶点索引二、什么是EBO三、EBO使用的完整代码 一、什么是顶点索引 OpenGL 中&#xff0c;顶点索引&#xff08;Vertex Index&#xff09;用于减少重复的顶点数据&#xff0c;提高绘制效率。其核心概念涉及索引缓冲对象&#xff08;Index Buffer Object&…

Python+jupyter进行数据分析与数据挖掘

随着人工智能的发展&#xff0c;现在越来越多人使用Python语言进行数据分析。Python在数据分析中有哪些优势呢&#xff1f;由于Python中有很多的第三方插件&#xff0c;接下来我们探讨Pythonjupyter的结合&#xff0c;在数据分析领域中的应用。 一、jupyter介绍 Jupyter 是一个…

AI4CODE】3 Trae 锤一个贪吃蛇的小游戏

【AI4CODE】目录 【AI4CODE】1 Trae CN 锥安装配置与迁移 【AI4CODE】2 Trae 锤一个 To-Do-List 这次还是采用 HTML/CSS/JAVASCRIPT 技术栈 Trae 锤一个贪吃蛇的小游戏。 1 环境准备 创建一个 Snake 的子文件夹&#xff0c;清除以前的会话记录。 2 开始构建 2.1 输入会…