0.png (58.22 KB, 下載次數: 64)
下載附件
2017-5-1 16:31 上傳
- /********************************************************************
- * 文件名 : 簡易風洞程序
- * 描述 :
- * 創建人 : 王東表哥 2014年8月14日
- * 版本號 : 2.0
- ***********************************************************************/
- #include<STC12C5A60S2.h>
- #include <string.h>
- #include <stdio.h>
- #include <math.h>
- #include<absacc.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define KSP 0.18 // 比例 0.18
- #define KSI 0.0045 // 積分 0.0045
- #define KSD 0.0001 // 微分 0.0001
- #define KSP1 0.14 // 比例
- #define KSI1 0.0018 // 積分
- #define KSD1 0.0001 // 微分
- uchar code IC_DAT[];
- uchar code pic1[];
- uchar code pic2[];
- uchar code pic3[];
- uint size=0; //位置
- uint sizechange,changesize=150; //高度變化停止用
- uint displaytime; //定義屏幕刷新時間
- uint Timetime; //計時
- uint RTimetime; //響應
- uint MTimetime; //保持
- uint ZTimetime; //總時間
- uint Beep1stime; //蜂鳴器1s定時時間
- uchar flagchangeStar; //任務變化標志位
- uchar shuzi;
- uchar code IC_DAT[]={
- "任務要求: "
- "響應時間: s"
- "小球位置: mm"
- "保持時間: s"
- };
- sbit RS = P1^4;
- sbit WRD = P1^5;
- sbit E = P1^6;
- sbit RES = P1^7;
- sbit RX = P3^7;
- sbit TX = P3^6;
- sbit BEEP = P3^5;
- uchar key,keysign,beeptime;
- bit flag =0;
- uchar flagStart=0; //啟動標志位
- uchar flagStart7=0; //啟動標志位7
- uchar flagStart6=0; //啟動標志位7
- uchar flagSep=0; //任務要求標志位
- uchar pidchang=0; //任務要求標志位
- uchar flagStart60=0; //任務6要求標志位
- uchar flagStart61=0; //任務6要求標志位1
- uchar beepchange1;
- uint time=0;
- int pwm=255;
- uint S=0,S1;
- void TransferData(char data1,bit DI);
- void display(void);
- void display_grapic(void);
- void delayms(uint n);
- void DisplayLine(uchar line1,uchar line2);
- void DisplayGraphic(uchar code *adder);
- void delay(uint m);
- void lcd_mesg(uchar code *adder1);
- void delay25us(void);
- /*====================================================================================================
- PID Function
- The PID (比例、積分、微分) function is used in mainly
- control applications. PIDCalc performs one iteration of the PID
- algorithm.
- While the PID function works, main is just a dummy program showing
- a typical usage.
- 以下為PID參數定義
- =====================================================================================================*/
- typedef struct PID {
- float SetPoint; // 設定目標 Desired Value(期望值)
- float Proportion; // 比例常數 Proportional Const
- float Integral; // 積分常數 Integral Const
- float Derivative; // 微分常數 Derivative Const
- float LastError; // Error[-1] 最后一個誤差
- float PrevError; // Error[-2]
- float SumError; // Sums of Errors 總誤差
- }PID ;
- /*====================================================================================================
- PID計算部分
- =====================================================================================================*/
- float PIDCalc( PID *pp, float NextPoint )
- {
- float dError,
- Error,
- DUTY;
- Error = pp->SetPoint - NextPoint; // 偏差 設定 - 下一點
- pp->SumError += Error; // 積分 誤差和
- dError = pp->LastError - pp->PrevError; // 當前微分 上一個 - 上上個
- pp->PrevError = pp->LastError; //移位 上一個》上上個
- pp->LastError = Error; //移位 上上個》誤差
- DUTY=
- ( pp->Proportion * Error // 比例項 比例*誤差
- + pp->Integral * pp->SumError // 積分項 積分*誤差和
- + pp->Derivative * dError // 微分項 微分*誤差變化
- );
- if(DUTY>255){DUTY=255;}
- if(DUTY<-255){DUTY=-255;}
- return DUTY;
- }
- /*====================================================================================================
- Initialize PID Structure
- =====================================================================================================*/
- void PIDInit (PID *pp)//將PID各個參數初始化為0
- {
- memset ( pp,0,sizeof(PID)); //MEM組
- }
- /*====================================================================================================
- Main Program
- =====================================================================================================*/
- float sensor (void) // Dummy Sensor Function 虛擬傳感器功能
- {
- while(!S);
- return (float)S; //(S/255.0)*5.0;
- }
- void actuator(float rDelta) // Dummy Actuator Function 虛擬致動器的功能
- {
- pwm=rDelta; //(rDelta/5.0)*255;
- if(pwm<0){pwm=0;} //高
- if(pwm>255) pwm=255; //低
- pwm=255-pwm;
- }
- /********************************************************************
- * 名稱 : 計數器 設T0為方式1,GATE=1
- * 功能 :
- * 輸入 :
- * 輸出 :
- ***********************************************************************/
- void InitTimer0(void)
- {
- TMOD = 0x11;
- TH0 = 0x10;
- TL0 = 0x00;
- TR0 = 1;
- }
- /********************************************************************
- * 名稱 : T0中斷用來計數器溢出,超過測距范圍
- * 功能 :
- * 輸入 :
- * 輸出 :
- ***********************************************************************/
- void Timer0Interrupt(void) interrupt 1 //T0中斷用來計數器溢出,超過測距范圍
- {
- flag=1; //中斷溢出標志
- }
- void StartModule() //啟動發射
- {
- TX=1;
- delay25us();
- TX=0;
- }
- /********************************************************************
- * 名稱 : Convert(uchar In_Date)
- * 功能 : 因為電路設計時,P0.0--P0.7接法剛好了資料中的相反,所以設計該函數。
- * 輸入 : 12864資料上的值
- * 輸出 : 送
- ***********************************************************************/
- unsigned char Convert(unsigned char In_Date)
- {
- unsigned char i, Out_Date = 0, temp = 0;
- for(i=0; i<8; i++)
- {
- temp = (In_Date >> i) & 0x01;
- Out_Date |= (temp << (7 - i));
- }
- return Out_Date;
- }
- /********************************************************************
- * 名稱 : LCD字庫初始化程序
- * 功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void initinal(void) //LCD字庫初始化程序
- {
- delay(40); //大于40MS的延時程序
- // PSB=1; //設置為8BIT并口工作模式
- delay(1); //延時
- RES=0; //復位
- delay(1); //延時
- RES=1; //復位置高
- delay(10);
- TransferData(0x30,0); //Extended Function Set :8BIT設置,RE=0: basic instruction set, G=0 :graphic display OFF
- delay(100); //大于100uS的延時程序
- TransferData(0x30,0); //Function Set
- delay(37); ////大于37uS的延時程序
- TransferData(0x08,0); //Display on Control
- delay(100); //大于100uS的延時程序
- TransferData(0x10,0); //Cursor Display Control光標設置
- delay(100); //大于100uS的延時程序
- TransferData(0x0C,0); //Display Control,D=1,顯示開
- delay(100); //大于100uS的延時程序
- TransferData(0x01,0); //Display Clear
- delay(10); //大于10mS的延時程序
- TransferData(0x06,0); //Enry Mode Set,光標從右向左加1位移動
- delay(100); //大于100uS的延時程序
- }
- /********************************************************************
- * 名稱 : 顯示文字
- * 功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void lcd_mesg(unsigned char code *adder1)
- {
- unsigned char i;
- TransferData(0x80,0); //設置圖形顯示內存addressset圖形顯示內存地址
- delay(100);
- for(i=0;i<32;i++)
- {
- TransferData(*adder1,1);
- adder1++;
- }
- TransferData(0x90,0); //設置圖形顯示內存地址
- delay(100);
- for(i=32;i<64;i++)
- {
- TransferData(*adder1,1);
- adder1++;
- }
- }
- /********************************************************************
- * 名稱 : 傳送數據或者命令
- * 功能 :
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void TransferData(char data1,bit DI) //傳送數據或者命令,當DI=0時,傳送命令,當DI=1時,傳送數據.
- {
- WRD=0;
- RS=DI;
- delay(1);
- P0=Convert(data1);
- E=1;
- delay(1);
- E=0;
- }
- void Conut(void)
- {
- time=TH0*256+TL0;
- TH0=0;
- TL0=0;
- S=time*0.179; //算出來是CM 11。0592M晶振
- if(flag==1) //超出測量
- {
- flag=0;
- }
- else
- {
- if(S>480) S1=0;
- else S1=480-S;
-
- }
- }
- void Distance(void)
- {
- StartModule(); //計算
- while(!RX); //當RX為零時等待
- TR0=1; //開啟計數
- while(RX); //當RX為1計數并等待
- TR0=0; //關閉計數
- Conut();
- }
- /********************************************************************
- * 名稱 : 毫秒延時
- * 功能 :
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void delayms(unsigned int xms) //延時xms毫秒
- {
- unsigned int i,j;
- for(i=xms;i>0;i--)
- for(j=1320;j>0;j--);
- }
- /********************************************************************
- * 名稱 : 10us延時程序
- * 功能 :
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void delay(unsigned int m) //延時程序
- {
- unsigned int i,j;
- for(i=0;i<m;i++)
- for(j=0;j<13;j++);
- }
- /********************************************************************
- * 名稱 : 25us延時程序
- * 功能 :
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void delay25us(void) //延時25us誤差 0us
- {
- unsigned char a,b;
- for(b=33;b>0;b--)
- for(a=3;a>0;a--);
- }
- void InitTimer1(void) //定時器初始化
- {
- TMOD = 0x11;
- TH1 = 0x0EC;
- TL1 = 0x78;
- EA = 1;
- ET1 = 1;
- TR1 = 1;
- }
-
- void Timer1Interrupt(void) interrupt 3
- {
- TH1 = 0x0EC;
- TL1 = 0x78;
- displaytime++;
- Timetime++; //計時
- }
- /********************************************************************
- * 名稱 : 顯示圖形
- * 功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void DisplayGraphic(unsigned char code *adder)
- {
- int i,j;
- //顯示上半屏內容設置
- for(i=0;i<32;i++)
- {
- TransferData((0x80 + i),0); //SET 垂直地址 VERTICAL ADD
- TransferData(0x80,0); //SET 水平地址 HORIZONTAL ADD
- for(j=0;j<16;j++)
- {
- TransferData(*adder,1);
- adder++;
- }
- }
- //顯示下半屏內容設置
- for(i=0;i<32;i++)
- {
- TransferData((0x80 + i),0); //SET 垂直地址 VERTICAL ADD
- TransferData(0x88,0); //SET 水平地址 HORIZONTAL ADD
- for(j=0;j<16;j++)
- {
- TransferData(*adder,1);
- adder++;
- }
- }
- }
- /*******************************************************************/
- /* */
- /* 矩陣鍵盤掃描 */
- /* */
- /*******************************************************************/
- uchar keyscan(void)//鍵盤掃描函數,使用行列反轉掃描法 比如:行為低電位,列為高四位
- {
- uchar cord_h,cord_l;//行列值
- P2=0x0f;//行線輸出全為0
- cord_h=P2&0x0f;//讀入列線值
- if(cord_h!=0x0f) //先檢測有無按鍵按下
- {
- delay(1); //去抖
- if(cord_h!=0x0f)
- {
- cord_h=P2&0x0f; //讀入列線值
- P2=cord_h|0xf0; //輸出當前列線值
- cord_l=P2&0xf0; //讀入行線值
- return(cord_h+cord_l);//鍵盤最后組合碼值
- }
- }
- else return(0xff);//返回該值
- }
- /**********************************************************/
- void beep()
- {
- uchar i;
- for (i=0;i<100;i++)
- {
- delay(10);
- BEEP=!BEEP; //BEEP取反
- }
- BEEP=1; //關閉蜂鳴器
- }
- void beepchange() //變音蜂鳴器
- {
- uchar i;
- for (i=0;i<(20-beeptime)*10;i++)
- {
- delay((beeptime+2)*3);
- BEEP=!BEEP; //BEEP取反
- }
- BEEP=1; //關閉蜂鳴器
-
- }
- /********************************************************************
- * 名稱 : Main()
- * 功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void main(void)
- {
- PID sPID; // PID Control Structure PID控制結構
- float rOut; // PID Response (Output) PID控制器的響應(輸出)
- float rIn; // PID Feedback (Input) PID反饋(輸入)
-
- PIDInit ( &sPID ); // Initialize Structure
- if(pidchang==0) // 準
- {
- sPID.Proportion = KSP; // Set PID Coefficients 比例
- sPID.Integral = KSI; // 積分
- sPID.Derivative = KSD; // 微分
- }
- if(pidchang==1) // 穩
- {
- sPID.Proportion = KSP1; // Set PID Coefficients 比例
- sPID.Integral = KSI1; // 積分
- sPID.Derivative = KSD1; // 微分
- }
- sPID.SetPoint = size; // Set PID Setpoint 設定值
- P4SW = 0x70;
- initina2(); //調用LCD顯示圖片(擴展)初始化程序
- beep();
- beep();
- delayms(200);
- initinal(); //調用LCD字庫初始化程序
- delay(100); //大于100uS的延時程序
- lcd_mesg(IC_DAT); //顯示中文漢字1
- InitTimer0(); //計時器
- InitTimer1(); //中斷初始化
- CCON = 0; //主控制寄存器的初始
- //PCA timer 停止運行
- //清除CF標志
- //清除所有中斷標志模塊
- CL = 0; //復位 PCA base timer
- CH = 0;
- CMOD = 0x02; //設置 PCA timer 時鐘源在 Fosc/2
- //禁用PCA timer溢出中斷
- CCAP0H = CCAP0L = 0xff; //pwm0端口輸出的50%占空比的矩形波
- CCAPM0 = 0x42; //PCA模塊工作在8位PWM模式 禁止PCA中斷
- CCAP1H = CCAP1L = 0xff; //PWM1輸出端口0方波的占空比
- CCAPM1 = 0x42; //PCA模塊工作在8位PWM模式 禁止PCA中斷
- CR = 1; //PCA timer 啟動運行
- beep();
- beep();
- while(1)
- {
-
- sPID.SetPoint = 480-size; // Set PID Setpoint 設定值
- Distance();
- delayms(10);
- // CCAP1H = CCAP1L = pwm; //pwm0端口輸出的50%占空比的矩形方波
- CCAP0H = CCAP0L = pwm; //pwm0端口輸出的50%占空比的矩形方波
- key=keyscan();//調用鍵盤掃描,
- switch(key)
- {
- case 235:key=0;break; //0 按下相應的鍵顯示相對應的碼值 原理就是高四位一列低四位一列的組
- //合。0111 1110 7e 0表示按鍵后為0,1表示沒有按鍵按下的。
- //其他類推。
- case 119:key=1;break; //1
- case 123:key=2;break; //2
- case 125:key=3;break; //3
- case 183:key=4;break; //4
- case 187:key=5;break; //5
- case 189:key=6;break; //6
- case 215:key=7;break; //7
- case 219:key=8;break; //8
- case 221:key=9;break; //9
- case 126:key=10;break; //A
- case 190:key=11;break; //B
- case 222:key=12;break; //C
- case 238:key=13;break; //D
- case 231:key=14;break; //*
- case 237:key=15;break; //#
- case 255:key=16;break; //空
- }
- if(key==16)
- {
- if(keysign!=16)
- {
- beeptime=keysign;
- if(beeptime!=14)
- {
- if((flagStart==1)&&(beeptime<=9)) {flagStart=1; beepchange1=1;}
- else beepchange();
- }
- if((flagStart==0)&&(keysign<=9)) {flagSep=keysign; shuzi=keysign;} //任務顯示
- if((flagStart==1)&&(keysign<=9)) { size=200-keysign*10; pidchang=1;} //任務3
- if((shuzi==2)&&(flagSep==1))
- {
- } //任務3
- if(keysign==15)
- {
- ZTimetime=0;
- flagStart=1; //標志位置1
- if(flagSep==1)
- {
- if(flagStart6==0)size=150;
- }//任務1 位置
- if(keysign==5) flagchangeStar=5 ; //任務5 位置
- }
- if(keysign==14) {flagStart=3;beepchange1=0; } //標志位置0 BEEP可以等于0;
- }
-
- }
- keysign=key; //上次的按鍵
- //***任務要求函數等等***
- if((flagStart==1)&&(flagSep==1))
- {
- rIn = sensor (); //把S轉成浮點型 // Read Input 讀取輸入
- rOut = PIDCalc ( &sPID,rIn ); //PID // Perform PID Interation
- actuator ( rOut+pwm ); //占空比 // Effect Needed Changes
- }
- //***取消小球下降函數***
- if(flagStart==3)
- {
- rIn = sensor (); //把S轉成浮點型 // Read Input 讀取輸入
- rOut = PIDCalc ( &sPID,rIn ); //PID // Perform PID Interation
- actuator ( rOut+pwm ); //占空比 // Effect Needed Changes
- size=sizechange+changesize;
- if(S1>=450)
- {
- sizechange=0; //最低點清 0
- flagStart=0;
- BEEP=1;
- pwm=255;
- flagSep=0;
- flagchangeStar=0;
-
- }
- }
- if((flagSep==5)&&(flagStart==1))
- {
- pidchang=1;
- if(S1>100) pwm=95;
- if(S1<150) {flagSep=1;size=1;}
-
-
- }
- /********************************************************************
- * 名稱 : 屏幕數據刷新
- * 功能 :
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- if(displaytime>=100 )
- {
- if(flagStart==3) sizechange=sizechange+40; //下降專用 距離下降 左后停止
- TransferData(0x95,0);
- TransferData(0x17,1); //高度顯示
- TransferData(S1%1000/100+0x30,1);
- TransferData(S1%100/10+0x30,1);
- TransferData(S1%10+0x30,1);
- TransferData(0x8D,0); //響應時間顯示
- TransferData(RTimetime/100%10+0x30,1);
- TransferData(RTimetime%100/10+0x30,1);
- TransferData(0x2E,1);
- TransferData(RTimetime%10+0x30,1);
- TransferData(0x9d,0); //保持時間顯示
- TransferData(MTimetime/100%10+0x30,1);
- TransferData(MTimetime%100/10+0x30,1);
- TransferData(0x2E,1);
- TransferData(MTimetime%10+0x30,1);
- displaytime=0;
- TransferData(0x85,0); //任務要求顯示
- TransferData(0x20,1);
- if(flagStart==1) TransferData(0x11,1);
- else TransferData(0x3C,1);
- TransferData(shuzi+0x30,1);
- if(flagStart==1) TransferData(0x10,1);
- else TransferData(0x3E,1);
- }
-
- if((Timetime>=22)&&(flagStart==1)) //0.1s的保持與采樣時間計算
- {
- ZTimetime++; //總時間
- if((flagSep==5)&&(S1>=100))
- {
- RTimetime=ZTimetime; //響應時間S
- }
- if((size==301)&&(S1<200))
- {
- size=50;
-
- }
-
- if((flagSep==1)&&((110>=S1)|(S1>=190))&&(size==150))
- {
- RTimetime=ZTimetime; //響應時間S
- pidchang=1;
- }
- if((flagSep==1)&&((10>=S1)|(S1>=90))&&(size==50))
- {
- RTimetime=ZTimetime; //響應時間S
- pidchang=1;
- }
- if((flagSep==1)&&((210>=S1)|(S1>=290))&&(size==250))
- {
- RTimetime=ZTimetime; //響應時間S
- pidchang=1;
- }
- else
- {
- Beep1stime++;
- if(Beep1stime>=1) BEEP=1;
- if((Beep1stime>=10)&&(beepchange1!=1)) {BEEP=0;Beep1stime=0; }
- }
- MTimetime=ZTimetime-RTimetime; //保持時間
- Timetime=0;
- if(size==301) MTimetime=0;
- }
- if(flagSep==6)
- {
- flagStart6=1;
- flagSep=1;
- size=301;
- pidchang=0;
- }
-
- if ((MTimetime>=30)&&(flagStart6==1))
- {
- flagStart61++;
- if (flagStart60==0)
- {
- size=250;
- flagStart60=1;
- pidchang=0;
- }
- else
- {
- size=50;
- flagStart60=0;
- pidchang=0;
- }
- MTimetime=0;
- ZTimetime=0;
- RTimetime=0;
- }
- if (flagStart61>=4){pwm=0; flagSep=0;}
-
-
- if(flagSep==7) //要求7功能
- {
-
- if((S1>=2)&&(flagStart7==0)){pwm=0;flagStart7=1;} //啟動標志位
- else
- if(flagStart7==1)
- {
- if (S1>=140) {flagSep=1; size=150;}
- }
- }
-
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
下載:
簡易風洞程序(2).zip
(72.04 KB, 下載次數: 54)
2017-5-1 15:40 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|