本系統(tǒng)采用單片機+LCD1602液晶+語音模塊+ULN2003驅(qū)動芯片+5線4相步進電機+按鍵模塊+遙控器模塊設(shè)計而成。
按鍵說明:
從左邊第一個起,升旗鍵、降旗鍵、停止鍵。
1. 單片機型號:STC89C52/51、AT89C52/51、AT89S52/51 可任選。
2.按下上升按鍵后,旗幟勻速上升,同時流暢地演奏歌。
3.上升到最高端時自動停止上升,歌停奏。
4.按下下降按鍵后,旗幟勻速下降,降旗的時間不放歌曲,下降到最低端時自動停止。
5.為避免誤動作,旗幟在最高端時,按上升鍵不起作用;旗幟在最低端時,按下降鍵不起作用。
6.液晶第二行數(shù)字即時顯示旗幟所在的高度。
7.可以通過遙控器控制旗幟升降和停止。
8.有旗幟升降和停止指示燈。
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
0.png (43.33 KB, 下載次數(shù): 38)
下載附件
2018-7-30 16:22 上傳
0.png (38.18 KB, 下載次數(shù): 32)
下載附件
2018-7-30 16:22 上傳
元件清單
元件標號 元件名稱 數(shù)量
C1 10uf電解電容 1
C2, C3 30pf瓷片電容 2
C4 100uf電解電容 1
C6 470uf電解電容 1
D1, D2 IN4007二極管 2
IR1 1838紅外一體接收頭+紅外遙控 1
J1 電源接口 1
"K1, K2, K3, K4, K5, K6,
K7
" 輕觸按鍵 7
L1, L2, L3, L4 3mm紅色led燈 4
P1 LCD1602液晶顯示屏+16P插座 1
P2 4針排針 1
P4 排針+步進電機+旗桿 1
PR1 103排阻 1
R1 3K電阻 1
R2, R9 10K電阻 2
R3, R4 1K電阻 2
SP1 喇叭 1
SW1 自鎖開關(guān) 1
U1 STC89C52單片機+DIP40插座 1
U2 WT588D -16語音模塊+2*8P 圓頭插座 1
U3 ULN2003芯片+DIP16插座 1
Y1 12M晶振 1
單片機源程序如下:
- #include <reg52.h> //調(diào)用單片機頭文件
- #define uchar unsigned char //無符路字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無符路整型 宏定義 變量范圍0~65535
- #include "eeprom52.h" //單片機存儲控制程序調(diào)用
- #include "LCD1602.h" //LCD1602控制顯示程序調(diào)用
- 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; //系統(tǒng)指示燈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}; //步進電機正轉(zhuǎn)動數(shù)據(jù)數(shù)組
- uchar code fz[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//步進電機反轉(zhuǎn)動數(shù)據(jù)數(shù)組
- uint UP_dat=0,Below_dat=0,Current_dat=0;
- //上移動的角度數(shù)據(jù)變量,下移動的角度數(shù)據(jù)變量,當前位置數(shù)據(jù)變量
- uchar Current_Height=0,circulation,speed_dat,dat_A;
- //當前旗幟的高度數(shù)據(jù)變量,步進電機循環(huán)控制變量,轉(zhuǎn)動速度控制變量,顯示當前高度變量
- uchar sys_state,state;
- //系統(tǒng)狀態(tài)變量 ,工作流程控制變量
- uchar irbyte[4];
- //分析紅外數(shù)據(jù)存數(shù)的32位數(shù)據(jù);
- uchar irtime,irflag,bitnum,irdateok;
- //脈沖周期計時便利阿尼哥,分析數(shù)據(jù)標志位,數(shù)據(jù)存入數(shù)組下標變量 ,數(shù)據(jù)接受完成標志位
- uchar irdate[33];
- //紅外信號的數(shù)據(jù)存儲數(shù)組
- /***********************小延時函數(shù)**************************/
- void delay_us (unsigned int us)
- {
- while(us--)
- {
- _nop_();
- }
- }
- /********************************************************************
- * 名稱 : delay_1ms()
- * 功能 : 延時1ms函數(shù)
- * 輸入 : q
- * 輸出 : 無
- ***********************************************************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<115;j++);
- }
-
-
- /************ 延時函數(shù) *****************/
- void delay_uint(uint z)
- {
- while(z--);
- }
- /***************清楚紅外信號暫存數(shù)組中的數(shù)據(jù)******************/
- void qing(void)
- {
- uint i;
- for(i=0;i<33;i++)
- {
- irdate[i]=0;
- }
- }
- /****************分析紅外信號32位數(shù)據(jù)***************/
- void deal_with(void)
- {
- uchar i,j,k,temp;
- k=1;
- for(j=0;j<4;j++)
- {
- for(i=0;i<8;i++) //每8位數(shù)據(jù)切換一個數(shù)組單元
- {
- temp=temp>>1;
- if(irdate[k]>7) //根據(jù)脈沖周期的時長判斷紅外數(shù)據(jù)
- {
- temp=temp|0x80;
- }
- k++;
- }
- irbyte[j]=temp;
- }
- }
- /***********************三線發(fā)碼子程序************************/
- 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);
- }
- /***************液晶初始化顯示函數(shù)**************/
- 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) //系統(tǒng)循環(huán)顯示函數(shù)
- {
- 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 為 旗低的狀態(tài)
- //sys_state=1 為 旗頂?shù)臓顟B(tài)
- //sys_state=2 為 半旗的狀態(tài)
- //sys_state=3 為 正在運行的一個狀態(tài)
- //sys_state=4 為 停止的一個狀態(tài)
- void key_code(void) //系統(tǒng)按鍵檢測控制程序
- {
- if(irdateok==1) //如果紅外信號接收完成標志位觸發(fā) 則
- {
- irdateok=0;
- deal_with(); //分析紅外數(shù)據(jù)
- }
- 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; //跳轉(zhuǎn)升全旗流程節(jié)點
- sys_state=3; //置為系統(tǒng)當前狀態(tài)
- led_1=0; //對應(yīng)指示燈
- }
- }
- 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; //對應(yīng)指示燈
- state=3; //跳轉(zhuǎn)將全旗流程節(jié)點
- sys_state=3; //置為系統(tǒng)當前狀態(tài)
- }
- }
- 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; //對應(yīng)指示燈
- state=5; //跳轉(zhuǎn)升半旗流程節(jié)點
- sys_state=3; //置為系統(tǒng)當前狀態(tài)
- }
- }
- if((!key_4||irbyte[2]==0x15)&&sys_state==2) //如果半旗降下按鍵按下(按鍵以及紅外遙控)并旗幟處于最半旗狀態(tài)
- {
- delay_uint(1000); //延時去抖
- if(!key_4||irbyte[2]==0x15) //再次判斷按鍵按下
- {
- while(!key_4||irbyte[2]==0x15) //等待按鍵釋放
- {
- qing();
- deal_with();
- }
- state=8; //跳轉(zhuǎn)半旗將下流程節(jié)點
- led_4=0; //對應(yīng)指示燈
- sys_state=3; //置為系統(tǒng)當前狀態(tài)
- }
- }
- if(!key_5||irbyte[2]==0x43) //復(fù)位按鍵復(fù)發(fā)
- {
- delay_uint(1000); //延時去抖
- if(!key_5||irbyte[2]==0x43) //再次判斷按鍵按下
- {
- while(!key_5||irbyte[2]==0x43) //等待按鍵釋放
- {
- qing();
- deal_with();
- }
- state=11; //跳轉(zhuǎn)旗幟返回最低端節(jié)點
- sys_state=3; //置為系統(tǒng)當前狀態(tài)
- led_1=led_2=led_3=led_4=1; //對應(yīng)指示燈
- }
- }
- if(!key_6||irbyte[2]==0x09) //復(fù)位按鍵復(fù)發(fā)
- {
- 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 為 旗低的狀態(tài)
- //sys_state=1 為 旗頂?shù)臓顟B(tài)
- //sys_state=2 為 半旗的狀態(tài)
- //sys_state=3 為 正在運行的一個狀態(tài)
- //uint UP_dat=0,Below_dat=0;
- void Control_code(void)
- {
- switch(state)
- {
- case 0: //停止轉(zhuǎn)動
- 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: //判斷是否將到半旗狀態(tài)
- 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) //系統(tǒng)主程序
- {
- Time_init(); // 調(diào)用定時器初始化配置程序
- EA=1; //打開總中斷
- EX0=1; //打開外部中斷0
- IT0=1; //配置觸發(fā)方式
- delay_uint(20000); // 系統(tǒng)等待延時
- Current_Height=byte_read(0x2000); //讀取EEPROM中存儲的數(shù)據(jù)
- if(Current_Height>140) Current_Height=0; //如果當前高度數(shù)據(jù)不正確則重新賦值
- if(Current_Height==0) sys_state=0; //判讀當前系統(tǒng)工作模式
- 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(); //液晶屏初始化程序調(diào)用
- show_init(); //顯示內(nèi)容初始化調(diào)用程序
- while(1)
- {
- show(); //顯示函數(shù)
- key_code(); //按鍵處理函數(shù)
- Control_code(); //系統(tǒng)控制函數(shù)
- }
- }
- 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 中斷程序 用于接收紅外數(shù)據(jù)信號
- {
- if(irflag==1)
- {
- if(irtime>32) //判斷起始信號
- {
- bitnum=0;
- }
- irdate[bitnum]=irtime;
- irtime=0;
- bitnum++;
- if(bitnum==33) //連續(xù)接收32為數(shù)據(jù) 則為一組數(shù)據(jù)接收完成
- {
- bitnum=0;
- irdateok=1; //觸發(fā)接收完成標志位
- }
- }
- else
- {
- irflag=1;
- irtime=0;
- }
- }
復(fù)制代碼
0.png (46.93 KB, 下載次數(shù): 29)
下載附件
2018-7-30 16:24 上傳
所有資料51hei提供下載:
51單片機自動升國旗完整資料.rar
(3.46 MB, 下載次數(shù): 111)
2018-7-30 15:31 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|