先看题目。
全部文件:提取码:azxy
main.c
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "iic.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit TX=P1^0;//超声波发射
sbit RX=P1^1;//超声波接收
u8 code duan[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};//0~9
u16 rb2=0;//电位器2的电压
u8 model=1;//数码管界面
u16 distance=0;//超声波测得距离
u8 kind=0;//货物类型
u8 time=1,time1=4,time2=6;//数码管显示的倒计时间 货物1传输时间 货物2传输时间
u8 stat=0;//空载 非空载 过载
u8 flag=0;//传输标志 0:未开始传输 1:开始传输
u8 time_setup=0;//货物传输时间设置区分
u8 relay=0;//继电器标志
u16 count=0,count1=0;//定时器时间累加变量
u8 Led_flag=0;//LED 0.5s 标志
u8 aa=0;//保证第一次上电 货物1时间为2S 货物2时间为4S
void delay(u16 i)//延迟函数
{
while(i--);
}
void Chan_hc573(u8 chose)//锁存器选择
{
switch(chose)
{
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;
}
P2 = (P2 & 0x1f) | 0x00;
}
void Init_system()//初始化关闭LED 蜂鸣器和继电器
{
P0=0x00;
Chan_hc573(5);
P0=0xff;
Chan_hc573(4);
}
void Smg_display(u8 com,u8 dat)//数码管选择
{
P0=0xff;
Chan_hc573(7);
P0=0x01<<com;
Chan_hc573(6);
P0=dat;
Chan_hc573(7);
delay(1000);
}
void Close_smg()//数码管消隐
{
P0=0x00;
Chan_hc573(6);
P0=0xff;
Chan_hc573(7);
}
void Display_model(u8 t)//数码管显示界面
{
if(stat!=0)//不是空载的时候
{
if(model==1)//界面1
{
while(t--)//因为是超声波显示界面,这一句是为了防止数码管闪烁太严重
{
Smg_display(0,duan[1]);
Smg_display(1,duan[10]);
Smg_display(2,duan[10]);
Smg_display(3,duan[distance/10%10]);
Smg_display(4,duan[distance%10]);
Smg_display(5,duan[10]);
Smg_display(6,duan[10]);
Smg_display(7,duan[kind]);
Close_smg();
}
}
else if(model==2)//界面2
{
Smg_display(0,duan[2]);
Smg_display(1,duan[10]);
Smg_display(2,duan[10]);
Smg_display(3,duan[10]);
Smg_display(4,duan[10]);
Smg_display(5,duan[10]);
Smg_display(6,duan[time/10]);
Smg_display(7,duan[time%10]);
Close_smg();
}
}
else //空载的时候
{
if(time_setup==0) {Close_smg();}//处于空载时,没有按S6时数码管熄灭
else //界面3
{
Smg_display(0,duan[3]);
Smg_display(1,duan[10]);
Smg_display(2,duan[10]);
Smg_display(3,duan[time1/10]);
Smg_display(4,duan[time1%10]);
Smg_display(5,duan[10]);
Smg_display(6,duan[time2/10]);
Smg_display(7,duan[time2%10]);
Close_smg();
}
}
}
/*******************超声波模块***********************/
void Delay12us() //延迟12us
{
unsigned char i;
_nop_();
_nop_();
i = 36;
while (--i);
}
void launch_csb()//超声波发射
{
u8 i=0;
for(i=0;i<8;i++)
{
TX=1;
Delay12us();
TX=0;
Delay12us();
}
}
void count_distane()//超声波测距
{
TMOD &= 0x0F;
TL0 = 0x00;
TH0 = 0x00;
TF0 = 0;
ET0 = 1;
launch_csb();
TR0=1;
while((TF0==0)&&(RX==1));
TR0=0;
if(TF0==1)
{
TF0=0;
distance=999;
}
else
{
distance = (TH0<<8)|TL0;
distance = distance*0.017+3;
if(distance>99) {distance=99;}
}
if(distance<=30) {kind=1;}//小于等于30cm,为货物1
else {kind=2;}//大于30cm为货物2
}
/********************************过载监测***************************/
void survey()//过载监测
{
rb2=Read_Rb2(0x03)/0.51;//读取电压
if(rb2<100) {stat=0;}//空载
else if((rb2>=100)&&(rb2<400)) {stat=1;}//非空载
else if(rb2>=400) {stat=2;}//过载
}
/*******************************存储时间***************************/
void Delay5ms() //延迟5ms
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void store_time()//把设置好的货物1和货物2时间存储到EEPROM里
{
Wire_dat(0x01,time1);Delay5ms();//连续写要延迟5ms
Wire_dat(0x02,time2);Delay5ms();
}
/*******************************按键模块***************************/
void Key_down()//按键判断
{
if(P33==0) //S4
{
delay(1000);
if(P33==0)
{
while(P33==0) {Display_model(10);}
if((stat==1)&&(flag==0))//判断是否不处于空载 过载 传输过程
{
model=2;flag=1;relay=1;
if(kind==1) {time=time1;}
if(kind==2) {time=time2;}
}
}
}
else if(P32==0) //S5
{
delay(1000);
if(P32==0)
{
while(P32==0) {Display_model(10);}
if(flag==1) //判断是否处于传输过程
{
if(relay==1) {relay=0;}
else if(relay==0) {relay=1;}
}
}
}
else if(P31==0) //S6
{
delay(1000);
if(P31==0)
{
while(P31==0) {Display_model(10);}
if(stat==0) //判断是否处于空载状态
{
model=3;
time_setup++;
if(time_setup==3) {store_time();time_setup=0;model=1;}
}
}
}
else if(P30==0) //S7
{
delay(1000);
if(P30==0)
{
while(P30==0) {Display_model(10);}
if(stat==0) //判断是否处于空载状态
{
if(time_setup==1) //货物1时间设置
{
time1++;
if(time1==11) {time1=1;}
}
else if(time_setup==2) //货物2时间设置
{
time2++;
if(time2==11) {time2=1;}
}
}
}
}
}
/*************************************定时器0*******************************/
void Timer1Init(void) //定时器1 1ms 12.000MHz
{
AUXR |= 0x40;
TMOD &= 0x0F;
TL1 = 0x20;
TH1 = 0xD1;
TF1 = 0;
ET1 = 1;
TR1 = 1;
EA = 1;
}
void service_t0() interrupt 3//中断服务函数
{
if(relay==1) {count++;}
if(relay==0) {count1++;}
if(count==1000)
{
count=0;
time--;
if(time==0) {model=1;flag=0;relay=0;}
}
if(count1==500)
{
count1=0;
if(Led_flag==0) {Led_flag=1;}
else if(Led_flag==1) {Led_flag=0;}
}
}
/************************继电器状态************************/
void Relay_stat()//继电器设置
{
if(flag==1)//如果处于传输过程
{
if(relay==1)
{
P04=1;P06=0;//继电器打开
Chan_hc573(5);
}
else
{
if(Led_flag==1)//L4点亮
{
P03=0;
Chan_hc573(4);
}
else //L4熄灭
{
P03=1;
Chan_hc573(4);
}
P04=0;P06=0;//继电器关闭
Chan_hc573(5);
}
}
if(stat==2)//如果过载
{
P04=0;P06=1;//蜂鸣器打开
Chan_hc573(5);
}
else //不处于过载的时候
{
if(flag==0)//这个条件是防止在传输过程时关闭继电器
{
P04=0;P06=0;//蜂鸣器关闭
Chan_hc573(5);
}
}
}
/**************************LED状态**********************/
void Led_stat()//LED设置
{
if(stat==0) {P00=0;Chan_hc573(4);} //空载状态下L1点亮
else if(stat==1) {P01=0;Chan_hc573(4);}//非空载状态下L2点亮
else if(stat==2) //过载的时候
{
if(Led_flag==1)//L3点亮
{
P02=0;
Chan_hc573(4);
}
else //L3熄灭
{
P02=1;
Chan_hc573(4);
}
}
}
void First_dat()//保证第一次上电时间,只会运行一次。
{
aa=time1=Read_dat(0x03);
if(aa!=131)
{
Wire_dat(0x01,2);Delay5ms();
Wire_dat(0x02,4);Delay5ms();
Wire_dat(0x03,131);Delay5ms();
}
time1=Read_dat(0x01);
time2=Read_dat(0x02);
}
void main()
{
Init_system();//关闭LED 蜂鸣器 继电器
Timer1Init();//打开定时器1
time1=Read_dat(0x01);//读取货物1时间
time2=Read_dat(0x02);//读取货物2时间
First_dat();//保证第一次上电时间,只会运行一次。
while(1)
{
survey();//过载监测
Key_down();//按键判断
Led_stat();//LED设置
Relay_stat();//继电器设置
Display_model(40);//数码管显示界面
if(model==1) {count_distane();}//超声波测距,只在界面1运行。
}
}
iic.c
#include "iic.h"
#include "reg52.h"
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
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;
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;
}
unsigned char Read_Rb2(unsigned char addr)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(1);
IIC_WaitAck();
IIC_Stop();
return dat;
}
void Wire_dat(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_dat(unsigned char addr)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(1);
IIC_WaitAck();
IIC_Stop();
return dat;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
void Wire_dat(unsigned char addr,unsigned char dat);
unsigned char Read_Rb2(unsigned char addr);
unsigned char Read_dat(unsigned char addr);
#endif