蓝桥杯AT24C02运用IIC总线

首先在咱们蓝桥杯单片机当中,STC15S2当中,他是运用外设AT24C02,EEPROM来储存我们所写的数据,比如,当你在写一个数码管显示数字,然后按下按键来驱使数码管进行加加,然后在按下另一个按键使数码管的程序保存到EEPROM当中,所以我们要来驱动这个程序。那么这个程序应该怎么来写呢?

这是AT24C02的数据线和时钟线,用上拉电阻来驱动。而A0 A1 A2 用地来接,

串行时钟信号引脚(SCL):在 SCL输入时钟信号的上升沿将数据送入 EEPROM器件,并在时钟的下降沿将数据 读出。 串行数据输入/输出引脚(SDA):SDA 引脚可实现双向串行数据传输。该引脚为开漏输出,可与其它多个开漏 输出器件或开集电极器件线或连接

相关引脚名字注意:各个引脚的功能

下面我来介绍一下我自己出的这个题的的程序,代码我先放在这里

#include <STC15F2K60S2.H>
#include <SDA.H>

sbit S7 = P3^0;
sbit S6 = P3^1;


unsigned char code SMG_Dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned int code  SMG_duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//SMG断码

unsigned char model = 20;
	
void Seclect_HC138(unsigned char channl)
{
	switch(channl)
	{
		case 4:
			P2 = (P2&0X1F)|0X80;
		break;
		case 5:
			P2 = (P2&0X1F)|0XA0;
		break;
		case 6:
			P2 = (P2&0X1F)|0XC0;
		break;
		case 7:
			P2 = (P2&0X1F)|0XE0;
		break;
		case 8:
			P2 = (P2&0X1F)|0X00;
		break;
	}
}

void Init_SMG(unsigned char date,unsigned char pos)
{
	Seclect_HC138(6);
	P0 = 0X01 << pos;
	Seclect_HC138(7);
	P0 = date;

}

void delay(unsigned char i)
{
	unsigned char x,y;
	for(x=i;x>0;x--)	
		for(y=114;y>0;y--);
	
}

void SMG_show()
{
	Init_SMG(SMG_duanma[model / 10],0);
	delay(20);
	Init_SMG(SMG_duanma[model % 10],1);
	delay(20);
}

void Write_SDA(unsigned char adad,unsigned char adar)
{

	I2CStart();
	I2CSendByte(0XA0);
	I2CWaitAck();
	I2CSendByte(adad);
	I2CWaitAck();
	I2CSendByte(adar);
	I2CWaitAck();
	I2CStop();
}

unsigned char Read_SDA(unsigned char addr)
{
	unsigned char sda_out;
	I2CStart();
	I2CSendByte(0XA0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();

	I2CStart();
	I2CSendByte(0XA1);
	I2CWaitAck();
	sda_out=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return sda_out;
}
void eeprom_w()
{
	Write_SDA(0X01,model);
	 delay(10);	

}

void eeprom_r()
{
	model = Read_SDA(0x01);
delay(10);	
}

void KEY()
{
	if(S7 == 0)
	{
		delay(10);
		if(S7 == 0)
		{
		
			model++;
		eeprom_w();
			while(S7==0)
			{
				SMG_show();
			}
		}
		while(S7==0)
		{
			SMG_show();
		}
	}
	if(S6 == 0)
	{
		delay(10);
		
			if(S6==0)
			{
			eeprom_r();
				while(S6==0)
			{
				SMG_show();
			}
			
			}
		while(S6==0)
		{
		SMG_show();
		}
	}



}



void main()
{
	eeprom_r();
	while(1)
	{
		KEY();
	 SMG_show();
	}
}


  IIC.C

/*    #   I2C代码片段说明
    1.     本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
    2.     参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
        中对单片机时钟频率的要求,进行代码调试和修改。
*/

#include <reg52.h>
#include <intrins.h>


#define DELAY_TIME    5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
sbit scl = P2^0;
sbit sda = P2^1;


//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();        
    }
    while(n--);          
}

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

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

//
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;  
}

//
unsigned char I2CReceiveByte(void)
{
    unsigned char da;
    unsigned char i;
    for(i=0;i<8;i++){   
        scl = 1;
        I2C_Delay(DELAY_TIME);
        da <<= 1;
        if(sda) 
            da |= 0x01;
        scl = 0;
        I2C_Delay(DELAY_TIME);
    }
    return da;    
}

//
unsigned char I2CWaitAck(void)
{
    unsigned char ackbit;
    
    scl = 1;
    I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    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);
}

#ifndef _iic_h_
#define _iic_h_

void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);

#endif

下面就是该程序实现的全部

然后,最主要的就是这一块代码:

void Write_SDA(unsigned char adad,unsigned char adar)
{

	I2CStart();
	I2CSendByte(0XA0);
	I2CWaitAck();
	I2CSendByte(adad);
	I2CWaitAck();
	I2CSendByte(adar);
	I2CWaitAck();
	I2CStop();
}

unsigned char Read_SDA(unsigned char addr)
{
	unsigned char sda_out;
	I2CStart();
	I2CSendByte(0XA0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();

	I2CStart();
	I2CSendByte(0XA1);
	I2CWaitAck();
	sda_out=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return sda_out;
}
void eeprom_w()
{
	Write_SDA(0X01,model);
	 delay(10);	

}
  1. 它分为写函数,读函数。写保护(WP)引脚:24C01/02/04/08/16 具有用于硬件数据写保护功能的引脚。当该引脚接 GND时,允许正常 的读/写操作。当该引脚接 VCC 时,芯片启动写保护功能
  2. 时钟及数据传输:SDA引脚通常被外围器件拉高。SDA引脚的数据应在 SCL为低时变化;当数据在SCL为高 时变化,将视为下文所述的一个起始或停止命令
  3. 起始命令:当 SCL为高,SDA由高到低的变化被视为起始命令,必须以起始命令作为任何一次读/写操作命令 的开始(参见图 5)
    停止命令:当 SCL为高,SDA 由低到高的变化被视为停止命令,在一个读操作后,停止命令会使 EEPROM进 入等待态低功耗模式(参见图 5)
  4. 应答:所有的地址和数据字节都是以 8 位为一组串行输入和输出的。每收到一组 8 位的数据后,EEPROM都 会在第 9 个时钟周期时返回应答信号。每当主控器件接收到一组 8 位的数据后,应当在第 9 个时钟周期向 EEPROM 返回一个应答信号。收到该应答信号后,EEPROM会继续输出下一组 8 位的数据。若此时没有得到主 控器件的应答信号,EEPROM会停止读出数据,直到主控器件返回一个停止命令来结束读周期。
  5. 等待模式:24C01/02/04/08/16特有一个低功耗的等待模式。可以通过以下方法进入该模式:(a)上电 ()收 到停止位并且结束所有的内部操作后。
  6. 器件复位:在协议中断、下电或系统复位后,器件可通过以下步骤复位:(1)连续输入 9 个时钟;(2)在 每个时钟周期中确保当 SCL为高时SDA也为高;(3)建立一个起始条件

相关时序图

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值