1.0 宏定义引脚
cpp
#define GET_IIC_SDA() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)
#define SET_IIC_SCL() GPIO_SetBits(GPIOB, GPIO_Pin_8)
#define CLR_IIC_SCL() GPIO_ResetBits(GPIOB, GPIO_Pin_8)
#define SET_IIC_SDA() GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define CLR_IIC_SDA() GPIO_ResetBits(GPIOB, GPIO_Pin_9)
#define ONE_BYTE_NUM (8)
2.0 初始化GPIO
注:此处表示对应的SCL与SDA引脚
cpp
void IIC_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); // 将PB10和PB11引脚初始化为开漏输出
/*设置默认电平*/
GPIO_SetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9); // 设置PB8和PB9引脚初始化后默认为高电平(释放总线状态)
}
3.0 IIC起始信号
cpp
void IIC_Start(void)
{
SET_IIC_SDA();
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SDA();
Delay_us(10);
CLR_IIC_SCL();
}
4.0 IIC停止信号
cpp
void IIC_Stop(void)
{
CLR_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
SET_IIC_SDA();
}
5.0 IIC发送一个字节
cpp
void IIC_SendByte(uint8_t byte)
{
for (uint8_t i = 0; i < ONE_BYTE_NUM; i++)
{
if (byte & 0x80)
{
SET_IIC_SDA();
}
else
{
CLR_IIC_SDA();
}
byte <<= 1;
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SCL();
Delay_us(10);
}
}
6.0 IIC接收一个字节
cpp
uint8_t IIC_ReceiveByte(void)
{
uint8_t byte = 0x00;
SET_IIC_SDA(); // 释放SDA
for (uint8_t i = 0; i < ONE_BYTE_NUM; i++)
{
SET_IIC_SCL();
Delay_us(10);
byte <<= 1;
if (GET_IIC_SDA())
{
byte++;
}
CLR_IIC_SCL();
Delay_us(10);
}
return byte;
}
7.0 IIC接收应答
cpp
// IIC 接收应答
bool IIC_Wait_Ack(void)
{
uint8_t errTime = 0;
SET_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
while (GET_IIC_SDA())
{
errTime++;
if (errTime > 250)
{
IIC_Stop();
return false;
}
}
CLR_IIC_SCL();
Delay_us(5);
return true;
}
8.0 IIC发送应答
cpp
// IIC 发送应答
void IIC_SendAck(void)
{
CLR_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SCL();
Delay_us(10);
SET_IIC_SDA();
}
9.0 IIC 发送非应答
cpp
// IIC 发送非应答
void IIC_SendNoAck(void)
{
SET_IIC_SDA();
Delay_us(5);
SET_IIC_SCL();
Delay_us(5);
CLR_IIC_SCL();
Delay_us(5);
}
10.0完整程序
cpp
#include "stm32f10x.h"
#include <stdint.h>
#include "stdbool.h"
#define GET_IIC_SDA() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)
#define SET_IIC_SCL() GPIO_SetBits(GPIOB, GPIO_Pin_8)
#define CLR_IIC_SCL() GPIO_ResetBits(GPIOB, GPIO_Pin_8)
#define SET_IIC_SDA() GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define CLR_IIC_SDA() GPIO_ResetBits(GPIOB, GPIO_Pin_9)
#define ONE_BYTE_NUM (8)
void IIC_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); // 将PB10和PB11引脚初始化为开漏输出
/*设置默认电平*/
GPIO_SetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9); // 设置PB8和PB9引脚初始化后默认为高电平(释放总线状态)
}
void IIC_Start(void)
{
SET_IIC_SDA();
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SDA();
Delay_us(10);
CLR_IIC_SCL();
}
void IIC_Stop(void)
{
CLR_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
SET_IIC_SDA();
}
void IIC_SendByte(uint8_t byte)
{
for (uint8_t i = 0; i < ONE_BYTE_NUM; i++)
{
if (byte & 0x80)
{
SET_IIC_SDA();
}
else
{
CLR_IIC_SDA();
}
byte <<= 1;
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SCL();
Delay_us(10);
}
}
uint8_t IIC_ReceiveByte(void)
{
uint8_t byte = 0x00;
SET_IIC_SDA(); // 释放SDA
for (uint8_t i = 0; i < ONE_BYTE_NUM; i++)
{
SET_IIC_SCL();
Delay_us(10);
byte <<= 1;
if (GET_IIC_SDA())
{
byte++;
}
CLR_IIC_SCL();
Delay_us(10);
}
return byte;
}
// IIC 接收应答
bool IIC_Wait_Ack(void)
{
uint8_t errTime = 0;
SET_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
while (GET_IIC_SDA())
{
errTime++;
if (errTime > 250)
{
IIC_Stop();
return false;
}
}
CLR_IIC_SCL();
Delay_us(5);
return true;
}
// IIC 发送应答
void IIC_SendAck(void)
{
CLR_IIC_SDA();
Delay_us(10);
SET_IIC_SCL();
Delay_us(10);
CLR_IIC_SCL();
Delay_us(10);
SET_IIC_SDA();
}
// IIC 发送非应答
void IIC_SendNoAck(void)
{
SET_IIC_SDA();
Delay_us(5);
SET_IIC_SCL();
Delay_us(5);
CLR_IIC_SCL();
Delay_us(5);
}
......