主函数
#include "stc15f2k60s2.h"
#include "driver.h"
#include "ds1302.h"
#include "sonic.h"
#include "display.h"
#include "iic.h"
uchar code SMG_TAB[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar SMG_WEI[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar time_display[8]; //时间显示
uchar wave_display[8]; //超声波距离显示
uchar set_display[8]; //时间设置显示
uchar setsonic_display[8]; //报警距离显示
uchar key_value; //键值
uchar display_mode; //显示模式
uchar mode; //时间设置页面下,选择具体的设置变量
uchar sonic_mode;
uchar shi,fen,miao; //时、分、秒
uchar flag_24c02;
extern long sonic_distance; //超声波距离/厘米
extern long lim_distance; //报警距离
extern bit sonic_flag;
extern bit time_flag; //时间显示标志
bit blink_flag; //闪烁标志位
void Timer0Init(); //1毫秒@11.0592MHz
void Blink(); //数码管闪烁
void set_add(); //加函数
void set_subtract(); //减函数
void sonic_baojing(); //距离报警函数
void Delay500ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 22;
j = 3;
k = 227;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
Timer0Init();
All_init();
DS1302_init();
init_set();
flag_24c02=Read_24c02(0x11);
if(flag_24c02==90) //保证第一次下载程序时,lim_distance是预设的初始值
lim_distance=Read_24c02(0x01);
else
{
lim_distance=30;
Write_24c02(0x11,90);
}
while(1)
{
Timer_Display();
Sonic_display();
settime_display();
Blink();
sonic_baojing();
key_value=key_init();
switch(key_value)
{
case 4:
set_subtract();
break;
case 5:
set_add();
break;
case 6:
if(display_mode==0)
display_mode=2; //时间设置界面
if(display_mode==1)
display_mode=3; //超声波报警距离调整界面
if(display_mode==2)
{
mode++;
if(mode==1) //读取当前时间
{
shi=(TIME[2]/16)*10+TIME[2]%16;
fen=(TIME[1]/16)*10+TIME[1]%16;
miao=(TIME[0]/16)*10+TIME[0]%16;
}
if(mode==3) //将设置后的时间写入1302
{
mode=0;
display_mode=0;
TIME[2]=shi/10*16+shi%10;
TIME[1]=fen/10*16+fen%10;
TIME[0]=miao/10*16+miao%10;
DS1302_init();
}
}
if(display_mode==3)
{
sonic_mode++;
if(sonic_mode==2)
{
sonic_mode=0;
display_mode=1;
}
}
break;
case 7:
display_mode++;
if(display_mode==2)
display_mode=0;
break;
}
}
}
void sonic_baojing()
{
if(display_mode==1)
{
if(sonic_distance<lim_distance) //距离小于报警距离
{
P2=(P2&0x1f)|0xa0;
P06=1; P04=0; //蜂鸣器响
P2=P2&0x1f;
}
else
{
P2=(P2&0x1f)|0xa0;
P06=0; P04=0;
P2=P2&0x1f;
}
if((lim_distance<sonic_distance)&&(sonic_distance<(1.2*lim_distance))) //距离小于1.2倍报警距离,L1闪烁
{
ledlight(0xfe);
Delay500ms();
ledlight(0xff);
Delay500ms();
}
}
}
void set_add()
{
if(display_mode==2) //时间设置模式
{
if(mode==1) //小时加
{
shi++;
if(shi==24)
shi=0;
}
if(mode==2) //分钟加
{
fen++;
if(fen==60)
fen=0;
}
}
if(display_mode==3) //报警距离加
{
lim_distance++;
Write_24c02(0x01,lim_distance);
}
}
void set_subtract()
{
if(display_mode==2)
{
if(mode==1) //小时减
{
if(shi>0)
shi--;
}
if(mode==2) //分钟减
{
if(fen>0)
fen--;
}
}
if(display_mode==3)
{
lim_distance--; //报警距离减
Write_24c02(0x01,lim_distance);
}
}
void Blink()
{
if(blink_flag)
{
if(display_mode==2)
{
if(mode==1)
{
set_display[0]=SMG_TAB[shi/10];
set_display[1]=SMG_TAB[shi%10];
}
if(mode==2)
{
set_display[3]=SMG_TAB[fen/10];
set_display[4]=SMG_TAB[fen%10];
}
}
}
else
{
if(display_mode==2)
{
if(mode==1)
{
set_display[0]=0x00;
set_display[1]=0x00;
}
else
{
set_display[0]=SMG_TAB[shi/10];
set_display[1]=SMG_TAB[shi%10];
}
if(mode==2)
{
set_display[3]=0x00;
set_display[4]=0x00;
}
else
{
set_display[3]=SMG_TAB[fen/10];
set_display[4]=SMG_TAB[fen%10];
}
}
}
}
void Timer0Init() //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
void timer0() interrupt 1
{
uchar smg_count;
uchar i;
uint sonic_count,init_count,blink_count;
sonic_count++;
smg_count++;
init_count++;
blink_count++;
if(smg_count==3)
{
smg_count=0;
P2=(P2&0X1F)|0XC0; //位选
P0=SMG_WEI[i];
P2=P2&0X1F;
if(display_mode==0)
{
P2=(P2&0X1F)|0XE0;
P0=~time_display[i];
P2=P2&0X1F;
}
if(display_mode==1)
{
P2=(P2&0X1F)|0XE0;
P0=~wave_display[i];
P2=P2&0X1F;
}
if(display_mode==2)
{
P2=(P2&0X1F)|0XE0;
P0=~set_display[i];
P2=P2&0X1F;
}
if(display_mode==3)
{
P2=(P2&0X1F)|0XE0;
P0=~setsonic_display[i];
P2=P2&0X1F;
}
i++;
if(i==8)
i=0;
}
if(sonic_count==200)
{
sonic_count=0;
sonic_flag=1;
}
if(init_count==1000)
{
init_count=0;
time_flag=1;
}
if(blink_count==400)
{
blink_count=0;
blink_flag=~blink_flag;
}
}
驱动
#include "driver.h"
void All_init()
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=P2&0X1F;
P2=(P2&0X1F)|0X80;
P0=0XFF;
P2=P2&0X1F;
}
void ledlight(uchar led)
{
P2=(P2&0X1F)|0X80;
P0=led;
P2=P2&0X1F;
}
#define key_state0 0
#define key_state1 1
#define key_state2 2
uchar key_init()
{
static uchar key_state=0;
uchar key_press, key_val=0;
key_press=P3&0x0f;
switch(key_state)
{
case key_state0:
if(key_press!=0x0f)
key_state=key_state1;
break;
case key_state1:
if(key_press!=0x0f)
{
if(key_press==0x0e) key_val=7;
if(key_press==0x0d) key_val=6;
if(key_press==0x0b) key_val=5;
if(key_press==0x07) key_val=4;
key_state=key_state2;
}
else
key_state=key_state0;
break;
case key_state2:
if(key_press==0x0f)
key_state=key_state0;
break;
}
return key_val;
}
DS1302模块
#include "ds1302.h"
/********************************************************************/
/*单字节写入一字节数据*/
unsigned char Write_addr[]={0x80,0x82,0x84};
unsigned char Read_addr[]={0x81,0x83,0x85};
unsigned char TIME[3]={0X59,0X50,0X11};
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte(dat); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
}
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
SD=0;
return temp;
}
void DS1302_init()
{
unsigned char i;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<3;i++)
{
Ds1302_Single_Byte_Write(Write_addr[i],TIME[i]);
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
void Read_time()
{
unsigned char i;
for(i=0;i<3;i++)
{
TIME[i]=Ds1302_Single_Byte_Read(Read_addr[i]);
}
}
超声波模块
#include "sonic.h"
#include "intrins.h"
void Delay13us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
unsigned int Rec_distance()
{
long count=0;
long UltraDistance=0; //最大距离
long i;
Echo=1;
for (i=0;i<10;i++)
{
Trig=~Trig; //产生连续的方波
Delay13us();
}
while(Echo)
{
count++;
if(count>=1000)
break;
}
UltraDistance=count/7;
return UltraDistance;
}
显示模块
#include "display.h"
#include "ds1302.h"
#include "driver.h"
#include "sonic.h"
bit time_flag;
bit sonic_flag;
long sonic_distance;
long lim_distance=30;
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void settime_display()
{
set_display[2]=0X40;
set_display[5]=0X40;
set_display[6]=SMG_TAB[miao/10];
set_display[7]=SMG_TAB[miao%10];
}
void Timer_Display()
{
if(time_flag)
{
Read_time();
time_display[0]=SMG_TAB[TIME[2]/16];
time_display[1]=SMG_TAB[TIME[2]%16];
time_display[2]=0X40;
time_display[3]=SMG_TAB[TIME[1]/16];
time_display[4]=SMG_TAB[TIME[1]%16];
time_display[5]=0X40;
time_display[6]=SMG_TAB[TIME[0]/16];
time_display[7]=SMG_TAB[TIME[0]%16];
}
}
void Sonic_display()
{
if(sonic_flag)
{
sonic_flag=0; //200ms读取一次
sonic_distance=Rec_distance();
}
wave_display[0]=0x00;
wave_display[1]=0x00;
wave_display[2]=0X00;
wave_display[3]=0x00;
wave_display[4]=0x00;
wave_display[5]=SMG_TAB[sonic_distance%1000/100];
wave_display[6]=SMG_TAB[sonic_distance%100/10];
wave_display[7]=SMG_TAB[sonic_distance%10/1];
setsonic_display[0]=0x00;
setsonic_display[1]=0x00;
setsonic_display[2]=0X00;
setsonic_display[3]=0x40;
setsonic_display[4]=0x40;
setsonic_display[5]=SMG_TAB[lim_distance%1000/100];
setsonic_display[6]=SMG_TAB[lim_distance%100/10];
setsonic_display[7]=SMG_TAB[lim_distance%10/1];
}
void init_set()
{
P2=(P2&0x1f)|0xa0;
P06=1; P04=0; //蜂鸣器响
P2=P2&0x1f;
ledlight(0xfe); //L1亮
time_display[0]=0xff; time_display[1]=0xff;
time_display[2]=0Xff; time_display[3]=0xff;
time_display[4]=0xff; time_display[5]=0xff;
time_display[6]=0xff; time_display[7]=0xff;
Delay1000ms();
P2=(P2&0x1f)|0xa0;
P06=0; P04=0; //蜂鸣器响
P2=P2&0x1f;
ledlight(0xfF); //L1亮
}
IIC模块
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(12MHz)
日 期: 2011-8-9
*/
#include "iic.h"
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
/*IIC总线协议规定,每传送一个字节数据后,都要有一个应答信号,以确定数据传送是否被对方收到,
应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉为低电平表示数据传输正确,即产生了应答。*/
//应答位控制
void IIC_Ack(unsigned char ackbit) //当ackbit为1时,表示单片机对从设备发送来数据的应答
//当ackbit为0时,表示主机接收了最后一个字节,因此不再应答,结束通信
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA) //在SCL为高电平期间,因为接收设备未将SDA拉低,所以默认未接收到应答,结束IIC通信
{
SCL = 0;
IIC_Stop();
return 0;
}
else //接收到应答,返回1,继续下一个数据字节的传输
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
void Write_24c02(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char Read_24c02(unsigned char dat)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return temp;
}