首先简单操作一下0x09寄存器,看一下官方的手册0x09的寄存器手册

主要修改7bit数据,取消待机的使能,不然ip2366没有输入以后会直接进入低功耗模式,只有按动微动开关才能启动芯片。使用很不方便。

首先是软IIC程序

//softiic.h文件
#ifndef __SOFTIIC_H
#define __SIFTIIC_H

void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(uint8_t Byte);
uint8_t IIC_ReceiveByte(void);
void IIC_SendAck(uint8_t AckBit);
uint8_t IIC_ReceiveAck(void);



#endif

软iic的c文件

//softiic.c
#include "air32f10x.h"                  // Device header
#include "delay.h"

void IIC_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, (BitAction)BitValue);
	Delay_Us(10);
}

void IIC_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOC, GPIO_Pin_15, (BitAction)BitValue);
	Delay_Us(10);
}

uint8_t IIC_R_SDA(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_15);
	Delay_Us(10);
	return BitValue;
}

void IIC_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOC, GPIO_Pin_14 | GPIO_Pin_15);
}

void IIC_Start(void)
{
	IIC_W_SDA(1);
	IIC_W_SCL(1);
	IIC_W_SDA(0);
	IIC_W_SCL(0);
}

void IIC_Stop(void)
{
	IIC_W_SDA(0);
	IIC_W_SCL(1);
	IIC_W_SDA(1);
}

void IIC_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)
	{
		IIC_W_SDA(Byte & (0x80 >> i));
		IIC_W_SCL(1);
		IIC_W_SCL(0);
	}
}

uint8_t IIC_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;
	IIC_W_SDA(1);
	for (i = 0; i < 8; i ++)
	{
		IIC_W_SCL(1);
		if (IIC_R_SDA()) {Byte |= (0x80 >> i);}
		IIC_W_SCL(0);
	}
	return Byte;
}

void IIC_SendAck(uint8_t AckBit)
{
	IIC_W_SDA(AckBit);
	IIC_W_SCL(1);
	IIC_W_SCL(0);
}

uint8_t IIC_ReceiveAck(void)
{
	uint8_t AckBit;
	IIC_W_SDA(1);
	IIC_W_SCL(1);
	AckBit = IIC_R_SDA();
	IIC_W_SCL(0);
	return AckBit;
}

然后根据IP2366时序图加上延时

示例代码:

#define IP2366_ADDRESS			0xEA        //IP2366IIC地址

//IP2366读寄存器
//RegAddress;寄存器地址
//返回值:返回对应地址的寄存器读数
uint8_t IP2366_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	
	IIC_Start();
	IIC_SendByte(IP2366_ADDRESS);
	IIC_ReceiveAck();
	Delay_Us(50);
	IIC_SendByte(RegAddress);
	IIC_ReceiveAck();
	Delay_Us(50);
	IIC_Start();
	IIC_SendByte(IP2366_ADDRESS | 0x01);
	IIC_ReceiveAck();
	Delay_Us(50);
	Data = IIC_ReceiveByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return Data;
}

//IP2366读寄存器
//RegAddress;寄存器地址
//Data:准备修改的数据
void IP2366_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	uint8_t yuan;
	yuan=IP2366_ReadReg(RegAddress);              //先读取需要修改的寄存器的值
	Delay_Ms(1);                                  //需要单字节读取,每次读取后需要等待1ms
	IIC_Start();
	IIC_SendByte(IP2366_ADDRESS);
	IIC_ReceiveAck();
	Delay_Us(50);
	IIC_SendByte(RegAddress);
	IIC_ReceiveAck();
	Delay_Us(50);
	IIC_SendByte(yuan&Data);
	IIC_ReceiveAck();
	IIC_Stop();
}

main函数

uint16_t read=0;

int main(void)
{
	RCC_ClkConfiguration();		//配置时钟(air32配置时钟频率,其他mcu可以忽略)
	Delay_Init();			//延时初始化
	IIC_Init();                     //IIC初始化

	OLED_Init();                    //OLED屏幕初始化

	read=IP2366_ReadReg(0x09);     //首先读一下0x09寄存器数值并显示
		
	OLED_ShowBinNum(1, 1, read, 8);
	
	Delay_S(1);                    //等待1s
	
	IP2366_WriteReg(0x09,0x00);    //写0x09寄存器输出为0

	
	read=IP2366_ReadReg(0x09);     //再次读取修改后寄存器的值
	
		
	OLED_ShowBinNum(2, 1, read, 8);//在OLED第二行显示修改后读取到的寄存器值
	

	while (1)
	{

	}
}

然后用逻辑分析仪抓一下波形

先发送设备地址0xEA等待应答延时50us,然后发送寄存器地址0x09等待应答延时50us,发送写入的数据,结束通讯。这里一定要注意因为IP2366的IIC寄存器是需要先读取然后在读取到的值的基础上修改需要更改的bit,如果直接写数据可能会造成不可预知的后果。

还有一点就是因为写操作是需要先读取寄存器那几位未开放寄存器的值的,一定要在读取后增加1ms的延时,不然后面的修改操作可能会不成功,也要关注IP2366的ACK应答情况如果没有增加1ms延时的话可能会出现无应答情况,后续的操作都会失败。

看一下最后整体的运行图片

读取后延时