由于篇幅有限以下只有部分代码,本程序的完整版本成从 http://www.51hei.com/f/xjjd.rar 下载.
/*===========================================================================
CopyLeft(CL) FORVERE Wjj
All rights NOT reserved
版权所无,翻版不究,但请保留此处信息
http://blog.sina.com.cn/u/2150397142
any problem or suggestion mail to: 15258297408@163.com
******************************************************************************
*文件名:Motor_simulation
*文件说明:洗衣机正反转、定时、加速减速模拟源代码
*版本: The final version
*芯片: STC89C52RC
*晶振: (外)内部12MHz晶振
*作者: Wang Jian Jun
*日期: 2010年6月4日
*编译环境: keil4 & proteus7
*结果: 软件测试通过,实物测试通过
*说明: 洗衣机正反转、定时、加速减速模拟,由LCD1602显示定时时长,并倒计时显示,
转速(转速由0-9数字表征),转动由数码管段位交替显示来体现
=============================================================================*/
#include<reg52.h> //加载C51核心库文件
#include<intrins.h> //加载应用型库文件
#define nop() _nop_()
#define N 15536
#define uint unsigned int
#define uchar unsigned char //宏定义,方便写程序
sbit key0 = P0^0;
sbit key1 = P0^1;
sbit key2 = P0^2;
sbit key3 = P0^3; //定时选择、启动(再次启动)按键定义
sbit pp = P2^7; //定时到报警输出口
sbit SpeAdd = P0^5; //速度加
sbit SpeSub = P0^4; //速度减
sbit lcden=P2^2;
sbit lcdrw=P2^1;
sbit lcdrs=P2^0; //LCD控制端口定义
uint count = 0;
uint count1 = 0;
uint count2 = 0;
uint count3 = 0; //计数变量定义
uint time = 0;
uint time1 = 0; //定时时间存储变量
uint Speed = 4; //速度选择 值越大速度越慢
uint Direction = 0; //方向标志
uint LedPa = 0; //数码管参数
uchar LedCode1[] = {0Xfe, 0Xfd, 0Xfb, 0Xf7, 0Xef, 0Xdf}; //正时针显示
uchar LedCode2[] = {0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; //逆时针显示
uchar idata table[]={"Set Time:"}; //第一行提示语"Set Time:"
uchar idata table1[]={"Real Speed:"}; //第一行提示语"Real Speed:"
/***********************************
*** 延时子程序 ***
*** 无返回值 ***
***********************************/
void DelayNS(uint dly)
{
uint i;
for(; dly>0; dly--)
for(i=0; i<100; i++);
}
/***********************************
*** LCD忙检测 ***
*** 返回忙标志 ***
************************************/
bit lcd_busy()
{
bit result;
lcdrw = 1;
lcdrs = 0;
lcden = 1;
nop();nop();nop();nop();
result = (bit)(P1&0x80);
lcden = 0;
return(result);
}
/***********************************
*** LCD写命令子程序 ***
*** 无返回值 ***
************************************/
void write_com(uchar com)
{
while(lcd_busy()); //LCD忙等待
lcdrs = 0;
lcdrw = 0;
P1 = com;
DelayNS(5);
lcden = 1;
DelayNS(5);
lcden = 0;
}
/***********************************
*** LCD写数据子程序 ***
*** 无返回值 ***
************************************/
void write_data(uchar date)
{
while(lcd_busy()); //LCD忙等待
lcdrs = 1;
lcdrw = 0;
P1 = date;
DelayNS(5);
lcden = 1;
DelayNS(5);
lcden = 0;
}
/***********************************
*** LCD初始化 ***
*** 无返回值 ***
************************************/
void lcd_init()
{
lcden = 0;
write_com(0x38);
DelayNS(5);
write_com(0x0c);
DelayNS(5);
write_com(0x06);
DelayNS(5);
write_com(0x01);
DelayNS(5);
write_com(0x80);
DelayNS(5);
write_com(0x01);
}
/***********************************
*** 键盘扫描子程序 ***
*** 无返回值 ***
************************************/
void keyscan()
{
P1=0xff;
if(key0==0)
{
DelayNS(10);
if(key0==0)
{
time = 300;
time1 = time;
}
while(!key0); //等待按键松开
} //设置300s
if(key1==0)
{
DelayNS(10);
if(key1==0)
{
time = 200;
time1 = time;
}
while(!key1); //等待按键松开
} //设置200s
if(key2==0)
{
DelayNS(10);
if(key2==0)
{
time = 100;
time1 = time;
}
while(!key2); //等待按键松开
} //设置100s
if(key3==0)
{
DelayNS(10);
if(key3==0)
{
while(!key3); //等待按键松开
TR1 = ~TR1;
TR0 = ~TR0;
time1 = time;
pp=1;
}
} //启动(再次启动)
}
/***********************************
*** 主程序 ***
*** ***
************************************/
void main() //主函数
{
uint i;
lcd_init(); //LCD初始化
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
ET1 = 1; //开定时器0中断
TMOD = 0x11; //定时器0和1的工作方式都为1
TH0 = 0x00;
TL0 = 0x00;
TH1=0x3c;
TL1=0xb0; //定时初值
Direction = 0; //方向设置(顺)
for(i=0;i<9;i++)
{
write_data(table[i]);
DelayNS(2);
} //第一行提示语"Set Time:"显示
write_com(0x80+0x40); //LCD第二行起始地址
for(i=0;i<11;i++)
{
write_data(table1[i]);
DelayNS(2);
} //第一行提示语"Real Speed:"
write_com(0x80);
while(1) //主循环
{
keyscan(); //按键扫描
table[10]=time1/100+0x30;
table[11]=time1%100/10+0x30;
table[12]=time1%100%10+0x30;
table[13]=0x73;
write_com(0x80+0x0a);
for(i=10;i<14;i++)
{
write_data(table[i]);
DelayNS(2);
}
table1[12]=(10-Speed)+0x30;
write_com(0x80+0x4c);
for(i=12;i<13;i++)
{
write_data(table1[i]);
DelayNS(2);
}
} //以上显示定时时间,转速
}
/***********************************
*** 定时器0中断服务程序 ***
*** 无返回值 ***
************************************/
void timer_0() interrupt 1
{
count++;
if(count==(6800/Speed))
{
count=0;
Direction=~Direction; //10s转向取反
}
if(!SpeAdd) //速度加判断
{
DelayNS(10);
while(!SpeAdd);
DelayNS(10);
++Speed;
if(Speed == 10) //档位溢出处理
{
Speed = 9;
}
}
if(!SpeSub) //速度减判断
{
DelayNS(10);
while(!SpeSub);
DelayNS(10);
Speed--;
if(Speed == 1) //档位溢出处理
{
Speed = 2;
}
}
count1++;
if(count1 == 50)
{
if(Direction)
{
P3 = LedCode1[LedPa++];
if(LedPa == 6)
{
LedPa = 0;
}
}
if(!Direction)
{
P3 = LedCode2[LedPa++];
if(LedPa == 6)
{
LedPa = 0;
}
}
count1 = 0;
} //数码管段位交替显示
TH0 = (65536 - (Speed*1000))/256;
TL0 = (65536 - (Speed*1000))%256; //重装初值
}
/***********************************
*** 定时器1中断服务程序 ***
*** 返回time1 ***
************************************/
void timer_1() interrupt 3
{
count3++;
if(count3 == 20) //定时1s
{
time1--; //实现倒计时
if(time1 == 0)
{
TR0 = ~TR0; //时间到关timer0
TR1 = ~TR1; //时间到关timer2
time1 = 0;
pp=0; //时间到报警
}
count3 = 0;
}
TH1=0x3c;
TL1=0xb0; //重装初值
}



