当前位置: 首页 > article >正文

STM32 IIC协议实现

1.0 宏定义引脚


#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引脚

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起始信号


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停止信号


void IIC_Stop(void)
{
    CLR_IIC_SDA();
    Delay_us(10);
    SET_IIC_SCL();
    Delay_us(10);
    SET_IIC_SDA();
}

5.0 IIC发送一个字节


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接收一个字节


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接收应答


// 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发送应答


// 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 发送非应答


// 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完整程序


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

......


http://www.kler.cn/a/442617.html

相关文章:

  • 49_Lua调试
  • WEB攻防-通用漏洞_XSS跨站_权限维持_捆绑钓鱼_浏览器漏洞
  • IDEA编译器集成Maven环境以及项目的创建(2)
  • 【Rust】错误处理机制
  • 使用gtsam添加OrientedPlane3Factor平面约束因子
  • 多模态论文笔记——CLIP
  • 银行金融项目测试+常问面试题(附答案)
  • XXE-Lab for PHP
  • uniapp scroll-view 不生效排查
  • RT-Thread 的时钟管理
  • 3_使用 HTML5 Canvas API (2) --[HTML5 API 学习之旅]
  • Qt之自定义标题栏拓展(十)
  • Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection
  • spring使用rabbitmq当rabbitmq集群节点挂掉 spring rabbitmq怎么保证高可用,rabbitmq网络怎么重新连接
  • 使用Python打造高效的PDF文件管理应用(合并以及分割)
  • Spring Boot 集成 Elasticsearch怎样在不启动es的情况下正常启动服务
  • 【21天学习AI底层概念】day5 机器学习的三大类型不能解决哪些问题?
  • 秒杀抢购场景下实战JVM级别锁与分布式锁
  • 四、网络层:数据平面,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
  • WPF 使用LibVLCSharp.WPF实现视频播放、停止、暂停功能
  • 【排序算法】——插入排序
  • .Net Core注册一个定制任务执行类服务
  • 首屏加载慢问题
  • 备战秋招:2024游戏开发入行与跳槽面试详解
  • 智能移动交通执法方案:易泊车牌识别相机助力精准执法与数据驱动管理
  • HCIA-Access V2.5_3_3_2_VLAN路由配置与实现