功能简述
智能物料传送系统能够实现货物类型判断、过载监测、紧急停止和系统参数存储记录等功能。系统硬件部分主要由按键电路、显示电路、数据存储电路、传感器检测电路及单片机系统组成,系统框图如图1所示:
I2C总线驱动程序、CT107D单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。原理图文件、程序流程图及相关工程文件请以考生号命名,并保存在计算机上的考生文件夹中(文件夹名为考生准考证号,文件夹位于Windows桌面上)。
设计任务及要求
1. 过载监测与货物类型识别
1.1空载、过载监测
使用电位器RB2输出电压Vo模拟压力变送器输出,设备实时采集电位器输出电压,完成货物空载、过载监测功能。
1.1.1当0<Vo<1V时,判断为空载,L1点亮;
1.1.2当1≤Vo<4V时,判断为非空载,货物被填装到传送起始位置,L2点亮;
1.1.3当Vo≥4V时,判断为过载状态,L3以0.5秒为间隔闪烁提醒,蜂鸣器报警提示。
说明:空载状态下,所有数码管熄灭。
1.2货物类型判断
货物被填装到传送起始位置后,系统启动超声波测距功能,完成货物类型判断,数码管显示界面如图2所示:
1.2.1当超声探头与货物之间的距离小于等于30cm时判断为I类货物;
1.2.2当超声探头与货物之间的距离大于30cm时判断为II类货物。
说明:
1.货物类型显示格式:I类货物-数字1、II类货物-数字2;
2. A3草稿纸短边接近30cm,可用于验证测距结果。
2. 货物传送
在非空载、非过载的前提下,通过按键控制继电器吸合,启动货物传送过程,并通过数码管实时显示剩余的传送时间,倒计时结束后,继电器自动断开,完成本次传送过程,数码管显示格式如图 3 所示:
说明:继电器吸合时,指示灯 L10 点亮,断开时 L10 熄灭。
3. 按键功能描述
3.1 按键 S4 定义为“启动传送”按键,按键按下后,启动货物传送过程。
说明:按键 S4 在空载、过载、传送过程中无效。
3.2 按键 S5 定义为“紧急停止”按键,按键按下后,继电器立即断开,指示灯 L4以 0.5 秒为间隔闪烁,剩余传送时间计时停止。再次按下 S5,传送过程恢复,L4 熄灭,恢复倒计时功能,继电器吸合,直到本次传送完成。
说明:按键 S5 仅在传送过程中有效。
3.3 按键 S6 定义为“设置”按键,按下 S6 按键,调整 I 类货物传送时间,再次按下 S6 按键,调整 II 类货物传送时间,第三次按下 S6,保存调整后的传送时间到 E2PROM,并关闭数码管显示。设置过程中数码管显示界面如图 4 所示:
说明:
1.货物传送时间可设定范围为 1-10 秒,通过按键 S7 调整;
2. “设置”按键 S6、“调整”按键 S7 仅在空载状态下有效;
3. 通过按键 S6 切换选择到不同货物类型的传送时间时,显示该类货物传送
时间的数码管闪烁。
4. 数据存储
I、II 类型货物的传送时间在设置完成后需要保存到 E2PROM 中,设备重新上电后,能够恢复最近一次的传送时间配置信息。
5. 上电初始化状态与工作流程说明
5.1 I 类设备默认传送时间为 2 秒,II 类设备为 4 秒;
5.2 最终作品提交前,将 RB2 输出电压调整到最小值,确保设备处于空载状态;
主函数
#include "stc15f2k60s2.h"
#include "iic.h"
#include "display.h"
#include "driver.h"
#include "sonic.h"
uchar key_value; //按键值
uchar S5_count; //S5按键次数
extern uchar mode_display; //显示模式
extern uchar voltage; //电压值
extern unsigned char countdown1; //货物I倒计时
extern unsigned char countdown2; //货物II倒计时
extern unsigned char goods_kind; //货物类型
extern uchar S6_count; //S6按键次数
bit flag500ms;
bit S4_enable; //S4按键使能
bit led4_flag; //led4闪烁标志
extern bit S5_enable; //S5按键使能
extern bit unload_flag; //空载标志
extern bit transmit_flag; //传送标志
extern bit countdown_flag; //倒计时标志
extern bit relay_flag; //继电器标志
void goods_test(); //空载、过载检测
void delayms(uint ms);
void main()
{
Timer0Init();
All_init();
countdown1=Read_eeprom(0x00);
delayms(10);
countdown2=Read_eeprom(0x01);
delayms(10);
while(1)
{
Display1();
goods_test();
Display2();
Display3();
key_value=key_init();
switch(key_value)
{
case 4:
if(S4_enable)
{
mode_display=1;
relay_flag=1;
countdown_flag=1;
S5_enable=1;
countdown1=Read_eeprom(0x00);
delayms(10);
countdown2=Read_eeprom(0x01);
delayms(10);
}
break;
case 5:
if(S5_enable)
{
S5_count++;
if(S5_count==2)
S5_count=0;
if(S5_count==1)
{
countdown_flag=0; //停止计数
relay_flag=0; //关闭继电器
led4_flag=1; //led4闪烁
}
else
{
countdown_flag=1;
relay_flag=1;
led4_flag=0;
}
}
break;
case 6:
if(unload_flag)
{
mode_display=2;
if(mode_display==2)
S6_count++;
if(S6_count==3)
{
S6_count=0;
mode_display=0;
Write_eeprom(0x00,countdown1);
delayms(10);
Write_eeprom(0x01,countdown2);
delayms(10);
}
}
break;
case 7:
if(unload_flag)
{
if(S6_count==1)
{
countdown1++;
if(countdown1==11)
countdown1=1;
}
if(S6_count==2)
{
countdown2++;
if(countdown2==11)
countdown2=1;
}
}
break;
}
if(mode_display==1)
{
if(relay_flag)
{
Relay(1);
Beep(0);
}
else
{
Relay(0);
Beep(0);
}
}
}
}
void goods_test()
{
voltage=Read_Pcf8591(0x03);
delayms(10);
if(led4_flag)
{
if(flag500ms)
{
led_init(0xf7);
}
else
{
led_init(0xff);
}
}
else
{
if(voltage<51) //小于1V,空载
{
led_init(0xfe);
Beep(0);
Relay(0);
S4_enable=0;
unload_flag=1; //空载标志
}
if((voltage>=51)&&(voltage<204)) //非空载
{
led_init(0xfd);
Beep(0);
if(relay_flag==0)
Relay(0);
S4_enable=1;
unload_flag=0;
transmit_flag=1;
}
if(voltage>=204) //过载
{
Beep(1); //蜂鸣器报警
Relay(0);
S4_enable=0;
unload_flag=0;
if(flag500ms)
{
led_init(0xfb);
}
else
{
led_init(0xff);
}
}
}
}
void delayms(unsigned int ms) //@11.0592MHz
{
unsigned char i, j;
while(ms--)
{
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
LED、蜂鸣器、继电器及按键驱动
#include "driver.h"
void All_init()
{
P2=(P2&0X1F)|0X80;
P0=0xff;
P2=P2&0X1F;
P2=(P2&0X1F)|0Xa0;
P0=0x00;
P2=P2&0X1F;
}
void led_init(unsigned char led)
{
P0=0XFF;
P2=(P2&0X1F)|0X80;
P0=led;
P2=P2&0X1F;
}
void Beep(bit on_off) //蜂鸣器
{
if(on_off)
P06=1;
else
P06=0;
P2=P2&0X1F|0XA0;
P2=P2&0X1F;
}
void Relay(bit on_off) //继电器
{
if(on_off)
P04=1;
else
P04=0;
P2=P2&0X1F|0XA0;
P2=P2&0X1F;
}
uchar key_init()
{
static uchar key_state=0;
uchar key_press, key_return=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_return=7;
if(key_press==0x0d) key_return=6;
if(key_press==0x0b) key_return=5;
if(key_press==0x07) key_return=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_return;
}
超声波测距
#include "sonic.h"
#include "intrins.h"
void Delay13us(); //@11.0592MHz
unsigned int Get_distance()
{
long distance=0;
long i,temp=0;
Echo=1;
for(i=0;i<10;i++)
{
Trig=~Trig;
Delay13us();
}
while(Echo)
{
temp++;
if(temp>=1000)
break;
}
distance=temp/7;
return distance;
}
void Delay13us() //@11.0592MHz
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
显示函数
#include "display.h"
#include "sonic.h"
#include "driver.h"
unsigned char code SMG_TAB[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char SMG_WEI[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80};
unsigned char goods_display[8];
unsigned char time_display[8];
unsigned char set_display[8];
unsigned char mode_display;
unsigned char goods_kind; //货物类型
unsigned char countdown1=2;
unsigned char countdown2=4;
unsigned char countdown;
unsigned char voltage;
unsigned char S6_count;
long sonic_distance;
bit blink_flag;
extern bit flag500ms;
bit unload_flag;
bit transmit_flag;
bit flag200ms;
bit countdown_flag;
bit relay_flag;
bit S5_enable;
void Display1()
{
if(transmit_flag)
{
if(flag200ms) //200ms测一次
{
flag200ms=0;
sonic_distance=Get_distance();
}
}
if(sonic_distance<=30)
{
goods_kind=1; //货物类型1
}
if(sonic_distance>30)
{
goods_kind=2; //货物类型2
}
if(unload_flag) //空载状态下,数码管全部熄灭
{
goods_display[0]=0x00;
goods_display[1]=0X00;
goods_display[2]=0x00;
goods_display[3]=0x00;
goods_display[4]=0x00;
goods_display[5]=0X00;
goods_display[6]=0X00;
goods_display[7]=0x00;
}
else
{
goods_display[0]=SMG_TAB[1];
goods_display[1]=0X00;
goods_display[2]=0x00;
goods_display[3]=SMG_TAB[sonic_distance/10%10];
goods_display[4]=SMG_TAB[sonic_distance%10];
goods_display[5]=0X00;
goods_display[6]=0X00;
goods_display[7]=SMG_TAB[goods_kind];
}
}
void Display2()
{
if(goods_kind==1)
countdown=countdown1;
if(goods_kind==2)
countdown=countdown2;
time_display[0]=SMG_TAB[2];
time_display[1]=0X00;
time_display[2]=0x00;
time_display[3]=0x00;
time_display[4]=0x00;
time_display[5]=0X00;
time_display[6]=SMG_TAB[countdown/10];
time_display[7]=SMG_TAB[countdown%10];
}
void Display3()
{
set_display[0]=SMG_TAB[3];
set_display[1]=0X00;
set_display[2]=0x00;
set_display[5]=0X00;
if(blink_flag) //数码管闪烁
{
if(S6_count==1)
{
set_display[3]=SMG_TAB[countdown1/10];
set_display[4]=SMG_TAB[countdown1%10];
}
if(S6_count==2)
{
set_display[6]=SMG_TAB[countdown2/10];
set_display[7]=SMG_TAB[countdown2%10];
}
}
else
{
if(S6_count==1)
{
set_display[3]=0x00;
set_display[4]=0x00;
}
else
{
set_display[3]=SMG_TAB[countdown1/10];
set_display[4]=SMG_TAB[countdown1%10];
}
if(S6_count==2)
{
set_display[6]=0x00;
set_display[7]=0x00;
}
else
{
set_display[6]=SMG_TAB[countdown2/10];
set_display[7]=SMG_TAB[countdown2%10];
}
}
}
void Timer0Init(void) //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
{
unsigned char smg_count,i;
unsigned int led_count,sonic_count,daojishi,blink_count;
smg_count++;
led_count++;
sonic_count++;
daojishi++;
blink_count++;
if(smg_count==3)
{
smg_count=0;
P2=(P2&0X1F)|0XC0;
P0=SMG_WEI[i];
P2=P2&0X1F;
if(mode_display==0)
{
P2=(P2&0X1F)|0XE0;
P0=~goods_display[i];
P2=P2&0X1F;
}
if(mode_display==1)
{
P2=(P2&0X1F)|0XE0;
P0=~time_display[i];
P2=P2&0X1F;
}
if(mode_display==2)
{
P2=(P2&0X1F)|0XE0;
P0=~set_display[i];
P2=P2&0X1F;
}
i++;
if(i==8)
i=0;
}
if(led_count==500)
{
led_count=0;
flag500ms=~flag500ms;
}
if(sonic_count==200)
{
sonic_count=0;
flag200ms=1;
}
if(daojishi==1000)
{
daojishi=0;
if(countdown_flag)
{
if(goods_kind==1)
{
countdown1--;
if(countdown1==0)
{
countdown_flag=0;
countdown1=0;
relay_flag=0;
S5_enable=0;
}
}
if(goods_kind==2)
{
countdown2--;
if(countdown2==0)
{
countdown_flag=0;
countdown2=0;
relay_flag=0;
S5_enable=0;
}
}
}
}
if(blink_count==400)
{
blink_count=0;
blink_flag=~blink_flag;
}
}
AD及EEPROM
说明:经过这一段时间的测试,发现读取RB2上的电压值时,先关闭定时器中断,读取数值比较稳定,同时官方给的iic驱动中,somenop中一共有25个_nop_()比较合适,具体见程序
/*
程序说明: 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;
}
//应答位控制
void IIC_Ack(unsigned char ackbit)
{
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 = 0;
IIC_Stop();
return 0;
}
else
{
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;
}
unsigned char Read_Pcf8591(unsigned char addr)
{
unsigned char temp;
ET0=0; //关闭定时器,防止程序被打乱
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
ET0=1;
return temp;
}
void Write_eeprom(unsigned char addr,unsigned char dat)
{
ET0=0; //关闭定时器,防止程序被打乱
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
ET0=1;
}
unsigned char Read_eeprom(unsigned char addr)
{
unsigned char temp;
ET0=0; //关闭定时器,防止程序被打乱
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
ET0=1;
return temp;
}
以上就是代码全部内容,欢迎交流,共同学习~
喜欢就关注一下吧~