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

......

相关推荐
小莞尔5 分钟前
【51单片机】【protues仿真】基于51单片机数控直流稳压电源系统
c语言·stm32·单片机·嵌入式硬件·51单片机
小莞尔6 分钟前
【51单片机】【protues仿真】基于51单片机密码锁系统
c语言·stm32·单片机·嵌入式硬件·51单片机
黑不拉几的小白兔7 分钟前
stm32教程:USART串口通信
stm32·单片机·嵌入式硬件
sheepwjl2 小时前
《嵌入式硬件(十二):基于IMX6ULL的时钟操作》
汇编·arm开发·单片机·嵌入式硬件·时钟·.s编译
智者知已应修善业4 小时前
【51单片机单按键控制2个LED循环闪烁】2022-12-7
c语言·经验分享·笔记·嵌入式硬件·51单片机
物随心转4 小时前
ARM的TrustZone
嵌入式硬件
风_峰5 小时前
PuTTY软件访问ZYNQ板卡的Linux系统
linux·服务器·嵌入式硬件·fpga开发
田甲5 小时前
【STM32】串口的阻塞、中断、DMA收发
stm32·单片机·嵌入式硬件
酷~6 小时前
单片机启动文件——数据段重定位,BSS段清零
单片机·嵌入式硬件
wotaifuzao6 小时前
单片机的RAM与ROM概念
单片机·嵌入式硬件