这里的代码是主文件的代码,其他的头文件之前已经提供,下面的代码仅提供思路,不提供原理,如有错误请及时留言提醒。
#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;
}
}
}
}