GPIO_I2C 模拟I2C的写作练习。

备份一下写的模拟IIC主机操作时序和代码结构

 
#ifndef __GPIO_IIC_DRIVER__H__
#define __GPIO_IIC_DRIVER__H__

#include "CSysCfg.h"

#if 0
typedef struct GPIO_IIC_Driver_Event
{
    /*pad configurations*/
    void_t (*__io_init)(void);
    /* functions */
    void_t (*__start)(void);
    int  (*__write)(uint8_t addr, uint8_t* buff, uint16_t write_n);
    void_t (*__read)(uint8_t addr, uint8_t* buff, uint16_t* read_n);
    int  (*__wait_ack)(void);
    void_t (*__send_ack)(void);
    void_t (*__send_nack)(void);
    void_t (*__stop)(void);
}GPIO_IIC_Driver_Event_t;
#endif
/****************************************************************************
 *初始化 I2C管教信号电平
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t InitI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C起始信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t StartI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C停止信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t StopI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C写一个字节
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 *       uint8_t byte
 *          需要写入的值
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t WriteByte_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio, const uint8_t byte);
/****************************************************************************
 *I2C应答信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t AckI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C应答否信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t NackI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C等待应答信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t 
 *           0:   有应答
 *           非0: 没有应答
*****************************************************************************/
uint8_t WaitAck_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C 读一个字节
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t
 *          实际读到的数值
*****************************************************************************/
uint8_t ReadByte_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio);
/****************************************************************************
 *I2C 读一个字节并发起ack信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t
 *          实际读到的数值
*****************************************************************************/
uint8_t ReadByteAck_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio, uint8_t ack);

#endif // !__GPIO_IIC_DRIVER__H

/****************************************************************************
 *初始化 I2C管教信号电平
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t InitI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
	tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_CFG_OUT_OD(pSCL);
    JBF_GPIO_CFG_OUT_OD(pSDA);
    JBF_GPIO_OUTPUT_HIGH(pSCL);
    JBF_GPIO_OUTPUT_HIGH(pSDA);
}
/****************************************************************************
 *I2C起始信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t StartI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_OUTPUT_HIGH(pSCL);   
    JBF_GPIO_OUTPUT_HIGH(pSDA);
    JBF_MCU_DELAY_4US();//对齐,挂一个scl脉冲,开始发送起始信号
    JBF_GPIO_OUTPUT_LOW(pSDA);
    JBF_MCU_DELAY_4US();//SCL 为高,SDA拉低,挂一个scl脉冲窗口
    JBF_GPIO_OUTPUT_LOW(pSCL);//钳住SCL先,准备下一步操作
}

/****************************************************************************
 *I2C停止信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t StopI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);
 
    JBF_GPIO_OUTPUT_LOW(pSCL);//钳住SCL先,准备下一步操作
    JBF_GPIO_OUTPUT_LOW(pSDA);
    JBF_MCU_DELAY_4US();
    JBF_GPIO_OUTPUT_HIGH(pSCL);//拉高SCL
    JBF_MCU_DELAY_4US();
    JBF_GPIO_OUTPUT_HIGH(pSDA);//拉高SDA
}
/****************************************************************************
 *I2C应答信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t AckI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_CFG_OUT_OD(pSDA);
    JBF_GPIO_OUTPUT_LOW(pSDA);
    JBF_MCU_DELAY_2US();//等数据稳定 挂一个脉冲
 
    JBF_GPIO_OUTPUT_HIGH(pSCL);//放开SCL
    JBF_MCU_DELAY_2US();//挂一个脉冲
 
    JBF_GPIO_OUTPUT_LOW(pSCL);
}
/****************************************************************************
 *I2C应答否信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t NackI2c_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_OUTPUT_HIGH(pSDA);
    JBF_MCU_DELAY_2US();//等数据稳定 挂一个脉冲

    JBF_GPIO_OUTPUT_HIGH(pSCL);//放开SCL
    JBF_MCU_DELAY_2US();//挂一个脉冲

    JBF_GPIO_OUTPUT_LOW(pSCL);
}
/****************************************************************************
 *I2C写一个字节
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 *       uint8_t byte
 *          需要写入的值
 * 
 * 返回  void_t:  void
*****************************************************************************/
void_t WriteByte_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio, const uint8_t byte)
{
    uint8_t bit, _byte;
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    _byte = byte;
    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_OUTPUT_LOW(pSDA);
    for(bit = 0; bit < 8; bit++)
    {
        if (_byte & 0x80)
        {
            JBF_GPIO_OUTPUT_HIGH(pSDA);
        }
        else
        {
            JBF_GPIO_OUTPUT_LOW(pSDA);
        }
        _byte <<= 1;// (_byte << 1); 
        JBF_MCU_DELAY_2US();
        JBF_GPIO_OUTPUT_HIGH(pSCL);
        JBF_MCU_DELAY_2US();
        JBF_GPIO_OUTPUT_LOW(pSCL);
        JBF_MCU_DELAY_2US();
    }
}

/****************************************************************************
 *I2C等待应答信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t 
 *           0:   有应答
 *           非0: 没有应答
*****************************************************************************/
uint8_t WaitAck_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{

    uint8_t _wait_cnt = 255;
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_OUTPUT_HIGH(pSDA);
    JBF_GPIO_CFG_MODE_IN(pSDA);
    JBF_MCU_DELAY_4US();
    JBF_GPIO_OUTPUT_HIGH(pSCL);
    JBF_MCU_DELAY_4US();

    while (JBF_GPIO_INPUT_READ(pSDA))
    {
        _wait_cnt--;
        if (_wait_cnt == 0)
        {
            break;
        }
    } 

    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_CFG_OUT_OD(pSDA);

    if (_wait_cnt == 0)/*time out*/
    {
        StopI2c_CDrvGpioIIC(pI2cGpio);
    }

    return (_wait_cnt == 0); 
}
/****************************************************************************
 *I2C 读一个字节
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t
 *          实际读到的数值
*****************************************************************************/
uint8_t ReadByte_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio)
{
	  uint8_t bit, _byte = 0;
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);

    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_OUTPUT_LOW(pSDA);
    JBF_GPIO_CFG_MODE_IN(pSDA);
    for (bit = 0; bit < 8; bit++)
    {
        JBF_GPIO_OUTPUT_HIGH(pSCL);
        JBF_MCU_DELAY_4US();
        _byte <<= 1;
        if (JBF_GPIO_INPUT_READ(pSDA))
        {
            _byte |= 0x01;
        }
        JBF_GPIO_OUTPUT_LOW(pSCL);
        JBF_MCU_DELAY_4US();
    }
    JBF_GPIO_CFG_OUT_OD(pSDA);
    return (_byte);
}
/****************************************************************************
 *I2C 读一个字节并发起ack信号
 *入参   tGPIO_IIC_INFO_t* pI2cGpio
 *          模拟IIC的GPIO管教设置,再传入前保证先调用
 *          宏GPIO_DEV_INFO_SET_IIC,并传入必要参数
 * 
 * 返回  uint8_t
 *          实际读到的数值
*****************************************************************************/
uint8_t ReadByteAck_CDrvGpioIIC(tGPIO_IIC_INFO_t* pI2cGpio, uint8_t ack)
{
	  uint8_t bit, _byte = 0;
    tGPIO_Port_t *pSCL = &(pI2cGpio->SCL);
    tGPIO_Port_t *pSDA = &(pI2cGpio->SDA);
    ASSERT(pI2cGpio);
    ASSERT(pSCL);
    ASSERT(pSDA);
	
    JBF_GPIO_OUTPUT_LOW(pSCL);
    JBF_GPIO_OUTPUT_LOW(pSDA);
    JBF_GPIO_CFG_MODE_IN(pSDA);
    for (bit = 0; bit < 8; bit++)
    {
        JBF_GPIO_OUTPUT_HIGH(pSCL);
        JBF_MCU_DELAY_2US();
        _byte <<= 1;
        if (JBF_GPIO_INPUT_READ(pSDA))
        {
            _byte |= 0x01;
        }
        JBF_GPIO_OUTPUT_LOW(pSCL);
        JBF_MCU_DELAY_2US();
    }
    JBF_GPIO_CFG_OUT_OD(pSDA);
    if (ack)
    {
        AckI2c_CDrvGpioIIC(pI2cGpio);
    } 
    else
    {
        NackI2c_CDrvGpioIIC(pI2cGpio);
    }
    return (_byte);
}

猜你喜欢

转载自blog.csdn.net/loveboon1/article/details/130366489
I2C