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

......

相关推荐
冷曦_sole2 小时前
linux-16 关于shell(十五)date,clock,hwclock,man,时间管理,命令帮助
linux·stm32·单片机
嵌入式@hxydj2 小时前
STM32F103单片机HAL库串口通信卡死问题解决方法
stm32·单片机·嵌入式硬件·串口·uart·hal·卡死
嵌入式阿萌3 小时前
STM32F407+LAN8720A +LWIP +FreeRTOS 实现TCP服务器
服务器·stm32·tcp/ip
Be Legendary-CGK5 小时前
【电子元器件】电感基础知识
嵌入式硬件·硬件工程
sayang_shao6 小时前
STM32 LL库串口DMA收发初始化
stm32·单片机·嵌入式硬件
skywalk81636 小时前
奇怪的知识又增加了:ESP32下的Lisp编程=>ULisp--Lisp for microcontrollers
开发语言·单片机·物联网·esp32·lisp
憧憬一下6 小时前
PCIe的三种路由方式
arm开发·嵌入式硬件·嵌入式·linux驱动开发·pci/pcie
Anin蓝天(北京太速科技-陈)6 小时前
208-Base Camera Link 图像信号模拟器
嵌入式硬件·fpga开发·信号处理
BT-BOX7 小时前
基于STM32的火灾烟雾报警器Proteus仿真设计(仿真+程序+设计报告+讲解视频)
stm32·proteus·音视频