我的解答
iic
iic.h
#ifndef __IIC_H__
#define __IIC_H__
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void AT24C02_Write(unsigned char Address,Data);
unsigned char AT24C02_Read(unsigned char Address);
unsigned char PCF8591_Read(unsigned char Address);
void Delay(unsigned char x);
#endif
下面展示一些 内联代码片
。
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
void AT24C02_Write(unsigned char Address,Data)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(Address);
IIC_WaitAck();
IIC_SendByte(Data);
IIC_WaitAck();
IIC_Stop();
}
unsigned char AT24C02_Read(unsigned char Address)
{
unsigned char Data;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(Address);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
Data=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return Data;
}
unsigned char PCF8591_Read(unsigned char Address)
{
unsigned char Data;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(Address);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
Data=IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return Data;
}
void Delay(unsigned char x) //@12.000MHz
{
unsigned char i, j;
while(x--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
ds1302
下面展示一些 内联代码片
。
ds1302.h
#include <STC15F2K60S2.H>
#define DS1302_Sec 0x80
#define DS1302_Min 0x82
#define DS1302_Hou 0x84
#define DS1302_WP 0x8E
sbit DS1302_SCLK=P1^7;
sbit DS1302_IO=P2^3;
sbit DS1302_CE=P1^3;
unsigned char DS1302_Time[3]={23,59,55};
void DS1302_Init()
{
DS1302_CE=0;
DS1302_SCLK=0;
}
void DS1302_WriteByte(unsigned char Command,Data)
{
unsigned char i;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<<i);
DS1302_SCLK=0;
DS1302_SCLK=1;
}
for(i=0;i<8;i++)
{
DS1302_IO=Data&(0x01<<i);
DS1302_SCLK=0;
DS1302_SCLK=1;
}
DS1302_CE=0;
}
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i,Data=0x00;
Command|=0x01;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<<i);
DS1302_SCLK=0;
DS1302_SCLK=1;
}
for(i=0;i<8;i++)
{
DS1302_SCLK=1;
DS1302_SCLK=0;
if(DS1302_IO){Data|=(0x01<<i);};
}
DS1302_IO=0;
DS1302_CE=0;
return Data;
}
void SetTime()
{
unsigned char Temp;
DS1302_WriteByte(DS1302_WP,0x00);
Temp=DS1302_Time[0];
DS1302_WriteByte(DS1302_Hou,Temp/10*16+Temp%10);
Temp=DS1302_Time[1];
DS1302_WriteByte(DS1302_Min,Temp/10*16+Temp%10);
Temp=DS1302_Time[2];
DS1302_WriteByte(DS1302_Sec,Temp/10*16+Temp%10);
DS1302_WriteByte(DS1302_WP,0x80);
}
void ReadTime()
{
unsigned char Temp;
Temp=DS1302_ReadByte(DS1302_Hou);
DS1302_Time[0]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_Min);
DS1302_Time[1]=Temp/16*10+Temp%16;
Temp=DS1302_ReadByte(DS1302_Sec);
DS1302_Time[2]=Temp/16*10+Temp%16;
}
main
main.c
#include <STC15F2K60S2.H>
#include "iic.h"
#include "ds1302.h"
sbit L1=P3^0;
sbit L2=P3^1;
sbit L3=P3^2;
sbit L4=P3^3;
sbit C1=P4^4;
sbit C2=P4^2;
sbit C3=P3^5;
sbit C4=P3^4;
typedef unsigned char u8;
typedef unsigned int u16;
/*----------数码管----------*/
u8 code ledguan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 weixuan,disp[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
/*----------按键----------*/
u8 KN,KTN;
u8 Key();
u8 GetState();
void Key_Loop();
/*----------Rb2----------*/
u8 Rb2,Rb2_count;
/*----------AT24C02----------*/
u8 EEP;
/*----------555测频率----------*/
u16 frq,time;
u16 zheng,fan,zheng_now,fan_now;
bit flag_frq;
/*----------主程序----------*/
u8 Mode;//0:时钟模式 1:电压测量 2:频率测量 3:查询
u8 an_4_count;//按下S4的次数
u8 hour,min,sec;//用于修改的时间
u8 VH=20,VL=10;//V的最大值和最小值
u8 shijian=0;//判断事件是0还是1
u8 sj_hour,sj_min,sj_sec;//事件发生的时间
void Timer0Init(void);
void Timer1Init(void);
void main()
{
/*----------初始化----------*/
P2=0x80;P0=0xff;P2=0x00;//LED灯熄灭
//DS1302初始化
DS1302_Init();
SetTime();
//把作品交上去之前先更新一下
// AT24C02_Write(1,20);
// Delay(5);
// AT24C02_Write(2,10);
// Delay(5);
//EEPROM读取
ET0=0;
VH=AT24C02_Read(1);
VL=AT24C02_Read(2);
shijian=AT24C02_Read(3);
sj_hour=AT24C02_Read(4);
sj_min=AT24C02_Read(5);
sj_sec=AT24C02_Read(6);
ET0=1;
//定时器初始化读取
Timer0Init();
Timer1Init();
while(1)
{
//时间读取
ET0=0;
ReadTime();
ET0=1;
/*----------按键模块----------*/
KTN=Key();
if(KTN)
{
/*----------按下S7----------*/
if(KTN==7)
{
Mode=0;//时钟模块
//在已经按过S4的前提下,更新时间数据
if(an_4_count)
{
DS1302_Time[0]=hour;
DS1302_Time[1]=min;
DS1302_Time[2]=sec;
SetTime();
}
//S4按键按下次数清零
an_4_count=0;
}
/*----------按下S6----------*/
if(KTN==6)
{
Mode=1;//电压测量模式
//在已经按过S4的前提下,更新电压阈值数据
if(an_4_count)
{
AT24C02_Write(1,VH);
Delay(5);
AT24C02_Write(2,VL);
Delay(5);
}
//S4按键按下次数清零
an_4_count=0;
}
/*----------按下S5----------*/
if(KTN==5)
{
Mode=2;//频率测量模式
an_4_count=0;//S4按键按下次数清零
}
/*----------按下S4----------*/
if(KTN==4)
{
//时钟模式下
if(Mode==0)
{
//第一次按下
if(an_4_count==0)
{
//数码管显示当前数据,时间停止 The World!
hour=DS1302_Time[0];
min=DS1302_Time[1];
sec=DS1302_Time[2];
}
//S4anxia次数增加
an_4_count++;
//0 1 2 3 1 2 3 1
if(an_4_count==4)an_4_count=1;
}
//频率测量模式下
if(Mode==1)
{
an_4_count++;
if(an_4_count==3)an_4_count=1;
}
//查看模式下
if(Mode==3)
{
an_4_count++;
if(an_4_count==3)an_4_count=1;
}
}
//如果按下S9,进入查询模式
if(KTN==9)
{
Mode=3;
an_4_count=0;
}
//如果按下S11
if(KTN==11)
{
//如果按过S4,并且时钟模式
if(an_4_count&&!Mode)
{
//如果按过一次,小时增加
if(an_4_count==1)
{
hour++;
if(hour>=24)
hour=0;
}
//如果按过俩次,分钟增加
if(an_4_count==2)
{
min++;
if(min>=60)
min=0;
}
//如果按过仨次,分钟增加
if(an_4_count==3)
{
sec++;
if(sec>=60)
sec=0;
}
}
//如果按过S4,并且电压测量模式
if((Mode==1)&&an_4_count)
{
//如果按过一次,电压最高阈值增加
if(an_4_count==1)
{
VH+=5;
}
//如果按过俩次,电压最低阈值增加
if(an_4_count==2)
{
VL+=5;
}
}
}
//同理
if(KTN==10)
{
if(an_4_count&&!Mode)
{
if(an_4_count==1)
{
if(hour==0)hour=23;
else hour--;
}
if(an_4_count==2)
{
if(min==0)min=59;
else min--;
}
if(an_4_count==3)
{
if(sec==0)sec=59;
else sec--;
}
}
if((Mode==1)&&an_4_count)
{
if(an_4_count==1)
{
VH-=5;
}
if(an_4_count==2)
{
VL-=5;
}
}
}
}
//时钟模式
if(!Mode)
{
disp[2]=0xbf;
disp[5]=0xbf;
//如果按过S4
if(an_4_count)
{
//按一次,闪烁
if(an_4_count==1)
{
if(DS1302_Time[2]%=2)
{
disp[0]=ledguan[hour/10%10];
disp[1]=ledguan[hour%10];
}
else
{
disp[0]=0xff;
disp[1]=0xff;
}
}
else
{
disp[0]=ledguan[hour/10%10];
disp[1]=ledguan[hour%10];
}
//同理
if(an_4_count==2)
{
if(DS1302_Time[2]%=2)
{
disp[3]=ledguan[min/10%10];
disp[4]=ledguan[min%10];
}
else
{
disp[3]=0xff;
disp[4]=0xff;
}
}
else
{
disp[3]=ledguan[min/10%10];
disp[4]=ledguan[min%10];
}
//同理
if(an_4_count==3)
{
if(DS1302_Time[2]%=2)
{
disp[6]=ledguan[sec/10%10];
disp[7]=ledguan[sec%10];
}
else
{
disp[6]=0xff;
disp[7]=0xff;
}
}
else
{
disp[6]=ledguan[sec/10%10];
disp[7]=ledguan[sec%10];
}
}
else
{
disp[0]=ledguan[DS1302_Time[0]/10%10];
disp[1]=ledguan[DS1302_Time[0]%10];
disp[3]=ledguan[DS1302_Time[1]/10%10];
disp[4]=ledguan[DS1302_Time[1]%10];
disp[6]=ledguan[DS1302_Time[2]/10%10];
disp[7]=ledguan[DS1302_Time[2]%10];
}
}
//电压测量模式
if(Mode==1)
{
if(Rb2_count==200)
{
Rb2_count=0;
Rb2=PCF8591_Read(0x03);
Rb2=(u8)(Rb2*50.0/255.0);
}
if(an_4_count)
{
//同理
if(an_4_count==1)
{
if(DS1302_Time[2]%=2)
{
disp[0]=ledguan[VH/10%10];
disp[1]=ledguan[VH%10];
disp[2]=ledguan[0];
disp[3]=ledguan[0];
}
else
{
disp[0]=0xff;
disp[1]=0xff;
disp[2]=0xff;
disp[3]=0xff;
}
}
else
{
disp[0]=ledguan[VH/10%10];
disp[1]=ledguan[VH%10];
disp[2]=ledguan[0];
disp[3]=ledguan[0];
}
//同理
if(an_4_count==2)
{
if(DS1302_Time[2]%=2)
{
disp[4]=ledguan[VL/10%10];
disp[5]=ledguan[VL%10];
disp[6]=ledguan[0];
disp[7]=ledguan[0];
}
else
{
disp[4]=0xff;
disp[5]=0xff;
disp[6]=0xff;
disp[7]=0xff;
}
}
else
{
disp[4]=ledguan[VL/10%10];
disp[5]=ledguan[VL%10];
disp[6]=ledguan[0];
disp[7]=ledguan[0];
}
}
else
{
if(Rb2>VH)
{
shijian=1;
sj_hour=DS1302_Time[0];
sj_min=DS1302_Time[1];
sj_sec=DS1302_Time[2];
AT24C02_Write(3,1);
Delay(5);
AT24C02_Write(4,sj_hour);
Delay(5);
AT24C02_Write(5,sj_min);
Delay(5);
AT24C02_Write(6,sj_sec);
Delay(5);
}
if(Rb2<VL)
{
shijian=0;
sj_hour=DS1302_Time[0];
sj_min=DS1302_Time[1];
sj_sec=DS1302_Time[2];
AT24C02_Write(3,0);
Delay(5);
AT24C02_Write(4,sj_hour);
Delay(5);
AT24C02_Write(5,sj_min);
Delay(5);
AT24C02_Write(6,sj_sec);
Delay(5);
}
disp[0]=0xbf;
disp[1]=ledguan[1];
disp[2]=0xbf;
disp[3]=0xff;
disp[4]=ledguan[Rb2/10%10];
disp[5]=ledguan[Rb2%10];
disp[6]=ledguan[0];
disp[7]=ledguan[0];
}
}
//频率测量
if(Mode==2)
{
disp[0]=0xbf;
disp[1]=ledguan[2];
disp[2]=0xbf;
disp[3]=ledguan[frq/10000%10];
disp[4]=ledguan[frq/1000%10];
disp[5]=ledguan[frq/100%10];
disp[6]=ledguan[frq/10%10];
disp[7]=ledguan[frq%10];
}
//查询
if(Mode==3)
{
if(an_4_count==2)
{
disp[0]=ledguan[sj_hour/10%10];
disp[1]=ledguan[sj_hour%10];
disp[2]=0xbf;
disp[3]=ledguan[sj_min/10%10];
disp[4]=ledguan[sj_min%10];
disp[5]=0xbf;
disp[6]=ledguan[sj_sec/10%10];
disp[7]=ledguan[sj_sec%10];
}
else
{
disp[0]=0xff;
disp[1]=0xff;
disp[2]=0xff;
disp[3]=0xff;
disp[4]=0xff;
disp[5]=0xff;
disp[6]=ledguan[0];
disp[7]=ledguan[shijian];
}
}
}
}
u8 Key()
{
u8 Temp;
Temp=KN;
KN=0;
return Temp;
}
u8 GetState()
{
u8 State=0;
C1=0;C2=1;C3=1;C4=1;
if(L1==0)State=7;
if(L2==0)State=6;
if(L3==0)State=5;
if(L4==0)State=4;
C1=1;C2=0;C3=1;C4=1;
if(L1==0)State=11;
if(L2==0)State=10;
if(L3==0)State=9;
return State;
}
void Key_Loop()
{
static u8 Now,Last;
Last=Now;
Now=GetState();
if(!Now&&Last)
{
KN=Last;
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR = 0xc0; //定时器时钟1T模式
TMOD = 0x00; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void Timer1Init(void) //5微秒@12.000MHz
{
AUXR = 0xc0; //定时器时钟1T模式
TMOD = 0x00; //设置定时器模式
TL1 = 0xC4; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 0;
}
void Timer0_R() interrupt 1
{
static u8 smg_count,key_count;
static u16 frq_count;
smg_count++;key_count++;Rb2_count++;
if(Mode==2)
{
frq_count++;
}
else
{
frq_count=0;
}
if(smg_count==2)
{
smg_count=0;
P2=0xC0;P0=1<<weixuan;P2=0x00;
P2=0xE0;P0=0xff;P2=0x00;
P2=0xE0;P0=disp[weixuan++];P2=0x00;
weixuan%=8;
}
if(key_count==20)
{
key_count=0;
Key_Loop();
}
if(frq_count>969)
{
TR1=1;
ET1=1;
if(frq_count>999)
{
frq_count=0;
TR1=0;
ET1=0;
time=5*(zheng_now+fan_now);
frq=1000000/time;
}
}
}
void Timer1_R() interrupt 3
{
if(P34==1)
{
zheng++;
if(flag_frq)
{
flag_frq=0;
fan_now=fan;
fan=0;
}
}
if(P34==0)
{
fan++;
if(!flag_frq)
{
flag_frq=1;
zheng_now=zheng;
zheng=0;
}
}
}