引言
I2C(Inter-Integrated Circuit)是一种常用于连接微控制器和外设的串行通信协议。在单片机的开发过程中,掌握I2C通信编程技巧是非常重要的。本文将以一个具体的示例来介绍如何使用I2C通信协议在单片机中进行数据传输。
示例介绍
我们将使用STM32F4系列微控制器,并且通过I2C总线与一个温湿度传感器(例如DHT11)进行通信。我们的目标是读取传感器测量到的温度和湿度值,并将其显示在LCD屏幕上。
I2C通信配置
首先,我们需要对单片机的I2C通信进行配置。以下是一些常用的配置参数:
- 发送和接收字节的速度:可以通过设置I2C频率来控制。
- I2C总线地址:每个设备都有一个唯一的地址,用于在总线上识别设备。
- 发送和接收字节的字长:可以设置为8位或16位。
- I2C时钟频率:可以通过设置I2C_CR2寄存器中的CLK频率字段来控制。
I2C通信流程
下面是使用I2C通信进行数据传输的基本流程:
- 初始化I2C总线和配置参数。
- 发送启动信号(START)到总线上。
- 发送设备地址和读/写模式。
- 如果是写操作,发送数据到设备。
- 如果是读操作,接收设备发送的数据。
- 发送停止信号(STOP)到总线上。
示例代码
以下是一个示例代码,展示了如何使用I2C通信从DHT11传感器读取温度和湿度值,并显示在LCD屏幕上。
#include <stdio.h>
#include <stm32f4xx.h>
// 定义I2C总线地址和设备地址
#define I2C_ADDRESS 0x27
#define DHT11_ADDRESS 0x5C
// 初始化I2C总线
void I2C_Init() {
// 配置GPIO引脚作为I2C功能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
// 配置I2C参数
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000; // 设置I2C速度为100kHz
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = I2C_ADDRESS;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}
// 从DHT11读取温度和湿度值
void DHT11_ReadData(uint8_t* temperature, uint8_t* humidity) {
// 发送启动信号
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) {}
// 发送设备地址和读模式
I2C_Send7bitAddress(I2C1, DHT11_ADDRESS, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {}
// 发送数据
I2C_SendData(I2C1, 0x00);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {}
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
// 延时一段时间
// 发送启动信号
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) {}
// 发送设备地址和读模式
I2C_Send7bitAddress(I2C1, DHT11_ADDRESS, I2C_Direction_Receiver);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {}
// 接收数据
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
*temperature = I2C_ReceiveData(I2C1);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) {}
*humidity = I2C_ReceiveData(I2C1);
}
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
}
int main() {
// 初始化LCD屏幕
LCD_Init();
LCD_Clear();
// 初始化I2C总线
I2C_Init();
uint8_t temperature, humidity;
while (1) {
// 从DHT11传感器读取温度和湿度值
DHT11_ReadData(&temperature, &humidity);
// 在LCD屏幕上显示温度和湿度值
char temp_text[16];
char hum_text[16];
sprintf(temp_text, "Temp: %dC", temperature);
sprintf(hum_text, "Humidity: %d%%", humidity);
LCD_SetCursorPosition(0, 0);
LCD_WriteString(temp_text);
LCD_SetCursorPosition(1, 0);
LCD_WriteString(hum_text);
// 延时一段时间
Delay(1000);
}
}
总结
通过这个示例,我们展示了如何使用I2C通信协议在单片机中进行数据传输。通过逐步配置I2C总线和实现通信流程,我们可以与外部设备进行数据交换,并将其显示在LCD屏幕上。希望这个示例能够帮助你更好地理解和应用I2C通信。
本文来自极简博客,作者:紫色星空下的梦,转载请注明原文链接:单片机中的I2C通信编程实战