硬汉嵌入式论坛

 找回密码
 立即注册
查看: 842|回复: 1
收起左侧

分享一个软件I2C模块

[复制链接]

5

主题

15

回帖

30

积分

新手上路

积分
30
发表于 2024-7-28 01:56:52 | 显示全部楼层 |阅读模式
本帖最后由 vuxtvg 于 2024-7-28 02:01 编辑

本人写了一个软件I2C的模块,实现模块化,高内聚低耦合


如有问题还望指正


#include "bsp_softi2c.h"

static void (*g_init_pins)(void) = NULL;
static void (*g_delay_microseconds)(uint32_t) = NULL;
static void (*g_set_sda)(bool state) = NULL;
static void (*g_set_scl)(bool state) = NULL;
static uint8_t (*g_get_sda)(void) = NULL;

static void softiic_init_pins(void)
{
    if (g_init_pins != NULL)
        g_init_pins();
}

static void softiic_delay_microseconds(uint32_t us)
{
    if (g_delay_microseconds != NULL)
        g_delay_microseconds(us);
}

static void softiic_set_sda(bool state)
{
    if (g_set_sda != NULL)
        g_set_sda(state);
}

static void softiic_set_scl(bool state)
{
    if (g_set_scl != NULL)
        g_set_scl(state);
}

static uint8_t softiic_get_sda(void)
{
    if (g_get_sda != NULL)
        return g_get_sda();
    else
        return 0;
}

void SoftIIC_Init(SoftIIC_Config *cfg)
{
    g_init_pins = cfg->init_pins;
    g_delay_microseconds = cfg->delay_microseconds;
    g_set_sda = cfg->set_sda;
    g_set_scl = cfg->set_scl;
    g_get_sda = cfg->get_sda;
    softiic_init_pins();
}

void SoftIIC_Start(void)
{
    softiic_set_sda(true);
    softiic_set_scl(true);
    softiic_delay_microseconds(4);
    softiic_set_sda(false);
    softiic_delay_microseconds(4);
    softiic_set_scl(false);
    softiic_delay_microseconds(4);
}

void SoftIIC_Stop(void)
{
    softiic_set_sda(false);
    softiic_delay_microseconds(4);
    softiic_set_scl(true);
    softiic_delay_microseconds(4);
    softiic_set_sda(true);
}

void SoftIIC_SendByte(uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++)
    {
        softiic_set_sda(byte & 0x80);
        byte <<= 1;
        softiic_delay_microseconds(4);
        softiic_set_scl(true);
        softiic_delay_microseconds(4);
        softiic_set_scl(false);
        softiic_delay_microseconds(4);
    }
}

uint8_t SoftIIC_ReadByte(void)
{
    uint8_t byte = 0;
    softiic_set_sda(true);

    for (uint8_t i = 0; i < 8; i++)
    {
        softiic_set_scl(true);
        softiic_delay_microseconds(4);
        byte <<= 1;
        if (softiic_get_sda())
        {
            byte |= 1;
        }
        softiic_set_scl(false);
        softiic_delay_microseconds(4);
    }

    return byte;
}

bool SoftIIC_WaitAck(void)
{
    uint8_t errTimes = 0;

    softiic_set_sda(true);
    softiic_delay_microseconds(4);
    softiic_set_scl(true);
    softiic_delay_microseconds(4);

    while (softiic_get_sda())
    {
        errTimes++;
        if (errTimes > 250)
        {
            SoftIIC_Stop();
            return false;
        }
    }

    softiic_set_scl(false);
    softiic_delay_microseconds(4);

    return true;
}

void SoftIIC_SendAck(void)
{
    softiic_set_sda(false);
    softiic_delay_microseconds(4);
    softiic_set_scl(true);
    softiic_delay_microseconds(4);
    softiic_set_scl(false);
    softiic_delay_microseconds(4);
    softiic_set_sda(true);
}

void SoftIIC_SendNack(void)
{
    softiic_set_sda(true);
    softiic_delay_microseconds(4);
    softiic_set_scl(true);
    softiic_delay_microseconds(4);
    softiic_set_scl(false);
    softiic_delay_microseconds(4);
}





#ifndef BSP_SOFTI2C_H_
#define BSP_SOFTI2C_H_

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

/**
* @brief 软件 IIC 模块配置结构体
*
* 此结构体包含了一些函数指针,用于初始化 IIC 的 SDA 和 SCL 引脚,设置和获取 SDA 和 SCL 的状态,
* 以及延时函数。通过这种方式,可以在不同的硬件平台上使用相同的 IIC 接口代码。
*/
typedef struct
{
    void (*init_pins)(void);                 // 初始化 IIC 的 SDA 和 SCL 引脚
    void (*delay_microseconds)(uint32_t us); // 延时函数
    void (*set_sda)(bool state);             // 设置 SDA 引脚状态
    void (*set_scl)(bool state);             // 设置 SCL 引脚状态
    uint8_t (*get_sda)(void);                // 获取 SDA 引脚状态
} SoftIIC_Config;

void SoftIIC_Init(SoftIIC_Config *cfg);
void SoftIIC_Start(void);
void SoftIIC_Stop(void);
void SoftIIC_SendByte(uint8_t byte);
uint8_t SoftIIC_ReadByte(void);
bool SoftIIC_WaitAck(void);
void SoftIIC_SendAck(void);
void SoftIIC_SendNack(void);

#endif


应该是可以支持所有的单片机的,仅需SoftIIC_Init初始化即可,方便移植,bsp_softi2c.c/.h 不需要修改
Ps:如果您用到项目中,还望可以署名我(本人邮箱:vuxtvg@163.com)是这个模块的一个小小的作者,也希望您能在这个帖子下面发表一下评论,让我开心一下(*^▽^*)
如有转载,注明出处(本人邮箱:vuxtvg@163.com)
本文结束啦,谢谢大家,感谢平台


回复

使用道具 举报

34

主题

206

回帖

308

积分

高级会员

积分
308
发表于 2024-7-28 08:36:18 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 06:30 , Processed in 0.035923 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表