一.I2C 简介
I2C(内部集成电路)总线接口用作微控制器和 I2C 串行总线之间的接口。它提供多主模式功
能,可以控制所有 I2C 总线特定的序列、协议、仲裁和时序。它支持标准和快速模式。它还
与 SMBus 2.0 兼容。
它可以用于多种用途,包括 CRC 生成和验证、 SMBus(系统管理总线)以及 PMBus(电源
管理总线)。
根据器件的不同,可利用 DMA 功能来减轻 CPU 的工作量
二.IIC物理层
它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总
线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
(2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线
(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
(3) 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之
间的访问。
(4) 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空
闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
5) 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用
总线。
(6) 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式
下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。
(7) 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制
三.在IIC通信前,先把串口的代码贴出来,因为需要用到串口调试
1.bsp_debug_usart.h
#ifndef __DEBUG_USART_H
#define __DEBUG_USART_H
#include "stm32f4xx.h"
#include <stdio.h>
//引脚定义
/*******************************************************/
#define DEBUG_USART USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_RX_PIN GPIO_Pin_10
#define DEBUG_USART_RX_AF GPIO_AF_USART1
#define DEBUG_USART_RX_SOURCE GPIO_PinSource10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_TX_PIN GPIO_Pin_9
#define DEBUG_USART_TX_AF GPIO_AF_USART1
#define DEBUG_USART_TX_SOURCE GPIO_PinSource9
/************************************************************/
//串口波特率
#define DEBUG_USART_BAUDRATE 115200
void Debug_USART_Config(void);
#endif /* __USART1_H */
2.bsp_debug_usart.c
#include "bsp_debug_usart.h"
/*DEBUG_USART GPIO 配置,工作模式配置。115200 8-N-1*/
void Debug_USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd( DEBUG_USART_RX_GPIO_CLK|DEBUG_USART_TX_GPIO_CLK, ENABLE);
/* 使能 UART 时钟 */
RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
/* 连接 PXx 到 USARTx_Tx*/
GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,DEBUG_USART_RX_SOURCE, DEBUG_USART_RX_AF);
/* 连接 PXx 到 USARTx__Rx*/
GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,DEBUG_USART_TX_SOURCE,DEBUG_USART_TX_AF);
/* 配置Tx引脚为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
/* 配置Rx引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* 配置串DEBUG_USART 模式 */
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(DEBUG_USART, &USART_InitStructure);
USART_Cmd(DEBUG_USART, ENABLE);
}
///重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
USART_SendData(DEBUG_USART, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USART);
}
四.IIC读写EEPROM过程
1.跟硬件相关的GPIO先用宏封装起来,方便移植,如图所示,我的原理图是用PB8和PB9作为IIC的两个引脚,下图是在STM32数据手册截图而来,我们设计原理图就要看这个
代码如下,包含AT24C02的设备地址读写位,IIC引脚的封装和一下函数的声明
IIC_GPIO.h
#ifndef _I2C_GPIO_H
#define _I2C_GPIO_H
#include "stm32f4xx.h"
#include "inttypes.h"
/*EEPROM写方向*/
#define EEPROM_I2C_WR 0
/*EEPROM读方向*/
#define EEPROM_I2C_RD 1
#define EEPROM_I2C_GPIO_PORT GPIOB
#define EEPROM_I2C_GPIO_CLK RCC_AHB1Periph_GPIOB
#define EEPROM_I2C_SCL_PIN GPIO_Pin_8
#define EEPROM_I2C_SDA_PIN GPIO_Pin_9
#define EEPROM_I2C_SCL_1() GPIO_SetBits(EEPROM_I2C_GPIO_PORT,EEPROM_I2C_SCL_PIN)
#define EEPROM_I2C_SCL_0() GPIO_ResetBits(EEPROM_I2C_GPIO_PORT,EEPROM_I2C_SCL_PIN)
#define