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