用C语言写一个STM32 寄存器版的从机I2C代码
时间: 2023-08-13 09:03:08 浏览: 159
以下是一个简单的STM32寄存器版从机I2C代码示例,使用的是STM32F407VG芯片,I2C2作为从机,代码中假设主机发送的数据为1字节:
```
#include "stm32f4xx.h"
void I2C2_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能 I2C2 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
// 使能 GPIOB 时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// 配置 GPIOB 引脚 PB10 和 PB11 为 I2C2_SCL 和 I2C2_SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置 PB10 和 PB11 的复用功能为 I2C2
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
// 配置 I2C2
I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusSlave; // 采用 SMBusSlave 模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // I2C 时钟占空比为 2
I2C_InitStructure.I2C_OwnAddress1 = 0x30; // 从机地址为 0x30
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 位地址模式
I2C_InitStructure.I2C_ClockSpeed = 100000; // I2C 时钟速度为 100 kHz
I2C_Init(I2C2, &I2C_InitStructure);
// 使能 I2C2
I2C_Cmd(I2C2, ENABLE);
// 配置 I2C2 中断
NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能 I2C2 中断
I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);
}
void I2C2_EV_IRQHandler(void)
{
if (I2C_GetITStatus(I2C2, I2C_IT_EVT) == SET) {
// 接收到主机发送的数据
if (I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR) == SET) {
// 清除 ADDR 标志位
(void)I2C2->SR2;
// 等待接收数据完成
while (I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE) == RESET);
// 读取接收到的数据
uint8_t data = I2C_ReceiveData(I2C2);
// 处理接收到的数据
// TODO: 在此处添加处理代码
// 发送应答
I2C_AcknowledgeConfig(I2C2, ENABLE);
// 清除 ADDR 标志位
(void)I2C2->SR2;
// 等待数据发送完成
while (I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE) == RESET);
// 发送数据
I2C_SendData(I2C2, data);
}
}
// 清除事件标志位
I2C_ClearITPendingBit(I2C2, I2C_IT_EVT);
}
int main(void)
{
I2C2_Configuration();
while(1) {
// 主循环
}
}
```
需要注意的是,在使用I2C2作为从机时,需要将PB10、PB11引脚配置为复用功能,并且不要忘记在I2C2_EV_IRQHandler中处理接收到的数据。另外,需要根据实际情况修改从机地址、时钟速度等参数。
阅读全文