自动控制升降旗系统 程序
单片机源程序如下:
- #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)
|