蓝桥杯单片机----学习六之IIC协议PCF8591、AT24C04(STC15F2K60S2)

一、原理图                           

                                                                                                                                                                                                                                                                                                                                                                                   

二、软件模拟IIC

        IIC协议是一种同步、串行、半双工的通信协议,使用两根线:SDA(数据线)和SCL(时钟线)。主设备控制时钟线,负责发起和终止传输。从设备通过地址识别。

        初始化GPIO的话,需要将SDA和SCL设置为输出模式,并且初始状态是高电平,因为IIC总线在空闲时这两根线都是高电平。可能需要配置上拉电阻,确保总线空闲时能拉高。也需要配置GPIO的模式为开漏输出,这样才方便实现线与逻辑。这点可能需要特别注意,否则可能无法正确读取数据。

1、开始和终止信号

        IIC的起始信号是在SCL高电平期间,SDA从高变低。所以模拟的时候,首先确保SCL为高,然后拉低SDA,接着再拉低SCL,准备后续的数据传输。需要严格按照时序来,可能需要插入一些延时,保证信号稳定。

void I2CStart(void)
{
    sda = 1;
    scl = 1;	//拉高释放总线
	I2C_Delay(DELAY_TIME);	//延时
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

        停止信号是在SCL高电平期间,SDA从低变高。所以主设备需要先拉低SCL,然后拉低SDA,再拉高SCL,最后在SCL高的时候拉高SDA。

void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

2、数据发送

        IIC的数据是在SCL高电平时稳定的,数据的变化只能在SCL低电平时进行。每个字节传输8位,高位在前。主设备在SCL低电平时改变SDA,然后拉高SCL,从设备在SCL高电平时读取SDA。之后需要等待一个时钟周期,可能还需要检测从设备的应答信号。应答信号是在每个字节后,发送方释放SDA(变为输入模式),接收方在第九个时钟周期拉低SDA表示应答。这里模拟的时候,主设备发送完8位后,需要切换SDA为输入,等待从设备的应答,检测SDA是否为低,然后再切回输出模式继续发送。        

void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){		//由高位到地位依次发送
        scl = 0;		//拉低传输数据
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;		//拉高稳定
        byt <<= 1;		//下一位数据
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

3、应答信号

应答:数据发送信号(低电平),表示成功接收到数据,且可以继续接收。
非应答:数据接收方发送信号(高电平),表示由于某些原因不再接收数据

unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);	
    ackbit = sda; //若为1时表示接收完成
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}
void I2CSendAck(unsigned char ackbit)	//主动发送应答
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

4、接收数据信号

        数据的读取是在SCL高电平期间(稳定),此时数据不在变化。读取完成后需主动发送应答信号来结束读取。

unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   //8位数据由高位开始
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

三、PCF8591(A/D、D/A)

 1、器件地址:

        高4位固定,后面3位对应器件引脚连接地址,蓝桥杯板子均接地(置0),最后一位控制读写操作(1为读,0为写)。

2、控制字节

第7位:固定值0;

第6位:0—A/D转换,1—D/A转换;

第5、4位:00—四路单端输入,01—三路差分输入,10—两路单端,一路差分,11—两路差分输入;

第3位:固定值0;

第2位:0—禁止自动增量,1—允许自动增量;

第1、0位:00—选择AIN0,01—选择AIN1,10—选择AIN2,11—选择AIN3.

 3、数据收发

unsigned char PCF8591_ADC(unsigned char channel)
{
	unsigned char dat;
	I2CStart();
	I2CSendByte(0x90);	//发送写地址
	I2CWaitAck();
	if(channel == 1)		//选择通道
		I2CSendByte(0x01);
	else if(channel == 3)
		I2CSendByte(0x03);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0x91);	//发送读
	I2CWaitAck();
	dat = I2CReceiveByte();		//接收数据
	I2CWaitAck();
	I2CSendAck(1);	//发送非应答信号
	I2CStop();
	return dat;
}
void PCF8591_DAC(unsigned char dat)
{
	I2CStart();
	I2CSendByte(0x90);	//发送写
	I2CWaitAck();
	I2CSendByte(0x40);	//打开DAC通道
	I2CWaitAck();	
	I2CSendByte(dat);	//发送数据
	I2CWaitAck();
	I2CSendAck(1);		//此处可删除
	I2CStop();
}

 四、AT24C04

1、器件地址

        注意:蓝桥杯板子位24C02。

2、向EEPROM写入数据

        该芯片使用9位地址进行数据寻址。

void AT24C04_write_page(unsigned char add,unsigned char *dat)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(add);
	I2CWaitAck();	
	I2CSendByte(dat[0]);
	I2CWaitAck();
	//I2CSendAck(1);
	I2CStop();
}

3、从指定地址读取数据

void AT24C04_read_page(unsigned char add,unsigned char *dat)
{
	
	I2CStart();
	I2CSendByte(0xa0);	//写操作
	I2CWaitAck();
	I2CSendByte(add);	//指定地址
	I2CWaitAck();	
	I2CStart();
	I2CSendByte(0xa1);	//读
	I2CWaitAck();
	dat[0] = I2CReceiveByte();	
	I2CSendAck(1);
	I2CStop();	
}

 tips:在数据读取时注意定时器中断,可能干扰IIC时序,最好在读取时关闭中断,结束后打开中断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值