和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

相关文章

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

如何用java对接微信小程序下单后的发货接口

《如何用java对接微信小程序下单后的发货接口》:本文主要介绍在微信小程序后台实现发货通知的步骤,包括获取Access_token、使用RestTemplate调用发货接口、处理AccessTok... 目录配置参数 调用代码获取Access_token调用发货的接口类注意点总结配置参数 首先需要获取Ac

讯飞webapi语音识别接口调用示例代码(python)

《讯飞webapi语音识别接口调用示例代码(python)》:本文主要介绍如何使用Python3调用讯飞WebAPI语音识别接口,重点解决了在处理语音识别结果时判断是否为最后一帧的问题,通过运行代... 目录前言一、环境二、引入库三、代码实例四、运行结果五、总结前言基于python3 讯飞webAPI语音

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学