Files
player/Project_App_Chat/App_Src/drive/qst_sw_i2c.c
2025-06-27 00:32:57 +08:00

498 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @file qmaX981_sw_i2c.c
* @author yzq
* @version V1.0
* @date 2018-05-01
* @brief 软件IIC 驱动
******************************************************************************
* @attention
*
* 实验平台:秉火 F103-指南者 STM32 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
/*
应用说明:
在访问I2C设备前请先调用 i2c_CheckDevice() 检测I2C设备是否正常该函数会配置GPIO
*/
#include "qst_sw_i2c.h"
/* 定义I2C总线连接的GPIO端口, 用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
#define GPIO_PORT_I2C GPIOA /* GPIO端口 */
#define RCC_I2C_PORT RCC_APB2Periph_GPIOA /* GPIO端口时钟 */
//#if defined(USE_I2C_1_PB6_7)
#if 1
#define I2C_SCL_PIN GPIO_Pin_9 /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN GPIO_Pin_10 /* 连接到SDA数据线的GPIO */
#endif
#if defined(USE_I2C_1_PB8_9)
#define I2C_SCL_PIN GPIO_Pin_8 /* 连接到SCL时钟线的GPIO */
#define I2C_SDA_PIN GPIO_Pin_9 /* 连接到SDA数据线的GPIO */
#endif
#if 1 /* 条件编译: 1 选择GPIO的库函数实现IO读写 */
/* 定义读写SCL和SDA的宏已增加代码的可移植性和可阅读性 */
#define I2C_SCL_OUTPUT()
#define I2C_SCL_INPUT()
#define I2C_SDA_OUTPUT()
#define I2C_SDA_INPUT()
#define I2C_SCL_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 1 */
#define I2C_SCL_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN) /* SCL = 0 */
#define I2C_SDA_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 1 */
#define I2C_SDA_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN) /* SDA = 0 */
#define I2C_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN) /* 读SDA口线状态 */
#else /* 这个分支选择直接寄存器操作实现IO读写 */
//#define SDA_IN() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=8<<4;} // GPIO8
//#define SDA_OUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=3<<4;} // GPIO9
//#define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)8<<28);} // GPIO6
//#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)3<<28);} // GPIO7
#if defined(USE_I2C_1_PB6_7)
#define I2C_SCL_INPUT() //{GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)8<<24);}
#define I2C_SCL_OUTPUT() //{GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)3<<24);}
#define I2C_SDA_INPUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)8<<28);}
#define I2C_SDA_OUTPUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=((uint32_t)3<<28);}
#endif
#if defined(USE_I2C_1_PB8_9)
#define I2C_SCL_INPUT()
#define I2C_SCL_OUTPUT()
#define I2C_SDA_INPUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=((uint32_t)8<<4);}
#define I2C_SDA_OUTPUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=((uint32_t)3<<4);}
#endif
#define I2C_SCL_1() GPIO_PORT_I2C->BSRR = I2C_SCL_PIN /* SCL = 1 */
#define I2C_SCL_0() GPIO_PORT_I2C->BRR = I2C_SCL_PIN /* SCL = 0 */
#define I2C_SDA_1() GPIO_PORT_I2C->BSRR = I2C_SDA_PIN /* SDA = 1 */
#define I2C_SDA_0() GPIO_PORT_I2C->BRR = I2C_SDA_PIN /* SDA = 0 */
#define I2C_SDA_READ() ((GPIO_PORT_I2C->IDR & I2C_SDA_PIN) != 0) /* 读SDA口线状态 */
#endif
void qst_delay(unsigned int delay)//0.1ms
{
int i, j;
for(i = 0; i < delay; i++)
{
for(j = 0; j < 800; j++)
{
;
}
}
}
void delay_us(int nus)
{
//volatile uint32_t i;
while(nus--)
{
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
}
}
#if 0
static void i2c_Delay(void)
{
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
}
#else
#define i2c_Delay() delay_us(1)
#endif
void i2c_Start(void)
{
/* 当SCL高电平时SDA出现一个下跳沿表示I2C总线启动信号 */
I2C_SCL_OUTPUT();
I2C_SDA_OUTPUT();
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_Start
* 功能说明: CPU发起I2C总线停止信号
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_Stop(void)
{
I2C_SCL_OUTPUT();
I2C_SDA_OUTPUT();
/* 当SCL高电平时SDA出现一个上跳沿表示I2C总线停止信号 */
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_SendByte
* 功能说明: CPU向I2C总线设备发送8bit数据
* 形 参_ucByte 等待发送的字节
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送字节的高位bit7 */
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1(); // 释放总线
}
_ucByte <<= 1; /* 左移一个bit */
i2c_Delay();
}
}
/*
*********************************************************************************************************
* 函 数 名: i2c_ReadByte
* 功能说明: CPU从I2C总线设备读取8bit数据
* 形 参:无
* 返 回 值: 读到的数据
*********************************************************************************************************
*/
uint8_t i2c_ReadByte(u8 ack)
{
uint8_t i;
uint8_t value;
/* 读到第1个bit为数据的bit7 */
I2C_SDA_INPUT(); // set data input
i2c_Delay();
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ())
{
value++;
}
//I2C_SCL_1();
//i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
I2C_SDA_OUTPUT(); // set data output
i2c_Delay();
if(ack==0)
i2c_NAck();
else
i2c_Ack();
return value;
}
/*
*********************************************************************************************************
* 函 数 名: i2c_WaitAck
* 功能说明: CPU产生一个时钟并读取器件的ACK应答信号
* 形 参:无
* 返 回 值: 返回0表示正确应答1表示无器件响应
*********************************************************************************************************
*/
uint8_t i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPU释放SDA总线 */
I2C_SDA_INPUT(); //set data input
i2c_Delay();
I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
i2c_Delay();
if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
I2C_SDA_OUTPUT(); //set data output
i2c_Delay();
return re;
}
/*
*********************************************************************************************************
* 函 数 名: i2c_Ack
* 功能说明: CPU产生一个ACK信号
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_Ack(void)
{
I2C_SDA_0(); /* CPU驱动SDA = 0 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生1个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1(); /* CPU释放SDA总线 */
}
/*
*********************************************************************************************************
* 函 数 名: i2c_NAck
* 功能说明: CPU产生1个NACK信号
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_NAck(void)
{
I2C_SDA_1(); /* CPU驱动SDA = 1 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生1个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/*
*********************************************************************************************************
* 函 数 名: i2c_GPIO_Config
* 功能说明: 配置I2C总线的GPIO采用模拟IO的方式实现
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void i2c_sw_gpio_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; /* 开漏输出 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
i2c_Stop();
}
uint8_t qst_sw_writereg(uint8_t slave, uint8_t reg_add,uint8_t reg_dat)
{
i2c_Start();
i2c_SendByte(slave);
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(reg_add);
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(reg_dat);
if(i2c_WaitAck())
{
return 0;
}
i2c_Stop();
return 1;
}
uint8_t qst_sw_writeregs(uint8_t slave, uint8_t reg_add, uint8_t *reg_dat, uint8_t len)
{
uint8_t i;
i2c_Start();
i2c_SendByte(slave);
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(reg_add);
if(i2c_WaitAck())
{
return 0;
}
for(i=0; i<len; i++)
{
i2c_SendByte(reg_dat[i]);
if(i2c_WaitAck())
{
return 0;
}
}
i2c_Stop();
return 1;
}
uint8_t qst_sw_readreg(uint8_t slave, uint8_t reg_add, uint8_t *buf, uint16_t num)
{
//uint8_t ret;
uint16_t i;
i2c_Start();
i2c_SendByte(slave);
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(reg_add);
if(i2c_WaitAck())
{
return 0;
}
i2c_Start();
i2c_SendByte(slave|0x01);
if(i2c_WaitAck())
{
return 0;
}
for(i=0;i<(num-1);i++){
*buf=i2c_ReadByte(1);
buf++;
}
*buf=i2c_ReadByte(0);
i2c_Stop();
return 1;
}
#if 1//defined(QST_CONFIG_JHM1200)
uint8_t jhm1200_iic_write(uint8_t Addr, uint8_t* Buff, uint8_t Len)
{
uint8_t i;
i2c_Start();
i2c_SendByte(0xf0);
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(Addr);
if(i2c_WaitAck())
{
return 0;
}
for(i=0;i<Len;i++)
{
i2c_SendByte(Buff[i]);
if(i2c_WaitAck())
{
return 0;
}
}
i2c_Stop();
return 1;
}
uint8_t jhm1200_iic_read(uint8_t *pData, uint16_t Length)
{
uint8_t i;
i2c_Start();
i2c_SendByte(0xf1);
if(i2c_WaitAck())
{
return 0;
}
for(i=0;i<(Length-1);i++){
*pData=i2c_ReadByte(1);
pData++;
}
*pData=i2c_ReadByte(0);
i2c_Stop();
return 1;
}
#endif