蓝桥杯单片机设计与开发决赛-第六届-智能物料传送系统

这里的代码是主文件的代码,其他的头文件之前已经提供,下面的代码仅提供思路,不提供原理,如有错误请及时留言提醒。

#include <stc15f2k60s2.h>
#include <intrins.h>
#include "iic.h"
typedef unsigned char uchar;
typedef unsigned int uint;

code uchar TAB[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff};//显示1-9 灭
uchar tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8;

uchar key, dat, AD;//常用的参数,按键,数据存放,AD读取存放

uint sonic_time, distance;// distance为超声波测距距离, 用uchar定义也是可以的,定时器的局限性它最多只能测100cm左右
#define somenop() {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}//超声波模块延时,注意使用define后面不用加分号
sbit TX = P1^0;//超声波模块发送  1为关闭 0为发送
sbit RX = P1^1;//超声波模块接收  1为关闭 0为接受

uint dat_t;
bit AD_state, sonic_state;

uchar goods_state;//货物状态,0为控制,1为非控制,2为过载
uchar led = 0xff;//定义存放led状态的变量

uint shan_t;//闪烁时间计时
bit shan;//闪烁标志位
uchar goods_num;//货物状态

uchar function;

uchar deliver_time;//剩余传送时间
uchar goods1time = 2, goods2time = 4;  //1类传送时间为2s 2类传送时间为4s
uint deliver_t;//传送时间计时
bit deliver_state, stop;//传送状态,停止位
uchar set_time;

void delay(uint z)//延时函数
{
	uint x, y;
	for(x=z; x>0; x--)
		for(y=845; y>0; y--);
}

void timer_int()//定时器初始,一般是手写放在这里面
{
	EA = 1;
	TR0 = 1; //定时器0,16位,定时1ms,定时中断
	ET0 = 1;
	TMOD |= 0X01;
	TH0 = (65535-1000)/256;
	TL0 = (65535-1000)%256;

	TMOD |= 0X10;// 定时器1,16位,用来定时超声波的往返时间
	TH1 = 0;
	TL1 = 0;
}

void display()//显示函数,配合定时器0中断使用,达到循环扫描
{
	static uchar i;//定义静态变量i
	switch(i)
	{
		case 0: P2=0XC0; P0=0X01; P2=0XE0; P0=TAB[tab1]; i=1; break;
		case 1: P2=0XC0; P0=0X02; P2=0XE0; P0=TAB[tab2]; i=2; break;
		case 2: P2=0XC0; P0=0X04; P2=0XE0; P0=TAB[tab3]; i=3; break;
		case 3: P2=0XC0; P0=0X08; P2=0XE0; P0=TAB[tab4]; i=4; break;

		case 4: P2=0XC0; P0=0X10; P2=0XE0; P0=TAB[tab5]; i=5; break;
		case 5: P2=0XC0; P0=0X20; P2=0XE0; P0=TAB[tab6]; i=6; break;
		case 6: P2=0XC0; P0=0X40; P2=0XE0; P0=TAB[tab7]; i=7; break;
		case 7: P2=0XC0; P0=0X80; P2=0XE0; P0=TAB[tab8]; i=0; break;
	}
}

void key_scan()//独立键盘扫描,常用需要理解记住
{	
	key = 0;
	P3 = 0X3F;
	if(P3!=0X3F)
	{
		P3 = 0X3F;
		delay(2);//消抖
		if(P3!=0X3F)
		{
			if(P33==0) key = 4;
			if(P32==0) key = 5;
			if(P31==0) key = 6;
			if(P30==0) key = 7;
		}
		while(P3!=0X3F);//判断抬手	
	}
}

void sonic_read()//超声波测距读取
{
	uchar i;
	TF1 = 0; TH1 = 0; TL1 = 0;//清空定时器计数和标志位
	for(i=0; i<8; i++)
	{
		TX = 0; //发送超声波
		somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();
		TX = 1; //关闭超声波
		somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();somenop();
	}
	TR1 = 1;//打开定时器,记录超声波往返时间
	while((TF1==0)&(RX==1));//等待接受,或定时器溢出
	TR1 = 0;//关闭定时器
	if(TF1==1)//定时器溢出,没有在测量范围内
	{
		TF1 = 0;
		distance = 99;
	}
	else 
	{
		sonic_time = TH1<<8;//计算往返时间
		sonic_time |= TL1;
		distance = (uint)(sonic_time*0.017); //计算距离
		if(distance>=99) distance = 99;//两位显示距离,限制上限
	}
}


void dat_gain()//定时获取数据
{
	if(sonic_state==1)
	{ 
		sonic_state = 0; sonic_read();//读取超声波距离,判断货物状态
		if(distance<=30) { goods_num = 1; } 
		else { goods_num = 2; }
	}
	else if(AD_state==1) 
	{ 
		AD_state = 0; AD = AD_read(0x03)/5.1; //转化为输出电压*10
		if((0<AD)&(AD<10)) { goods_state = 0; P2=0X80; led |= 0x07; led &= 0xfe; P0=led; }//判断空载,熄灭led1,2,3,并点亮相关的led
		else if((10<=AD)&(AD<40)) { goods_state = 1; P2=0X80; led |= 0x07; led &= 0xfD; P0=led; }//判断非空载,熄灭led1,2,3,并点亮相关的led
		else if(AD>=40) //判断过载,熄灭led1,2,3,并点亮相关的led
		{ 
			goods_state = 2; 
			if(shan==1) { P2=0X80; led |= 0x07; led &= 0xfb; P0=led; }//间隔闪烁提醒
			else { P2=0X80; led |= 0x07; led |= 0x04; P0=led;  } 
		}
	}	
}

void key_function()//按键功能
{
	if((key==4)&(goods_state==1))//判断启动传送条件
	{
		key = 0; //按键扫描函数里面没有设置按键值清零,所以每次用完按键后要清零,防止按键功能跑飞
		function = 1;
		P2 = 0XA0; P0 = 0X10;
		if(goods_num==1)  deliver_time = goods1time;//赋值传送时间
		else if(goods_num==2)  deliver_time = goods2time;
		deliver_state = 1;//打开传送标志位,在定时器0中断开始计时
	}
	else if((key==5)&(function==1))//判断紧急停止条件
	{
		key = 0;
		stop = ~stop;//停止时,会在定时器0中断中,启动LED4闪烁
		if(stop==0) { P2 = 0XA0; P0 = 0X10; }//打开继电器
		else { P2 = 0XA0; P0 = 0X00; }
	}
	else if((key==6)&(goods_state==0))//判断设置条件
	{
		key = 0;
		function = 2;
		if(set_time==0) set_time = 1;//set_time为1时 标志可以调整1类货物时间
		else if(set_time==1) set_time = 2;//set_time为2时 标志可以调整2类货物时间
		else if(set_time==2) //第3下按键S6,set_time为0 保存调整时间
		{ 
			set_time = 0; function = 0; goods_state = 0;
			EEPROM_write(0x20,goods1time); delay(3); EEPROM_write(0x21,goods2time); 
		}
	}
	else if((key==7)&(function==2))//判断调整条件
	{
		key = 0; 
		if(set_time==1) { goods1time++; if(goods1time==11) goods1time = 1; }//调节传送时间时,记得设置上下限
		else if(set_time==2) { goods2time++; if(goods2time==11) goods2time = 1; }
	}	
}

void dat_display()//数据显示
{
	if(goods_state!=0)//正常显示
	{    //function=0 为货物类型显示 =1 为剩余传送时间显示  =2 为传送时间设置界面
		if(function==0) { tab1=1; tab2=10; tab3=10; tab4=distance/10; tab5=distance%10; tab6=10; tab7=10; tab8=goods_num; }
		else if(function==1) { tab1=2; tab2=10; tab3=10; tab4=10; tab5=10; tab6=10; tab7=deliver_time/10; tab8=deliver_time%10; }	
		else if(function==2) 
		{ 
			if(shan==0) { tab1=3; tab2=10; tab3=10; tab4=goods1time/10; tab5=goods1time%10; tab6=10; tab7=goods2time/10; tab8=goods2time%10; }
			else if((shan==1)&(set_time==1)) { tab1=3; tab2=10; tab3=10; tab4=10; tab5=10; tab6=10; tab7=goods2time/10; tab8=goods2time%10; }
			else if((shan==1)&(set_time==2)) { tab1=3; tab2=10; tab3=10; tab4=goods1time/10; tab5=goods1time%10; tab6=10; tab7=10; tab8=10; }
		}
	}
	else //设置显示
	{
		if(function==2) 
		{ 
			if(shan==0) { tab1=3; tab2=10; tab3=10; tab4=goods1time/10; tab5=goods1time%10; tab6=10; tab7=goods2time/10; tab8=goods2time%10; }
			else if((shan==1)&(set_time==1)) { tab1=3; tab2=10; tab3=10; tab4=10; tab5=10; tab6=10; tab7=goods2time/10; tab8=goods2time%10; }
			else if((shan==1)&(set_time==2)) { tab1=3; tab2=10; tab3=10; tab4=goods1time/10; tab5=goods1time%10; tab6=10; tab7=10; tab8=10; }
		}
		else { tab1=10; tab2=10; tab3=10; tab4=10; tab5=10; tab6=10; tab7=10; tab8=10; }
			
	}
}

void main()
{
	P2=0X80; P0=0XFF; P2=0XA0; P0=0X00;//初始化,熄灭灯,关闭蜂鸣器和继电器

	if(EEPROM_read(0x11)!=1)//初始化参数,第一遍烧录程序只执行一次,比较好的模板,可记住
	{
		delay(3);
		EEPROM_write(0x11,1);
		delay(3);//连续读取或写入,必须加小延迟
		EEPROM_write(0x20,2);
		delay(3);
		EEPROM_write(0x21,4);
	}
	delay(3);
	goods1time = EEPROM_read(0x20);//读取传送时间
	delay(3);
	goods2time = EEPROM_read(0x21);

	timer_int();
	while(1)
	{
		key_scan();//按键扫描 
		
		dat_gain();

		key_function();

		dat_display();

	}
}

void timer0()interrupt 1
{
	TH0 = (65535-1000)/256;//定时器1装载
	TL0 = (65535-1000)%256;
	display(); //数码管扫描显示 	

	dat_t++;//定时数据获取的时刻,定义时,记得超过256,需要定义为 unsigned int
	if(dat_t==50) AD_state = 1;
	else if(dat_t==150) sonic_state = 1;
	else if(dat_t==250) dat_t = 0;//时间最后记得清零

	shan_t++;//过载闪烁
	if(shan_t==500)
	{
		shan_t = 0;	
		shan = ~shan;
		if(stop==1)
		{
			if(shan==1) { P2 = 0X80; led &= 0xf7; P0=led; }
			else { P2 = 0X80; led |= 0x08; P0=led; }
		}
		else  { P2 = 0X80; led |= 0x08; P0=led; }
	}

	if(deliver_state==1)//传送时间计时
	{
		if(stop==0) deliver_t++;
		if(deliver_t==1000) 
		{
			deliver_t = 0;//时间定时完成,最后记得清零
			deliver_time--;
			if(deliver_time==0)
			{
				deliver_t = 0;//这句好像写多了
				P2 = 0XA0; P0 = 0X00;//关闭继电器
				deliver_state = 0;	//复位,为下次计时做准备
				function = 0;
			}
		}
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值