STM32 IIC协议实现

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);
}

......

相关推荐
草丛中的蝈蝈6 分钟前
单片机烧写新程序后,ST-LINK无法发现设备
单片机·嵌入式硬件
不做无法实现的梦~22 分钟前
PX4怎么使用使用PlotJuggler分析PX4日志
linux·嵌入式硬件·机器人·自动驾驶
ae_zr28 分钟前
STM32H743+DMA+串口空闲中断接收不定长数据,并使用DMA发送数据
stm32·单片机·嵌入式硬件·dma
芯岭技术29 分钟前
全新一代2.4GHz 单片无线收发芯片 XL2400T,性能更强,距离更远
单片机·嵌入式硬件
dump linux1 小时前
Linux DRM GPU 驱动框架详解
linux·驱动开发·嵌入式硬件
天骄t1 小时前
ARM时钟初始化与GPT定时器深度解析
stm32·单片机·fpga开发
Zeku1 小时前
20260120 - Linux驱动学习笔记:SPI子系统核心层到具体硬件驱动
stm32·freertos·linux驱动开发·linux应用开发
阿华hhh1 小时前
day4(IMX6ULL)<定时器>
c语言·开发语言·单片机·嵌入式硬件
钰珠AIOT1 小时前
在电源的滤波电路中10uf 和100nF 的电容滤波的频率大概是多少?如何计算?
单片机·物联网
CQ_YM2 小时前
ARM中断
arm开发·嵌入式硬件·arm