和STM32的I2C接口搏击道路1

2024-01-02 00:30
文章标签 接口 stm32 道路 i2c 搏击

本文主要是介绍和STM32的I2C接口搏击道路1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  1. 一直使用STM32进行开发,对项目进行开发的过程中对I2C接口很常用到。平常在使用I2C过程中基本都是使用IO口直接模拟I2C。不过在使用软件I2C过程中可能会面临着达不到400k的速率。因此想趁着使用I2C器件的过程中使用硬件I2C。在调试的过程中,终于明白了大家为什么直接使用软件模拟I2C。因为硬件在使用过程中确实有点麻烦。
  2. 平常在对STM32的片内外设进行初始化的时候喜欢直接操作寄存器,主要原因是觉得对寄存器操作能够对该资源的运转有个质的把控。在使用库函数或者HAL库的时候总觉得隔着一层面纱不能真正对资源进行把控。因此,在对I2C进行调试的时候,依旧采用了寄存器操作来初始化硬件。
  3. 通过查看STM32F103RCT6的原理图,看到I2C的功能是复用在PB6,PB7上。因此在初始化的时候需要先对PB6,PB7进行复用初始化。这里要注意一点,I2C的管脚复用时为开漏推挽输出。因为I2C协议支持多个主设备与多个从设备在一条总线上,如果不用开漏输出,而采用推挽输出,会出现主设备之间短路的情况,因此要为开漏输出。而且I2C的片外器件要接上拉电阻。这里采用的I2C器件为MAX30101,如图1所示。该小开发板在板子上已经接了上拉电阻。
    图1 MAX30101开发板
  4. 硬件准备好后就需要进行软件的编写,这时候需要根据操作手册进行时序的编写。首先是关于I2C的初始化。在《STM32中文参考手册》中对I2C在主模式的操作顺序如图2所示。
    图2 对I2C主模式的操作时序说明
  5. 按照说明进行操作时,内想到初始化后一直不成功,进行断点调试发现在初始化后I2C的SR2寄存器的BUSY位一直是1,这说明总线一直被占用。但是这明显是不对的,没有数据“住在”总线的时候,总线竟然呈现着“被占用”的状态。刚开始逐行查找初始化的语句并没有发现错误。代码如下所示:
/*
*Description :I2C初始化,这里配置为100khz的普通模式
*Param       :None
*Return Code :None
*/
void I2C_Init(void)
{   RCC->APB2ENR|=1<<3;        //PORTB是专用使能RCC->APB1ENR|=1<<21;       //I2C1时钟使能GPIOB->CRL|=0X00FFFFFF;    //GPIOB6,7复用为开漏输出GPIOB->CRL|=0XFF000000;    //GPIOB6,7复用为开漏输出
//	GPIOB->CRL|=0XFF000000;    //GPIOB6,7复用为开漏输出GPIOB->ODR|=1<<6;GPIOB->ODR|=1<<7;I2C1->CR2|=0X24;           //0X02 2MHZ-0X24 36MHZ, 0X14 20MHZ,0X08I2C1->CCR|=0XB4;I2C1->TRISE&=0X0000;I2C1->TRISE|=0X25;I2C1->OAR1|=1<<14;         //在这里将该位用软件设置为1I2C1->OAR1|=0X0A;          //写入从机地址I2C1->CR1|=1<<10;          //使能I2C模式I2C1->CR1|=1<<0;           //使能I2C模式
}
  1. 单步调试如图3所示

图3 单步调试结果图

  1. 从代码分析刚开始确实没查找出错误,首先对PB6,PB7的操作来看,最终确实是配置成了开漏复用输出,对I2C的寄存器操作确实是都写进去了,但是SR2的BUSY位还是为1.表示总线处在繁忙的状态。查找无果。
  2. 既然寄存器一直走不通,何不采用库函数来配置一下。对I2C进行配置。然后查看SR2状态寄存器是否依旧是busy状态。采用库函数的配置程序如下
/*
*Description:MAX30101初始化
*Param      :None
*Return Code:None
*/
void max30102_init(void)
{  /*对端口进行初始化*/GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);           //打开PORTB口的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);            //打开I2C1的端口GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;                  //开漏复用输出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;                        //SCLGPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;                        //SDAGPIO_Init(GPIOB,&GPIO_InitStructure);/*对I2C进行初始化*/I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;                       //设置为I2C模式I2C_InitStructure.I2C_OwnAddress1=0X0A;                        //自己的地址I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000;I2C_Init(I2C1,&I2C_InitStructure);I2C_Cmd(I2C1,ENABLE);                                          //使能I2C1
}
  1. 使用库函数对I2C配置如图4所示。图4 使用库函数对I2C进行初始化
  2. 可以看出采用库函数初始化I2C的SR2状态位不是处于BUSY状态,这说明配置步骤没有问题。问题应该还是出在寄存器配置端口这里。重新返回事故现场进行调试。发现在执行第14行代码的时候。SR2寄存器的BUSY位就会进入置1的状态。结果如图5所示。因为学习的板子一直是参考正点原子的例程,因此习惯了先&后|对GPIO的寄存器进行操作。当然也不是说正点原子的例程有错误,只是在这时候执行第14行代码再执行第15行代码确实将PB6,PB7配置成了开漏输出,但是这个过程是先配置为模拟输入然后再配置成了开漏输出。这样实质是没有对PB6,PB7完成开漏配置。
    图5 单步调试现场图
  3. 跳过GPIO->CRL&=0X00FFFFFF;这个步骤,直接执行GPIO->CRL|=0XFF000000,在进行调试,发现事故不在发生。结果如图6所示。从结果中可以看出,I2C的SR2寄存器没有处在BUSY状态,对PB6,PB7的配置也是开漏输出。图6 更改后调试结果图
  4. 至此,刚走过初始化的部分。初始化中唯一一个坑就是对PB6,PB7的推挽输出复用功能时的寄存器配置。

这篇关于和STM32的I2C接口搏击道路1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/560901

相关文章

SpringBoot+Redis防止接口重复提交问题

《SpringBoot+Redis防止接口重复提交问题》:本文主要介绍SpringBoot+Redis防止接口重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录前言实现思路代码示例测试总结前言在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。例

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Java中的Closeable接口及常见问题

《Java中的Closeable接口及常见问题》Closeable是Java中的一个标记接口,用于表示可以被关闭的对象,它定义了一个标准的方法来释放对象占用的系统资源,下面给大家介绍Java中的Clo... 目录1. Closeable接口概述2. 主要用途3. 实现类4. 使用方法5. 实现自定义Clos

java对接第三方接口的三种实现方式

《java对接第三方接口的三种实现方式》:本文主要介绍java对接第三方接口的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录HttpURLConnection调用方法CloseableHttpClient调用RestTemplate调用总结在日常工作

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

Java对接Dify API接口的完整流程

《Java对接DifyAPI接口的完整流程》Dify是一款AI应用开发平台,提供多种自然语言处理能力,通过调用Dify开放API,开发者可以快速集成智能对话、文本生成等功能到自己的Java应用中,本... 目录Java对接Dify API接口完整指南一、Dify API简介二、准备工作三、基础对接实现1.

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及