STM32入门教程:I2C通信

I2C(Inter-Integrated Circuit)是一种广泛使用的串行通信接口标准,可用于连接微控制器和外部设备。在本教程中,我们将详细介绍如何在STM32微控制器上使用I2C通信。我们将从基础知识开始,并提供具体的代码案例来演示如何使用I2C进行数据传输。

一、I2C基础知识 I2C使用两根线(SDA和SCL)进行通信,其中SDA是数据线,SCL是时钟线。I2C通信中有两个主要角色:主设备和从设备。主设备负责发起通信并控制总线上的数据传输,而从设备负责接收主设备发送的数据。

I2C通信中每个设备都有一个唯一的地址,主设备通过发送设备地址来选择所要通信的从设备。在传输数据时,主设备发送起始信号(Start)和停止信号(Stop)来标识通信的开始和结束。数据传输过程中,每个字节的数据都由8个位组成,其中最高位是读写位,指示是读取还是写入操作。

二、STM32上的I2C配置 在STM32上使用I2C通信需要进行一些配置工作。首先,我们需要启用对应的GPIO和I2C模块的时钟。其次,我们需要配置GPIO引脚的模式和速度,以及I2C的时钟频率和地址。

  1. 启用GPIO和I2C模块的时钟
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;   // 启用GPIOB的时钟
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;  // 启用I2C1的时钟

  1. 配置GPIO引脚的模式和速度
GPIOB->MODER &= ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7);  // 清除GPIOB6和GPIOB7的模式位
GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);  // 配置GPIOB6和GPIOB7为复用模式
GPIOB->AFR[0] &= ~(GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7);  // 清除GPIOB6和GPIOB7的复用位
GPIOB->AFR[0] |= (4 << GPIO_AFRL_AFRL6_Pos) | (4 << GPIO_AFRL_AFRL7_Pos);  // 配置GPIOB6和GPIOB7的复用为I2C1
GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);  // 配置GPIOB6和GPIOB7为开漏输出
GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7);  // 配置GPIOB6和GPIOB7的输出速度为高速
GPIOB->PUPDR |= (GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR7_0);  // 配置GPIOB6和GPIOB7的上拉电阻

  1. 配置I2C的时钟频率和地址
I2C1->CR2 |= (16 << I2C_CR2_FREQ_Pos);  // 配置I2C1的时钟频率为16MHz
I2C1->CR1 |= I2C_CR1_PE;  // 使能I2C1
I2C1->OAR1 |= (0x01 << 1);  // 配置I2C1的从设备地址为0x01
I2C1->CR1 |= I2C_CR1_ACK;  // 使能I2C1的应答功能

三、I2C数据传输 在STM32上使用I2C进行数据传输需要遵循一定的顺序。首先,我们需要发送起始信号(Start)来表示通信的开始。然后,我们发送设备地址,并指定是读取还是写入操作。接下来,我们可以发送或接收一系列的数据字节。最后,我们发送停止信号(Stop)来表示通信的结束。

下面是使用I2C读取外部设备的示例代码:

void I2C_Start(void) {
    I2C1->CR1 |= I2C_CR1_START;  // 发送起始信号
    while (!(I2C1->SR1 & I2C_SR1_SB));  // 等待起始信号发送完成
}

void I2C_Stop(void) {
    I2C1->CR1 |= I2C_CR1_STOP;  // 发送停止信号
    while (I2C1->SR2 & I2C_SR2_MSL);  // 等待停止信号发送完成
}

void I2C_Write(uint8_t data) {
    I2C1->DR = data;  // 写入数据
    while (!(I2C1->SR1 & I2C_SR1_TXE));  // 等待数据发送完成
}

uint8_t I2C_Read(void) {
    while (!(I2C1->SR1 & I2C_SR1_RXNE));  // 等待数据接收完成
    return I2C1->DR;  // 读取接收到的数据
}

void I2C_SendAddress(uint8_t address) {
    I2C1->DR = address;  // 发送设备地址和读写位
    while (!(I2C1->SR1 & I2C_SR1_ADDR));  // 等待设备地址发送完成
    (void) I2C1->SR2;  // 清除ADDR标志位
}

void I2C_Init(void) {
    I2C_Start();
    I2C_SendAddress(0xA0);  // 发送设备地址(假设为0xA0)
    I2C_Write(0x00);  // 发送写入地址(假设为0x00)
    I2C_Stop();
    
    I2C_Start();
    I2C_SendAddress(0xA1);  // 发送设备地址(假设为0xA1)
    uint8_t data = I2C_Read();  // 读取数据
    I2C_Stop();
}

在上述代码中,我们首先发送起始信号(Start),然后发送设备地址和写入位(0xA0)。接下来,我们发送写入地址(0x00),表示我们要写入的寄存器地址。然后,我们发送停止信号(Stop)来结束第一个传输。

接着,我们重新发送起始信号(Start),发送设备地址和读取位(0xA1)。然后,我们读取接收到的数据,并发送停止信号(Stop)来结束第二个传输。

这只是一个简单的示例,演示了如何使用I2C在STM32上进行读取操作。根据具体的外部设备和需求,你可能需要进一步扩展代码来实现更复杂的功能。

四、总结 本教程详细介绍了如何在STM32微控制器上使用I2C通信。我们从基础知识开始,并提供了具体的代码案例来演示如何配置I2C和进行数据传输。希望这个教程能够帮助你入门STM32的I2C通信,并能够应用于你的项目中。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值