标题:
单片机自动控制升降旗系统源程序
[打印本页]
作者:
gh8989090
时间:
2018-5-9 20:24
标题:
单片机自动控制升降旗系统源程序
自动控制升降旗系统 程序
0.jpg
(33.94 KB, 下载次数: 25)
下载附件
2018-5-9 20:52 上传
单片机源程序如下:
#include <reg52.h> //调用单片机头文件
#define uchar unsigned char //无符路字符型 宏定义 变量范围0~255
#define uint unsigned int //无符路整型 宏定义 变量范围0~65535
#include "eeprom52.h" //单片机存储控制程序调用
#include "LCD1602.h" //LCD1602控制显示程序调用
sbit VSDA = P3^5; //语音控制IO口定义
sbit VCS = P3^6;
sbit VSCL = P3^7;
sbit key_1=P1^0; //控制按键IO口
sbit key_2=P1^1;
sbit key_3=P1^2;
sbit key_4=P1^3;
sbit key_5=P1^4;
sbit key_6=P1^5;
sbit led_1=P1^6; //系统指示灯IO口
sbit led_2=P1^7;
sbit led_3=P3^0;
sbit led_4=P3^1;
uchar code zz[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //步进电机正转动数据数组
uchar code fz[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//步进电机反转动数据数组
uint UP_dat=0,Below_dat=0,Current_dat=0;
//上移动的角度数据变量,下移动的角度数据变量,当前位置数据变量
uchar Current_Height=0,circulation,speed_dat,dat_A;
//当前旗帜的高度数据变量,步进电机循环控制变量,转动速度控制变量,显示当前高度变量
uchar sys_state,state;
//系统状态变量 ,工作流程控制变量
uchar irbyte[4];
//分析红外数据存数的32位数据;
uchar irtime,irflag,bitnum,irdateok;
//脉冲周期计时便利阿尼哥,分析数据标志位,数据存入数组下标变量 ,数据接受完成标志位
uchar irdate[33];
//红外信号的数据存储数组
/***********************小延时函数**************************/
void delay_us (unsigned int us)
{
while(us--)
{
_nop_();
}
}
/********************************************************************
* 名称 : delay_1ms()
* 功能 : 延时1ms函数
* 输入 : q
* 输出 : 无
***********************************************************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<115;j++);
}
/************ 延时函数 *****************/
void delay_uint(uint z)
{
while(z--);
}
/***************清楚红外信号暂存数组中的数据******************/
void qing(void)
{
uint i;
for(i=0;i<33;i++)
{
irdate[i]=0;
}
}
/****************分析红外信号32位数据***************/
void deal_with(void)
{
uchar i,j,k,temp;
k=1;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++) //每8位数据切换一个数组单元
{
temp=temp>>1;
if(irdate[k]>7) //根据脉冲周期的时长判断红外数据
{
temp=temp|0x80;
}
k++;
}
irbyte[j]=temp;
}
}
/***********************三线发码子程序************************/
void Send_threelines(unsigned char addr) //控制语音模块播放那段地址的语音
{
unsigned char i;
VCS=0;
delay_1ms(5); /* 片选拉低5ms */
for(i=0;i<8;i++)
{
VSCL=0;
if(addr&0x01)
{
VSDA=1;
}
else
VSDA=0;
addr>>=1;
delay_us(150); /* 150us */
VSCL=1;
delay_us(150); /* 150us */
}
VCS=1;
delay_1ms(30);
}
/***************液晶初始化显示函数**************/
void show_init(void)
{
LCD1602_write(0,0xC0);
LCD1602_writebyte("Height:14.0cm");//显示旗杆总长度
LCD1602_write(0,0x80);
LCD1602_writebyte("C_Height:"); //显示当前高度
LCD1602_write(1,0x30+Current_Height/100%10); //十位
LCD1602_write(1,0x30+Current_Height/10%10); //个位
LCD1602_writebyte(".");
LCD1602_write(1,0x30+Current_Height%10); //0.1位
LCD1602_writebyte("cm"); //单位
}
void show(void) //系统循环显示函数
{
LCD1602_write(0,0x89); //显示当前旗帜高度
LCD1602_write(1,0x30+Current_Height/100%10);
LCD1602_write(1,0x30+Current_Height/10%10);
LCD1602_writebyte(".");
LCD1602_write(1,0x30+Current_Height%10);
}
//sys_state=0 为 旗低的状态
//sys_state=1 为 旗顶的状态
//sys_state=2 为 半旗的状态
//sys_state=3 为 正在运行的一个状态
//sys_state=4 为 停止的一个状态
void key_code(void) //系统按键检测控制程序
{
if(irdateok==1) //如果红外信号接收完成标志位触发 则
{
irdateok=0;
deal_with(); //分析红外数据
}
if((!key_1||irbyte[2]==0x44)&&sys_state==0) //如果升全旗按键按下(按键以及红外遥控) 并旗帜处于最低部
{ //延时去抖
delay_uint(1000);
if(!key_1||irbyte[2]==0x44) //再次判断按键按下
{
while(!key_1||irbyte[2]==0x44) //等待按键释放
{
qing();
deal_with();
}
state=1; //跳转升全旗流程节点
sys_state=3; //置为系统当前状态
led_1=0; //对应指示灯
}
}
if((!key_2||irbyte[2]==0x40)&&sys_state==1) //如果将旗旗按键按下(按键以及红外遥控)并旗帜处于最顶部
{
delay_uint(1000); //延时去抖
if(!key_2||irbyte[2]==0x40) //再次判断按键按下
{
while(!key_2||irbyte[2]==0x40) //等待按键释放
{
qing();
deal_with();
}
led_2=0; //对应指示灯
state=3; //跳转将全旗流程节点
sys_state=3; //置为系统当前状态
}
}
if((!key_3||irbyte[2]==0x07)&&sys_state==0) //如果升半旗按键按下(按键以及红外遥控)并旗帜处于最低部
{
delay_uint(1000);//延时去抖
if(!key_3||irbyte[2]==0x07) //再次判断按键按下
{
while(!key_3||irbyte[2]==0x07) //等待按键释放
{
qing();
deal_with();
}
led_3=0; //对应指示灯
state=5; //跳转升半旗流程节点
sys_state=3; //置为系统当前状态
}
}
if((!key_4||irbyte[2]==0x15)&&sys_state==2) //如果半旗降下按键按下(按键以及红外遥控)并旗帜处于最半旗状态
{
delay_uint(1000); //延时去抖
if(!key_4||irbyte[2]==0x15) //再次判断按键按下
{
while(!key_4||irbyte[2]==0x15) //等待按键释放
{
qing();
deal_with();
}
state=8; //跳转半旗将下流程节点
led_4=0; //对应指示灯
sys_state=3; //置为系统当前状态
}
}
if(!key_5||irbyte[2]==0x43) //复位按键复发
{
delay_uint(1000); //延时去抖
if(!key_5||irbyte[2]==0x43) //再次判断按键按下
{
while(!key_5||irbyte[2]==0x43) //等待按键释放
{
qing();
deal_with();
}
state=11; //跳转旗帜返回最低端节点
sys_state=3; //置为系统当前状态
led_1=led_2=led_3=led_4=1; //对应指示灯
}
}
if(!key_6||irbyte[2]==0x09) //复位按键复发
{
delay_uint(1000); //延时去抖
if(!key_6||irbyte[2]==0x09) //再次判断按键按下
{
while(!key_6||irbyte[2]==0x09)
{
qing();
deal_with();
}
Send_threelines(1);//停止语音播报
state=0;
sys_state=4; //停止当前旗帜动作
Below_dat=0;
UP_dat=0;
led_1=led_2=led_3=led_4=1; //取消指示灯
}
}
}
//sys_state=0 为 旗低的状态
//sys_state=1 为 旗顶的状态
//sys_state=2 为 半旗的状态
//sys_state=3 为 正在运行的一个状态
//uint UP_dat=0,Below_dat=0;
void Control_code(void)
{
switch(state)
{
case 0: //停止转动
P2 &= 0xf0;
P2 |= 0x00;
break;
case 1: //升全旗 并播音
Send_threelines(0);
UP_dat=8800;
state=2;
break;
case 2: //判断是否升到最顶端
if(UP_dat==0)
{
state=0;
sys_state=1;
led_1=1;
Current_dat=8800;
}
break;
case 3: //将全旗
Below_dat=8800;
state=4;
break;
case 4: //判断是否将到最低端
if(Below_dat==0)
{
state=0;
sys_state=0;
led_2=1;
Current_dat=0;
}
break;
case 5: //升全旗 并播音
Send_threelines(0);
UP_dat=8800;
state=6;
break;
case 6: //判断是否升到最顶端 并降半旗
if(UP_dat==0)
{
Below_dat=2933;
state=7;
}
break;
case 7: //判断是否将到半旗状态
if(Below_dat==0)
{
state=0;
sys_state=2;
led_3=1;
Current_dat=8800-2933;
}
break;
case 8: //升半旗
UP_dat=2933;
state=9;
break;
case 9: //判断是否上升完成 并降全旗
if(UP_dat==0)
{
Below_dat=8800;
state=10;
}
break;
case 10: //判断是否将到最低端
if(Below_dat==0)
{
state=0;
sys_state=0;
led_4=1;
Current_dat=0;
}
break;
case 11: //停止语音播报 并将旗帜降到最低端
Send_threelines(1);
UP_dat=0;
Below_dat=Current_dat;
state=12;
break;
case 12: //判断是否将到最低端
if(Below_dat==0)
{
state=0;
sys_state=0;
}
break;
}
Current_Height=Current_dat/62.8; //当前旗帜高度计算
if(Current_Height>140) Current_Height=140;
if(dat_A!=Current_Height) //如果显示的旗帜高度不等于实际高度 从新赋值并保存
{
dat_A=Current_Height;
SectorErase(0x2000); //保存当前报读
byte_write(0x2000,Current_Height);
}
}
void Time_init(void) //定时器初始化配置
{
TMOD = 0x20;
TH1 = 0x00;
TL1 = 0x00;
ET1 = 1;
TR1 = 1;
}
void main(void) //系统主程序
{
Time_init(); // 调用定时器初始化配置程序
EA=1; //打开总中断
EX0=1; //打开外部中断0
IT0=1; //配置触发方式
delay_uint(20000); // 系统等待延时
Current_Height=byte_read(0x2000); //读取EEPROM中存储的数据
if(Current_Height>140) Current_Height=0; //如果当前高度数据不正确则重新赋值
if(Current_Height==0) sys_state=0; //判读当前系统工作模式
else if(Current_Height==140)sys_state=1;
else if(Current_Height>90&&Current_dat<100) sys_state=2;
else sys_state=4;
Current_dat=Current_Height*62.8; //高度计算
if(Current_dat>8800) Current_dat=8800;
LCD1602_cls(); //液晶屏初始化程序调用
show_init(); //显示内容初始化调用程序
while(1)
{
show(); //显示函数
key_code(); //按键处理函数
Control_code(); //系统控制函数
}
}
void Time_2() interrupt 3
{
irtime++;
speed_dat++;
if(speed_dat>17) //8600-8800 旗杆走一杆110mm
{
speed_dat=0;
if(UP_dat!=0)
{
P2 &= 0xf0;
P2 |= zz[circulation]; //步进电机控制
circulation=(circulation+1)%8;
UP_dat--;
if(Current_dat<8800) Current_dat++;
}
if(Below_dat!=0)
{
P2 &= 0xf0;
P2 |= fz[circulation]; //步进电机控制
circulation=(circulation+1)%8;
Below_dat--;
if(Current_dat!=0) Current_dat--;
}
}
}
void int0() interrupt 0 //外部中断0 中断程序 用于接收红外数据信号
{
if(irflag==1)
{
if(irtime>32) //判断起始信号
{
bitnum=0;
}
irdate[bitnum]=irtime;
irtime=0;
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
1-程序.rar
(46.23 KB, 下载次数: 23)
2018-5-9 20:23 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1