一.实验目的、内容、仪器
实验内容:利用定时器产生一个0~99秒变化的秒表,并且显示在数码管上,每过一秒,将这个变化的数写入板上AT24C02内部,当关闭实验板电源,并再次打开实验版电源时,单片机先从AT24C02中将原来写入的数取出来,接着此数继续变化并显示在数码管上。
- 上电后,从AT24C02 10H开始,连续读取六个字节的数据,将该六个字节内容显示到lcd1602的一行。
- 接收到串口发过来的6个字符数据(0-9)后,将该六个字符写到AT24C02从10H开始的连续六个字节单元中。
- 将收到的串口字符显示在LCD1602的第一行
- 重新上电,观察lcd1602的显示,看是否修改数据成功且保存在了AT24C02的指定存储单元
-
二.程序流程图
三.代码实现
#include<reg51.h>
#include<intrins.h>
#include"iic.h"
u8 numer[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
u8 display[4];
sbit A1=P2^2;
sbit B1=P2^3;
sbit C1=P2^4;
#define SHUMA P0
sbit K1=P3^0;//保存
sbit K2=P3^1;//读取
sbit K3=P3^2;//num++
sbit K4=P3^3;//清零
u8 num;
void delay(u16 i)
{
while(i--);
}
void shumaguan(u8 word[])
{ u8 i;
for(i=0;i<4;i++)
{
switch(i)
{
case 0:C1=0;B1=0;A1=0;break;
case 1:C1=0;B1=0;A1=1;break;
case 2:C1=0;B1=1;A1=0;break;
case 3:C1=0;B1=1;A1=1;break;
}
SHUMA=word[i];
delay(100);
SHUMA=0x00;
}
}
void Key(u8 dat)
{
if(K1==0)
{
delay(1000);
if(K1==0)
At24CO2Write(dat,1);
while(!K1);
}
if(K2==0)
{
delay(1000);
if(K2==0)
num=At24CO2Read(1);
while(!K2);
}
if(K3==0)
{
delay(1000);
if(K3==0)
num++;
while(!K3);
}
if(K4==0)
{
delay(1000);
if(K4==0)
num=0;
while(!K4);
}
}
void change()
{
display[0]=numer[num/1000];
display[1]=numer[(num%1000)/100];
display[2]=numer[(num%100)/10];
display[3]=numer[num%10];
}
void main()
{
while(1)
{
Key(num);
change();
shumaguan(display);
}
}
//iic.c
#include<reg51.h>
#include"iic.h"
void delay10us(void)
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
void I2cStart() //开始函数,时钟信号始终为高,当数据线由高变低时开始
{
SDA=1;
delay10us();
SCL=1;
delay10us();
SDA=0;
delay10us();
SCL=0;
delay10us();
}
void I2cStop() //停止函数,时钟信号始终为高,当数据线由低变高时开结束
{
SDA=0;
delay10us();
SCL=1;
delay10us();
SDA=1;
delay10us();
}
u8 I2cSend(u8 dat)
{
u8 i,b;
for(i=0;i<8;i++)
{
SDA=dat>>7;
delay10us();
dat<<=1;
SCL=1;
delay10us();
SCL=0;
delay10us();
}
SDA=1;
delay10us();
SCL=1;
while(SDA)
{
b++;
if(b>5){SCL=0;delay10us();return 0;}
}
SCL=0;
delay10us();
return 1;
}
u8 I2cRead()
{
u8 i,dat;
for(i=0;i<8;i++)
{
SCL=1;
delay10us();
dat<<=1;
dat|=SDA;
SCL=0;
delay10us();
}
return dat;
}
void At24CO2Write(u8 dat,u8 addr)
{
I2cStart();
I2cSend(0xa0);
I2cSend(addr);
I2cSend(dat);
I2cStop();
}
u8 At24CO2Read(u8 addr)
{
u8 num;
I2cStart();
I2cSend(0xa0);
I2cSend(addr);
I2cStart();
I2cSend(0xa1);
num=I2cRead();
I2cStop();
return num;
}
//iic.h
#ifndef_IIC_H
#define_IIC_H
#include<reg51.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit SDA=P1^0;
sbit SCL=P1^1;
void At24c02Write(u8 dat,u8 addr);
u8 At24c02Write(u8 addr);
#endif
四.实验步骤
(1) 独立按键分别进行num++,保存,清零,读取操作;
(2) 使单片机获得数据并与24C02进行数据传输;
(3) 向AT24C02某一存储单元写入1个字节数据,过程如下:
① 主机发送一个起始信号,启动发送过程;
② 主机发送7 位从机地址和1位写控制位;
③ 从机发应答位。在主机发送起始信号和从机地址字节后,AT24C02监视总线并当其地址与发送的从地址相符时,响应一个应答信号。在第9个时钟,将SDA 线拉为低电平;
④ 主机接收到应答位后,发从机子地址高8位(为AT24C02某一存储单元地址);
⑤ 从机接收完高8位子地址后,发应答位;
⑥ 主机接收到应答位后,发从机子地址低8位;
⑦ 从机接收完低8位子地址后,发应答位;
⑧ 主机接收到应答位后,发送待8位写入数据;
⑨ 从机接收完8数据后,发应答位,并开始内部数据的擦写;
⑩ 主机接收到应答位后,发停止位,结束传送,总线挂起。
(4) 通过LED数码管把数据显示出来。
五.结果及讨论
若向AT24C02中写入且成功读取,则数码管上显示的数会接着关闭实验板时的数继续显示,否则可能显示乱码。