蓝桥杯单片机第六届国赛(智能物料传送系统)

先看题目。
全部文件:提取码: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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一心向月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值