使用I2C软件,驱动mpu6050
#define GPIO_PORT_I2C GPIOB /* GPIO端口*/
#define RCC_I2C_PORT RCC_APB2Periph_GPIOB /* GPIO时钟*/
#define I2C_SCL_PIN GPIO_Pin_6 /* 连接SCL的GPIO */
#define I2C_SDA_PIN GPIO_Pin_7 /* 连接SDL的GPIO */
#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数据 */
static void i2c_Delay(void)
{
uint8_t i;
for (i = 0; i < 10; i++);
}
//当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号
void i2c_Start(void)
{
/* _____
*SDA \_____________
* __________
*SCL \________
*/
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
//当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号
void i2c_Stop(void)
{
/* _______
*SDA __________/
* ____________
*SCL _____/
*/
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
/*CPU向I2C总线设备发送8bit数据
*/
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送高7位,*/
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
I2C_SDA_1();//发送的1
}
else
{
I2C_SDA_0();//发送的0
}
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1(); //释放总线
}
_ucByte <<= 1; /*左移一个 bit */
i2c_Delay();
}
}
/*
CPU从I2C设备读取8bit数据
*/
uint8_t i2c_ReadByte(u8 ack)
{
uint8_t i;
uint8_t value;
/* 读取到第一个bit为数据的bit7 */
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ())
{
value++;
}
I2C_SCL_0();
i2c_Delay();
}
if(ack==0)
i2c_NAck();
else
i2c_Ack();
return value;
}
/*
CPU产生一个时钟,并读取器件的ACK应答信号
*/
uint8_t i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPU释放SDA总线 */
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_Delay();
return re;
}
/*
CPU产生一个ACK信号
*/
void i2c_Ack(void)
{
/* ____
*SCL ______/ \______
* ____ _____
*SDA \_______/
*/
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总线 */
}
/*
CPU产生1个NACK信号
*/
void i2c_NAck(void)
{
/* ____
*SCL ______/ \______
* __________________
*SDA
*/
I2C_SDA_1(); /* CPU驱动SDA = 1 */
i2c_Delay();
I2C_SCL_1(); /* CPU产生一个时钟 */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
/*
配置I2C总线的GPIO
*/
void i2c_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); //时钟
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);
//停止信号,复位I2C总线上的所有设备
i2c_Stop();
}
/*
CPU发送设备地址,然后读取设备应答是否有设备
*/
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_GPIO_Config(); /* 配置GPIO */
i2c_Start(); /*I2C开始信号*/
/* 发送设备地址和读写控制bit(0=写,1=读)bit7位先传 */
i2c_SendByte(_Address|I2C_WR);
ucAck = i2c_WaitAck(); /*检测设备应答 */
i2c_Stop(); /* I2C结束信号 */
return ucAck;
}
|
———————————————— 版权声明:本文为CSDN博主「为了维护世界和平_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/WANGYONGZIXUE/article/details/121503215