和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

相关文章

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu