备份一下写的模拟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);
}